Make the "all frontend code ships with tests" rule mechanical: fail the web CI job when coverage drops below a floor, and ratchet the floor up as screens get covered.
Context
Merged main: 111 SPA tests, overall line 16% / branch 80%. The auth + logic + routing foundation is ~100% (src/auth 100%, lib/dates 100%, api/client.ts 97.6%, Login/ProtectedRoute/StockPage ~100%); the number is held down by ~14 still-untested screen components. So a naive global 80% gate would fail everything — set floors near current levels and raise them over time.
Scope
- Add
@vitest/coverage-v8 as a devDependency (pin to the Vitest 3.2.x line).
coverage config in vite.config.ts test block: provider: 'v8', include: ['src/**/*.{ts,tsx}'], sensible exclude (src/test/** helpers, main.tsx, *.test.*, type-only api/types.ts).
coverage.thresholds — start as a regression floor near current numbers (e.g. global lines/statements ~16, branches ~78), plus per-directory high-water marks that lock in the well-covered areas so they can't backslide:
src/auth/** and src/lib/** → 100 (or autoUpdate-style high floor);
src/api/client.ts → ~95.
- Consider
thresholds.perFile for the covered dirs, and/or 100: true on the auth/lib globs.
- New
test:coverage script; wire it into the web CI job (.github/workflows/ci.yml) so a drop below the floor fails the build. Keep the fast npm run test for local/dev.
- Optional: a short CONTRIBUTING note that new
web/ code needs tests and the gate enforces it; ratchet the global floor up in the same PR that adds each screen's tests.
Non-goals
Tests
- CI fails when a covered file's coverage is deleted/reduced below its threshold; passes at current levels.
Follows the "all frontend code needs tests" rule. Part of #105, epic #14.
Make the "all frontend code ships with tests" rule mechanical: fail the web CI job when coverage drops below a floor, and ratchet the floor up as screens get covered.
Context
Merged main: 111 SPA tests, overall line 16% / branch 80%. The auth + logic + routing foundation is ~100% (
src/auth100%,lib/dates100%,api/client.ts97.6%, Login/ProtectedRoute/StockPage ~100%); the number is held down by ~14 still-untested screen components. So a naive global 80% gate would fail everything — set floors near current levels and raise them over time.Scope
@vitest/coverage-v8as a devDependency (pin to the Vitest 3.2.x line).coverageconfig invite.config.tstest block:provider: 'v8',include: ['src/**/*.{ts,tsx}'], sensibleexclude(src/test/**helpers,main.tsx,*.test.*, type-onlyapi/types.ts).coverage.thresholds— start as a regression floor near current numbers (e.g. globallines/statements~16,branches~78), plus per-directory high-water marks that lock in the well-covered areas so they can't backslide:src/auth/**andsrc/lib/**→ 100 (orautoUpdate-style high floor);src/api/client.ts→ ~95.thresholds.perFilefor the covered dirs, and/or100: trueon the auth/lib globs.test:coveragescript; wire it into the web CI job (.github/workflows/ci.yml) so a drop below the floor fails the build. Keep the fastnpm run testfor local/dev.web/code needs tests and the gate enforces it; ratchet the global floor up in the same PR that adds each screen's tests.Non-goals
Tests
Follows the "all frontend code needs tests" rule. Part of #105, epic #14.