Rewrite all 11 remaining behavior documents to match the streamlined invoice.md format: - dashboard.md: 250 lines, 62 behaviors - payment.md: 260 lines, behaviors for list, void, check printing, ACH - transaction.md: 310 lines, list, import, admin insights - ledger.md: 519 lines, entries, P&L, balance sheet, cash flows - company.md: 320 lines, profile, 1099s, Plaid/Yodlee, reports - admin.md: 494 lines, clients, accounts, vendors, rules, jobs, history - pos.md: 405 lines, sales, deposits, tenders, refunds, shifts - search-indicators.md: 167 lines, search modal, indicators - auth.md: 184 lines, login, logout, impersonation, sessions - outgoing-invoice.md: 192 lines, create, line items, PDF - legacy-spa.md: 340 lines, all legacy pages (docs only) All documents now use: - Testing Patterns section with reusable abstractions - Numbered tables: # | Behavior | Test Strategy | Status - It should... behavior descriptions - Checkboxes [ ]/[x] for tracking implementation - Cross-Cutting Behaviors for permissions, lock dates, etc. - Test Data Requirements tables - Existing Tests to Preserve sections Total: 3,844 lines of behavior documentation across 12 subsystem docs.
341 lines
20 KiB
Markdown
341 lines
20 KiB
Markdown
# Legacy SPA Behaviors
|
|
|
|
## Overview
|
|
|
|
These pages are rendered client-side via Reagent/Re-frame and use GraphQL for data fetching. They are being migrated to HTMX SSR. **No UI tests should be written for these pages until migrated.**
|
|
|
|
**Testing Philosophy**
|
|
- Prefer unit tests for pure business logic (calculations, validations, transformations)
|
|
- Use integration tests for GraphQL queries, mutations, and data flows
|
|
- Use UI tests only after migration to SSR; until then, mark as "UI (when migrated)"
|
|
- Every behavior must be user-visible; no tests for implementation details
|
|
|
|
---
|
|
|
|
## Testing Patterns
|
|
|
|
### Pattern: GraphQL Data Fetching
|
|
All data fetching uses re-frame `graphql` effect with JWT token from `:user` in app-db:
|
|
1. Queries use `owns-state` to track loading status per page
|
|
2. Results flow through `::data-page/received` event which stores data and syncs URL query params
|
|
3. Filter changes are debounced (800ms) via `dispatch-debounce`
|
|
|
|
**Test implications:** Integration test the GraphQL query resolution and response shape. Do not test the re-frame effect machinery.
|
|
|
|
### Pattern: Re-frame State Management
|
|
- **Data pages**: `data-page` namespace provides reusable pagination/filtering state
|
|
- `::data-page/params` — merged filters + table params + query params
|
|
- `::data-page/data` — GraphQL response data
|
|
- `::data-page/checked` — selected rows for bulk operations
|
|
- **Forms**: `forms` namespace manages edit dialogs with `start-form`, `change-handler`, `save-succeeded`
|
|
- **Status**: `status` namespace tracks async operation states (`:loading`, `:complete`, `:error`)
|
|
|
|
**Test implications:** Test via integration tests that verify the correct data appears after state transitions. Do not test subscription internals.
|
|
|
|
### Pattern: Client-Side Routing
|
|
- Navbar uses Bidi `path-for` with `routes/routes` for legacy SPA links
|
|
- Some navbar items (Payments, POS, Invoices) now link to `ssr-routes/only-routes` instead
|
|
- Page components dispatch `::mounted` on mount and `::unmounted` on unmount
|
|
|
|
**Test implications:** After migration, integration test route redirects from old SPA routes to new SSR routes.
|
|
|
|
---
|
|
|
|
## Home
|
|
|
|
### Dashboard Display
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 1.1 | It should display a dashboard with three chart sections: top expense categories, upcoming bills, and cash flow projection | UI (when migrated) | [ ] |
|
|
| 1.2 | It should load data for the currently selected client on page load | Integration | [ ] |
|
|
| 1.3 | It should display a note: "these reports are for [client]. Please choose a specific customer for their report." when the user has access to multiple clients and has not selected a specific one | UI (when migrated) | [ ] |
|
|
| 1.4 | It should display an interactive bar chart for cash flow projection | UI (when migrated) | [ ] |
|
|
| 1.5 | It should display a table below the cash flow chart showing invoices, upcoming debits, and upcoming credits with days-until due | UI (when migrated) | [ ] |
|
|
| 1.6 | It should allow switching the cash flow range between 7, 30, 60, 90, 120, 150, and 180 days | UI (when migrated) | [ ] |
|
|
| 1.7 | Given the user switches the cash flow range, then the chart and table should update to reflect the selected range | Integration | [ ] |
|
|
| 1.8 | Given the user clicks a cash flow bar, then it should redirect to the unpaid invoices page for that date | UI (when migrated) | [ ] |
|
|
| 1.9 | It should show empty charts gracefully when there is no data for the selected client | UI (when migrated) | [ ] |
|
|
| 1.10 | It should show a loading state while GraphQL data is being fetched | UI (when migrated) | [ ] |
|
|
| 1.11 | It should handle GraphQL errors by showing the loading state appropriately | UI (when migrated) | [ ] |
|
|
|
|
---
|
|
|
|
## Login
|
|
|
|
### Authentication
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 2.1 | It should display a "Login with Google" button on the login page | UI (when migrated) | [ ] |
|
|
| 2.2 | It should link the login button to Google OAuth | UI (when migrated) | [ ] |
|
|
| 2.3 | It should preserve the `redirect-to` query parameter in the Google OAuth URL | Integration | [ ] |
|
|
| 2.4 | It should display a warning notification with the logout reason when the `logout-reason` query parameter is set | UI (when migrated) | [ ] |
|
|
| 2.5 | It should redirect an already authenticated user away from the login page | Integration | [ ] |
|
|
|
|
### Needs Activation
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 2.6 | It should display the message: "Sorry, your user is not activated yet. Please have Ben Skinner enable your account." when the user's account is inactive | UI (when migrated) | [ ] |
|
|
| 2.7 | It should provide a "here" link that clears user state and redirects to the login page | Integration | [ ] |
|
|
|
|
---
|
|
|
|
## Transactions
|
|
|
|
### List Display
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 3.1 | It should display a table of transactions with columns for amount, memo, location, approval status, vendor, accounts, date, and description | UI (when migrated) | [ ] |
|
|
| 3.2 | It should load the transaction list with a default date filter of the last 1 month | Integration | [ ] |
|
|
| 3.3 | It should allow filtering by vendor, account, bank account, date range, amount range, location, import batch, description, and linked status via a sidebar | UI (when migrated) | [ ] |
|
|
| 3.4 | It should debounce sidebar filter changes by 800ms before refreshing data | Integration | [ ] |
|
|
| 3.5 | It should support pagination with start and per-page parameters | Integration | [ ] |
|
|
| 3.6 | It should display checkboxes for row selection when the user is an admin | UI (when migrated) | [ ] |
|
|
| 3.7 | It should not display checkboxes or bulk action buttons for non-admin users | UI (when migrated) | [ ] |
|
|
|
|
### Transaction Edit
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 3.8 | It should open an edit sidebar when the user clicks a transaction row | UI (when migrated) | [ ] |
|
|
| 3.9 | It should allow updating the vendor, approval status, memo, and expense accounts | UI (when migrated) | [ ] |
|
|
| 3.10 | It should validate that the sum of expense account amounts equals the transaction amount | Unit + Integration | [ ] |
|
|
| 3.11 | It should validate that locations are valid for the selected accounts | Unit + Integration | [ ] |
|
|
| 3.12 | It should block editing locked transactions | Integration | [ ] |
|
|
| 3.13 | It should display validation errors inline in the edit form | UI (when migrated) | [ ] |
|
|
|
|
### Bulk Operations (Admin)
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 3.14 | It should allow deleting selected transactions or all visible transactions | Integration | [ ] |
|
|
| 3.15 | It should allow suppressing selected transactions instead of deleting them | Integration | [ ] |
|
|
| 3.16 | It should allow bulk coding by applying vendor, account, approval status, and account rules to multiple transactions | Integration | [ ] |
|
|
| 3.17 | It should allow importing transactions via a manual Yodlee import dialog | Integration | [ ] |
|
|
|
|
### Route Variants
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 3.18 | It should apply the correct default approval status filter for each route variant: all, unapproved, approved, requires-feedback, excluded | Integration | [ ] |
|
|
|
|
---
|
|
|
|
## Ledger
|
|
|
|
### General Ledger
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 4.1 | It should display a table of journal entries with expandable line items | UI (when migrated) | [ ] |
|
|
| 4.2 | It should load the ledger with a default date filter of the last 1 month | Integration | [ ] |
|
|
| 4.3 | It should allow filtering by vendor, account, bank account, date range, amount range, and location via a sidebar | UI (when migrated) | [ ] |
|
|
| 4.4 | It should support virtual pagination controls | Integration | [ ] |
|
|
| 4.5 | It should allow admin users to export filtered results as a CSV download | Integration | [ ] |
|
|
| 4.6 | It should display "Not authorized" for users with the manager role | UI (when migrated) | [ ] |
|
|
|
|
### Profit and Loss
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 4.7 | It should generate a profit and loss report for a single client with a default period | Integration | [ ] |
|
|
| 4.8 | It should allow selecting multiple companies via a multi-select typeahead and generating a combined report | UI (when migrated) | [ ] |
|
|
| 4.9 | It should provide period preset buttons: 13 periods, 12 months, last week, week-to-date, last month, month-to-date, year-to-date, last calendar year, and full year | UI (when migrated) | [ ] |
|
|
| 4.10 | It should populate the correct date ranges when a period preset is selected | Unit | [ ] |
|
|
| 4.11 | It should allow custom period selection via start and end date pickers in advanced mode | UI (when migrated) | [ ] |
|
|
| 4.12 | It should optionally include period-over-period deltas | UI (when migrated) | [ ] |
|
|
| 4.13 | It should optionally break out the report by location, which is mutually exclusive with including deltas | Integration | [ ] |
|
|
| 4.14 | It should allow admin users to generate and download a PDF export | Integration | [ ] |
|
|
| 4.15 | It should provide an email composition link for single-client PDF exports | UI (when migrated) | [ ] |
|
|
| 4.16 | It should open a ledger detail sidebar when the user clicks a report cell | UI (when migrated) | [ ] |
|
|
| 4.17 | It should display "Not authorized" for users with the manager role | UI (when migrated) | [ ] |
|
|
|
|
### Cash Flows
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 4.18 | It should generate a cash flows statement report | Integration | [ ] |
|
|
| 4.19 | It should use the same company, period, delta, and location column controls as the profit and loss report | Integration | [ ] |
|
|
| 4.20 | It should allow admin users to export the report to PDF | Integration | [ ] |
|
|
| 4.21 | It should open a ledger detail sidebar when the user clicks a report cell | UI (when migrated) | [ ] |
|
|
| 4.22 | It should display "Not authorized" for users with the manager role | UI (when migrated) | [ ] |
|
|
|
|
### Profit and Loss Detail
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 4.23 | It should generate a detailed journal entry report with a default 2-week date range | Integration | [ ] |
|
|
| 4.24 | It should group journal entries by category: sales, COGS, payroll, controllable, fixed overhead, and ownership controllable | Integration | [ ] |
|
|
| 4.25 | It should display Gross Profit, Overhead, and Net Profit summaries | UI (when migrated) | [ ] |
|
|
| 4.26 | It should filter journal entries by the selected start and end dates | Integration | [ ] |
|
|
| 4.27 | It should allow admin users to export the report to PDF with an email link for single client | Integration | [ ] |
|
|
| 4.28 | It should display "Not authorized" for users with the manager role | UI (when migrated) | [ ] |
|
|
|
|
### Balance Sheet
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 4.29 | It should generate a balance sheet report as of a specific date | Integration | [ ] |
|
|
| 4.30 | It should allow selecting multiple companies and combining them into a single report | Integration | [ ] |
|
|
| 4.31 | It should optionally include a prior-year comparison with a side-by-side view | UI (when migrated) | [ ] |
|
|
| 4.32 | It should allow admin users to export the report to PDF with an email composition link for single client | Integration | [ ] |
|
|
| 4.33 | It should open ledger entries filtered by account and date range when the user clicks a cell | UI (when migrated) | [ ] |
|
|
| 4.34 | It should display "Not authorized" for users with the manager role | UI (when migrated) | [ ] |
|
|
|
|
### External Ledger
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 4.35 | It should display only externally-imported journal entries with an external_id | Integration | [ ] |
|
|
| 4.36 | It should allow admin users to delete selected entries, with a maximum of 1000 at once | Integration | [ ] |
|
|
| 4.37 | It should allow admin users to export to CSV | Integration | [ ] |
|
|
| 4.38 | It should display "Not authorized" for non-admin users | UI (when migrated) | [ ] |
|
|
|
|
### External Import
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 4.39 | It should allow admin users to paste tab-separated data into a textarea | UI (when migrated) | [ ] |
|
|
| 4.40 | It should provide a checkbox to indicate whether the first row is a header | UI (when migrated) | [ ] |
|
|
| 4.41 | It should parse the pasted data into a table with columns: Id, Client, Source, Vendor, Date, Account, Location, Debit, Credit, Note, and Cleared against | Integration | [ ] |
|
|
| 4.42 | It should validate that the client code exists | Unit + Integration | [ ] |
|
|
| 4.43 | It should validate that the vendor exists | Unit + Integration | [ ] |
|
|
| 4.44 | It should validate that the date is in MM/dd/yyyy format | Unit + Integration | [ ] |
|
|
| 4.45 | It should validate that total debits equal total credits | Unit + Integration | [ ] |
|
|
| 4.46 | It should validate that all amounts are greater than 0 | Unit + Integration | [ ] |
|
|
| 4.47 | It should validate that entries are dated after the client's locked-until date | Integration | [ ] |
|
|
| 4.48 | It should validate that the location belongs to the client or is "A" | Unit + Integration | [ ] |
|
|
| 4.49 | It should validate that the account exists and the location matches the account's required location | Unit + Integration | [ ] |
|
|
| 4.50 | It should display errors per row with a dropdown explanation | UI (when migrated) | [ ] |
|
|
| 4.51 | It should show status icons indicating success, ignored, or existing per row after import | UI (when migrated) | [ ] |
|
|
| 4.52 | It should display the total success count, ignored count, and error count after import | UI (when migrated) | [ ] |
|
|
| 4.53 | It should provide an "Only show errors" filter | UI (when migrated) | [ ] |
|
|
| 4.54 | It should display "Not authorized" for non-admin users | UI (when migrated) | [ ] |
|
|
|
|
---
|
|
|
|
## Payments
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 5.1 | It should be fully migrated to SSR at `/payment/`; the legacy client route exists only for navbar highlighting | N/A | [x] |
|
|
|
|
---
|
|
|
|
## Reports
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 6.1 | It should be fully migrated to SSR at `/company/reports`; the legacy client route exists only for navbar highlighting | N/A | [x] |
|
|
|
|
---
|
|
|
|
## Vendors
|
|
|
|
### Admin Vendor Management
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 7.1 | It should be fully migrated to SSR at `/admin/vendor`; the legacy client route exists only for navbar highlighting | N/A | [x] |
|
|
|
|
### New Vendor Dialog
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 7.2 | It should load the home dashboard with the vendor creation dialog pre-opened when navigating to `/vendor/new` | UI (when migrated) | [ ] |
|
|
| 7.3 | It should only open the vendor dialog if the user has `:vendor :create` permission | Integration | [ ] |
|
|
| 7.4 | It should allow creating a new vendor with name, terms, address, contacts, and default account | UI (when migrated) | [ ] |
|
|
| 7.5 | It should validate that only one terms override exists per client | Unit + Integration | [ ] |
|
|
| 7.6 | It should validate that only one schedule payment DOM override exists per client | Unit + Integration | [ ] |
|
|
| 7.7 | It should validate that only one account override exists per client | Unit + Integration | [ ] |
|
|
|
|
---
|
|
|
|
## Cross-Cutting Behaviors
|
|
|
|
### GraphQL Query Patterns
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 8.1 | It should include the JWT token from the `:user` app-db state in all GraphQL requests | Integration | [ ] |
|
|
| 8.2 | It should track loading status per page using `owns-state` | Integration | [ ] |
|
|
| 8.3 | It should store GraphQL response data and sync URL query params via the `::data-page/received` event | Integration | [ ] |
|
|
| 8.4 | It should debounce filter changes by 800ms before dispatching GraphQL requests | Integration | [ ] |
|
|
|
|
### Re-frame State Management
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 8.5 | It should merge filters, table params, and query params into `::data-page/params` | Integration | [ ] |
|
|
| 8.6 | It should store GraphQL response data in `::data-page/data` | Integration | [ ] |
|
|
| 8.7 | It should track selected rows for bulk operations in `::data-page/checked` | Integration | [ ] |
|
|
| 8.8 | It should manage edit dialog state with `start-form`, `change-handler`, and `save-succeeded` events | Integration | [ ] |
|
|
| 8.9 | It should track async operation states as `:loading`, `:complete`, or `:error` | Integration | [ ] |
|
|
|
|
### Navigation
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 8.10 | It should redirect old SPA routes to new SSR routes after migration | Integration | [ ] |
|
|
| 8.11 | It should set up data subscriptions, forward event listeners, and parameter change watchers on page mount | Integration | [ ] |
|
|
| 8.12 | It should tear down data subscriptions, forward event listeners, and parameter change watchers on page unmount | Integration | [ ] |
|
|
|
|
---
|
|
|
|
## Test Data Requirements
|
|
|
|
| Entity | Requirements |
|
|
|--------|-------------|
|
|
| **Users** | Admin, power-user, manager, user, and read-only roles |
|
|
| **Clients** | Multiple clients with different locations; some with locked-until dates |
|
|
| **Vendors** | With/without default accounts, terms, and autopay settings |
|
|
| **Accounts** | Expense accounts with/without invoice allowance; different locations |
|
|
| **Bank Accounts** | Check, cash, and credit types |
|
|
| **Transactions** | Various approval statuses, dates, amounts, locked/unlocked states |
|
|
| **Journal Entries** | With/without external_id; various categories and accounts |
|
|
| **Invoices** | Various statuses and due dates for cash flow projections |
|
|
|
|
## Existing Tests to Preserve
|
|
|
|
- Test GraphQL query resolution for `HomeDashboard`, `TransactionPage`, `LedgerPage`, `ProfitAndLoss`, `CashFlows`, `JournalDetailReport`, `BalanceSheet`, and `ExternalLedger`
|
|
- Test re-frame event handlers for data page state transitions
|
|
- Test form validation logic for transaction editing and external ledger import
|
|
|
|
## Dependencies
|
|
|
|
- GraphQL API (data fetching)
|
|
- Re-frame/Reagent (client-side state and rendering)
|
|
- Bidi (client-side routing)
|
|
- Recharts (chart rendering on Home page)
|
|
- Server-side PDF generation (P&L, Cash Flows, Balance Sheet, P&L Detail)
|
|
|
|
## Migration Notes
|
|
|
|
### Already Migrated to SSR
|
|
- **Payments** (`/payments/`) - Fully migrated to `/payment/` SSR routes
|
|
- **Reports** (`/reports/`) - Fully migrated to `/company/reports` SSR routes
|
|
- **Admin Vendors** (`/admin/vendors`) - Fully migrated to `/admin/vendor` SSR routes
|
|
|
|
### Still Legacy SPA (prioritized by complexity)
|
|
1. **Transactions** - High complexity (filters, edit form, bulk operations, manual import)
|
|
2. **Home/Dashboard** - Medium complexity (charts, cash flow calculations)
|
|
3. **Ledger** - Medium complexity (filters, CSV export)
|
|
4. **External Ledger** - Low-medium complexity (subset of ledger + delete)
|
|
5. **External Import** - Medium complexity (TSV parsing, validation, batch import)
|
|
6. **Profit and Loss** - High complexity (multi-company, periods, PDF export)
|
|
7. **Cash Flows** - High complexity (shares P&L infrastructure)
|
|
8. **Profit and Loss Detail** - Medium complexity (category filtering, running balances)
|
|
9. **Balance Sheet** - Medium complexity (comparison mode, drill-down)
|
|
10. **Login** - Low complexity (static page)
|
|
11. **Needs Activation** - Low complexity (static page)
|
|
12. **New Vendor** - Low complexity (dialog on home page)
|
|
|
|
### Migration Risks
|
|
- **Chart libraries**: Home page uses Recharts (React). Replacement needed for SSR.
|
|
- **PDF generation**: P&L, Cash Flows, Balance Sheet, P&L Detail all support PDF export via server-side generation.
|
|
- **Bulk operations**: Transactions page has complex bulk coding/deletion with validation.
|
|
- **External import**: TSV parsing and validation logic lives entirely in SPA; server-side equivalent needed.
|