Testing
Two suites, one boundary
| Suite | Files | Scope |
|---|---|---|
| Vitest | **/*.test.ts | pure logic only — no DOM, no Supabase |
| Playwright | e2e/*.spec.ts | full flows against a seeded local Supabase |
The boundary is the point. Unit tests that mock a database client mostly assert that the mock was called, which is why the coverage gate below is credible.
The 100% gate
Vitest enforces 100% lines, branches, functions and statements — but only over
the pure-logic layer (app/utils, server/utils, layers/**/server/utils).
Platform-bound files are excluded, not mocked to hit a number:
exclude: [
'app/utils/download.ts', // browser DOM
'server/utils/requireAdmin.ts', // H3 + Supabase
'layers/email/server/utils/emails.ts', // renders .vue templates
]
A gate that counts fake-mocked platform code reports 100% while testing nothing. This one covers a smaller surface honestly.
Playwright projects
A spec only runs once it's added to a project's testMatch:
- chromium — public smoke, no session
- a11y — axe against every page, in light and dark
- app — authenticated feature flows on the seeded admin session
- isolation — logs in as a second tenant; runs with no saved session
- screenshots — opt-in, see below
Screenshots
pnpm screenshots
Captures every route in both themes at 1920×1080, plus a Pixel 7 mobile pass, into
docs/screenshots/. It's gated behind a SCREENSHOTS env var so a bare
pnpm test:e2e never regenerates PNGs and dirties your working tree.
Not a visual-regression baseline — there's no pixel diffing. It exists so README images and design review keep up with the app instead of aging into fiction.