Skip to content

Testing Strategy

Co-located tests/ per feature. Coverage thresholds: 70% lines / 80% functions.

The 4-layer Vitest model

LayerWhatKey rule
L1Pure functionsNo mocks needed; fast.
L2Hooks/servicesMock supabase + TanStack Query. Assert correct rpc/invoke calls + query keys.
L3Component smokeImport the real component. First test = "mounts without error."
L4Page integrationOptional. 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.ts is standalone — deliberately does NOT merge vite.config.js (keeps the dev-only Horizons/visual-editor plugins out of the runner). It duplicates only resolve.alias/extensions + @vitejs/plugin-react.
  • Setup: src/test/setup.ts (@testing-library/jest-dom/vitest).
  • globals: false → the setup file must register afterEach(cleanup) itself (otherwise render() calls silently accumulate across tests in the same file).
  • .env.test (committed, dummy values) supplies VITE_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 tests

Other layers

LayerToolStatus
Edge FunctionsDeno test:ef✅ live — every EF ships co-located tests/.
SQL / RPCpgTAP test:db🎯 planned — RPC projections don't leak columns; RLS isolation; grants.
E2EPlaywright 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.