Appearance
Testing Strategy
Co-located tests/ per feature. Coverage thresholds: 70% lines / 80% functions.
The 4-layer Vitest model
| Layer | What | Key rule |
|---|---|---|
| L1 | Pure functions | No mocks needed; fast. |
| L2 | Hooks/services | Mock supabase + TanStack Query. Assert correct rpc/invoke calls + query keys. |
| L3 | Component smoke | Import the real component. First test = "mounts without error." |
| L4 | Page integration | Optional. Plus a compliance test asserting the feature never calls from(). |
The RiEdit3Line lesson: never mock the component under test or its icon imports — a smoke test that mocks the thing it's testing proves nothing. Import the real component and real icons.
Config essentials
vitest.config.tsis standalone — deliberately does NOT mergevite.config.js(keeps the dev-only Horizons/visual-editor plugins out of the runner). It duplicates onlyresolve.alias/extensions+@vitejs/plugin-react.- Setup:
src/test/setup.ts(@testing-library/jest-dom/vitest). globals: false→ the setup file must registerafterEach(cleanup)itself (otherwiserender()calls silently accumulate across tests in the same file)..env.test(committed, dummy values) suppliesVITE_SUPABASE_*so the client doesn't throw.
Commands
bash
npm test # full suite
npm run test:watch # watch mode
npm run test:coverage # coverage (70% lines / 80% functions)
npx vitest run path/to/file.test.tsx # single file
npm run test:ef # Deno edge-function testsOther layers
| Layer | Tool | Status |
|---|---|---|
| Edge Functions | Deno test:ef | ✅ live — every EF ships co-located tests/. |
| SQL / RPC | pgTAP test:db | 🎯 planned — RPC projections don't leak columns; RLS isolation; grants. |
| E2E | Playwright e2e:* | 🎯 planned — ephemeral local Supabase stack (schema snapshot, not migration replay); functions serve as a separate process; mutation guard; deploy-smoke on the real URL. |
What EF tests must cover
Success · validation failure · auth/authz failure · safe 500 (no leakage) · edge cases. Green before deploy. See Adding an Edge Function.