Add behavior documentation covering all SSR and legacy SPA pages: - Testing strategy and type definitions (unit/integration/UI) - Dashboard, Invoice, Payment, Transaction, Ledger pages - Company/Settings, POS, Admin, Search, Auth pages - Legacy SPA behavior docs (no UI tests until migrated) - Edge cases, test data requirements, and dependencies per subsystem Total: 3,600+ lines of behavior documentation to guide test authorship.
7.6 KiB
7.6 KiB
Search & Indicators Behaviors
Overview
The Search subsystem provides a global full-text search dialog accessible from the main navigation bar. It queries a Solr index of invoices, payments, transactions, and journal entries, returning results filtered by the user's client permissions. The Indicators subsystem provides small UI utilities like relative date badges (e.g., "5 days ago") used across the application.
Routes & Pages
| Route | Method | Handler | Purpose |
|---|---|---|---|
GET /search |
GET | :search |
Opens the search modal dialog |
POST /search |
POST | :search |
Executes search query, returns results HTML |
GET /days-ago |
GET | ::days-ago |
Returns a relative date badge pill (HTMX) |
Behaviors
Unit Tests
q->solr-qtransforms user query into Solr query string- Bare words become
_text_:"word"clauses joined withAND - Quoted phrases are preserved as single tokens
- Keywords
invoice,payment,transaction,journal-entrymap totype:<value>filters - Dates in
normal-dateformat (e.g.,5/5/2034) are converted to Solr date format - Dates in
iso-dateformat are converted to Solr date format - Unparseable dates pass through unchanged
- Decimal numbers (
123.45) are formatted to 2 decimal places with HALF_UP rounding - Integers pass through unchanged
- Multiple tokens are joined with
AND
- Bare words become
try-cleanse-dateparsesnormal-dateandiso-dateformats, returning Solr-formatted datetry-cleanse-datereturns original string for unparseable inputtry-parse-numberformats decimal strings to exactly 2 decimal placestry-parse-numberreturns non-decimal strings unchangedsearch-resultsfilters Solr results bycan-see-client?against user's allowed clientsdays-ago*returns "N days ago" pill with color:primaryfor < 30 daysdays-ago*returns "N days ago" pill with color:secondaryfor 30-59 daysdays-ago*returns "N days ago" pill with color:yellowfor 60-89 daysdays-ago*returns "N days ago" pill with color:redfor 90+ daysdays-ago*returns "N days from now" pill with color:primaryfor future datesdays-ago*returns empty[:div]for nil date
Integration Tests
GET /searchwith authenticated user returns 200 with search modal HTML- Search modal contains text input with
hx-post="/search",hx-target="#search-results",hx-indicator="#search" - Search input triggers on
keyup changed delay:300msandsearchevents POST /searchwith query parameterqreturns HTML search results- Search results include card for each Solr document with type icon, client code, amount, vendor name, date, and description
- Each result card links to the appropriate detail page (
/invoices,/transactions,/ledger,/payments) withexact-match-idparameter - Results are filtered to only show documents from clients the user can access
GET /searchwithoutqparameter returns modal dialog (not results)POST /searchwithoutqparameter returns modal dialog (not results)GET /days-ago?date=<iso-date>returns colored pill HTML for past datesGET /days-ago?date=<future-date>returns "days from now" pill HTMLGET /days-agowith missing or invalid date returns empty div (schema enforcement)
UI Tests (SSR)
Happy Path: Search and View Result
- Authenticated user clicks search icon in navbar
- Search modal opens with autofocused input and placeholder "5/5/2034 Magheritas"
- User types a query (e.g., "invoice 1000")
- After 300ms debounce, HTMX POSTs to
/search - Results appear below input as cards
- Each card shows: type icon, type name, client code pill, amount pill, vendor pill (if present), date, and description/number
- User clicks external link icon on a result
- Result opens in new tab on the appropriate detail page with
exact-match-idset
Search with Type Filter
- User opens search modal
- User types "payment"
- Results are filtered to only show
type:paymentdocuments - Each result card shows payment icon and links to
/payments/?exact-match-id=<id>
Search with Date
- User opens search modal
- User types "5/5/2034"
- Date is parsed and converted to Solr format
- Results matching that date appear
Empty Search Results
- User opens search modal
- User types a query with no matches
- "No results found." message displays
Days-Ago Indicator
- User views a page containing a
days-agoHTMX element - Element fetches
/days-ago?date=<date> - Colored pill renders showing relative time (e.g., "45 days ago" in secondary color)
Edge Cases
Search
- Special characters in query: Solr special characters are not escaped in user query (relies on phrase wrapping)
- Empty query: Modal renders without results; no Solr query executed
- Very long query: Passes through to Solr; UI handles long text via flex layout
- No accessible clients: Returns empty results even if Solr has matching documents
- Solr unavailable: Behavior depends on
solr/impl(MockSolrClient returns nil/empty) - Mixed type keywords and text: "invoice 1000" produces
type:invoice AND _text_:"1000" - Multiple type keywords: "invoice payment" produces
type:invoice AND type:payment(likely zero results) - Numeric tokens with commas/currency:
$1,000.50passes through as literal text search - Future dates: Date parsing accepts future dates; Solr query includes them
Indicators
- Nil date: Returns empty div, no error
- Invalid date format: Schema enforcement rejects before handler executes
- Same-day date: Returns "0 days ago" with primary color
- Very old dates: Returns "N days ago" with red color (90+ days threshold)
Test Data Requirements
Solr Index
- Indexed documents of all four types:
invoice,payment,transaction,journal-entry - Documents span multiple clients
- Documents with varying dates, amounts, descriptions, numbers, and vendor names
- Documents with and without vendor associations
Users
- Authenticated user with access to subset of clients
- Authenticated user with access to all clients
- Admin user (for full client visibility)
Datomic Entities
- Clients with
:client/codeand:client/name - Invoices with
:invoice/invoice-number,:invoice/total,:invoice/date,:invoice/client,:invoice/vendor - Payments with
:payment/check-number,:payment/amount,:payment/date,:payment/client,:payment/vendor - Transactions with
:transaction/description-original,:transaction/amount,:transaction/date,:transaction/client,:transaction/vendor - Journal entries with
:journal-entry/amount,:journal-entry/date,:journal-entry/client,:journal-entry/vendor,:journal-entry/line-items
Dependencies
External Services
- Solr: Full-text search index (
auto-ap.solr). UsesMockSolrClientin test environments without Solr configured - Datomic: Client visibility checks pull user/client associations
Frontend Libraries
- HTMX: Modal loading, search debounce (
keyup changed delay:300ms), indicator spinner - Alpine.js: Modal card structure
Middleware Stack
wrap-secure: Requires authentication for search and days-ago endpointswrap-client-redirect-unauthenticated: Redirects unauthenticated to/loginwrap-schema-enforce: Validatesdatequery parameter for/days-ago
Related Subsystems
- Invoices: Search results link to invoice detail pages
- Payments: Search results link to payment detail pages
- Transactions: Search results link to transaction detail pages
- Ledger: Search results link to ledger for journal entries