Testing Strategy
Layered verification: focused unit/route tests first, browser smoke when a change touches user workflows.
Suites and commands
| Suite | Runner | Command | |---|---|---| | Unit + API route tests | Vitest (src/__tests__) | npm run test:run | | Single file | Vitest | npm run test:run -- src/__tests__/api/example.test.ts | | Component tests | Testing Library + JSDOM | npm run test:run (same suite) | | Coverage | V8 | npm run test:coverage | | Browser E2E | Playwright (e2e/, ~30 specs) | npm run e2e | | Launch workflows / visuals | Playwright | npm run e2e:launch-workflows, npm run e2e:launch-visuals | | Public smoke (prod server) | Playwright | npm run e2e:smoke | | Accessibility | axe-core | npm run e2e:axe, npm run e2e:axe:rooms | | AI evals (deterministic) | Vitest | npm run ai:evals | | Typecheck | tsc + route typegen | npm run typecheck | | Lint + zero-warning budget | ESLint | npm run lint, npm run lint:warning-budget |
vitest.config.ts sets low global coverage floors (large route surface) with 80%-statement scoped gates on lib/auth, lib/billing, lib/cases, lib/ai, proxy.ts, and a 55% gate on lib/redis. Ratchet upward, never down.
Route tests (required per protected route)
Call handlers directly with NextRequest; mock auth + Prisma via src/__tests__/helpers/mocks.ts. Cover: unauthenticated → 401; wrong role → 403; happy path; invalid input; cross-firm access (must miss).
Component tests
Assert user-visible behavior with semantic queries (getByRole), not implementation details. Upload components additionally cover: bad MIME, oversize file, presigned-URL failure, storage PUT failure, success.
E2E
Use Playwright for auth cookies, file selection, redirects, responsive layout, and cross-route navigation. Launch smoke covers auth/onboarding, case CRUD, tasks, document upload/share, reports export, billing shell, portal entry, integration health previews, and the mobile viewport matrix.
Gates and evidence
- Warning budget is zero (
--budget=0); Prisma Babel deopt notes are exempt. verify:launchneeds Node 24 (auto-re-exec viaCASESOLO_VERIFY_NODE_BIN/- When closing a task, record: focused tests passed, typecheck/lint status,
CASESOLO_NODE24_BIN / Homebrew / nvm / Volta); --dry-run --json for non-mutating checks. Full runs only in controlled environments.
warning-budget status, E2E/manual smoke, residual risk.