test(#39): add coverage thresholds + CI gate for web and api - #40
Conversation
Establishes a ratchet coverage floor on both apps so coverage can't silently erode as the codebase grows (issue #39). - web: add v8 coverage block to vitest.config.ts scoped to app/** source (excludes generated app/api/* + config files); test script runs with --coverage. Floors: lines/statements 88%, branches 90%, functions 60% (baseline ~90% lines). - api: enable Node's --experimental-test-coverage on test:run with --test-coverage-{lines=80,branches=80,functions=90}; excludes test files + src/test/**, source-mapped to .ts (baseline ~85% lines). - Gates ride the existing CI test steps — no new job. - Document thresholds + ratchet-upward intent in .claude/CLAUDE.md. Closes #39
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughThis PR adds test coverage enforcement to web and api applications by configuring coverage thresholds and updating test scripts to fail builds when coverage drops below baseline. Both apps now measure and gate test coverage using their respective test runners (Vitest v8 for web, Node experimental coverage for api), with measured baselines set as ratchet floors. ChangesTest Coverage Gates
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
apps/web/vitest.config.tsESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox. Comment |
G0maa
left a comment
There was a problem hiding this comment.
Code Review: PR #40
Commit: 8728904e38fc0ede44dc74e4931a8a8789e8f05c
Note: GitHub blocks self-approval, so this is posted as a COMMENT review. Code-review verdict is APPROVED (see below); the approval marker has been written for the merge gate.
Summary
Adds ratchet-floor test-coverage gates to both monorepo apps (web via Vitest v8 provider, api via Node's built-in --experimental-test-coverage), riding the existing CI test steps rather than adding a new job. Closes #39. Pure test-infra config — no runtime code.
Checklist Results
- Architecture & Design: Pass (no runtime/domain code touched)
- Code Quality: Pass
- Testing: Pass (this PR is the test-infra change; manual fail-verification documented in body)
- Security: Pass (no auth/secrets/input surface)
- Performance: Pass (gates ride existing steps; no extra CI job)
- PR Description & Glossary: Pass (Glossary present, 5 well-defined terms)
- Summary Bullet Narrative: Pass (every bullet states what + why)
- Technical Decisions (AgDR): N/A (test-infra config; no library/architecture decision — using each app's native coverage tooling, not introducing a new one)
- Adopter Handbooks: N/A (no handbooks loaded for this diff)
Coverage-of-coverage: N/A — this is the coverage configuration itself.
Issues Found
None blocking.
Verification performed
- web exclude globs are correct.
include: ['app/**/*.{ts,vue}']+exclude: ['app/api/**', 'app/**/__tests__/**']correctly excludes the committed-but-generated API client (app/api/{index,types.gen,zod.gen}.ts) and test dirs, while keeping hand-written source (app.vue,pages/,components/,composables/,plugins/). No real source is accidentally excluded.app.config.ts/app.vuestay in scope — correct, they're hand-written and already in the 90.4% baseline. - api exclude globs are correct.
--test-coverage-exclude="**/*.test.ts"is necessary in addition tosrc/test/**because test files live colocated undersrc/modules/**andsrc/entrypoints/**, not only undersrc/test/. Both globs are doing real work. - Ratchet floors are sensible. All floors sit just below measured baseline (web: lines 88 < 90.4, branches 90 < 100, functions 60 < 66.7; api: lines/branches 80, functions 90 vs ~85% lines baseline) so the PR is green while still catching regression. The conservative web functions floor (60) is appropriate for a young suite with few functions where a single uncovered function swings the percentage hard.
- Documentation is accurate.
.claude/CLAUDE.mdgate description matches the actual config values and the never-lower ratchet intent is stated clearly.
Suggestions (non-blocking)
- Consider recording the measured api function-coverage % alongside web's baseline, so a future maintainer raising the api functions floor (currently 90) has the same reference point web has.
CI status
cicheck: IN_PROGRESS at review time (not blocking this verdict — note it must go green before merge per the no-red-CI rule).- CodeRabbit: PENDING.
Verdict
APPROVED (code-review axis)
Floors are well-chosen, exclude globs verified against the actual tree, docs accurate. Merge remains gated on CI going green + explicit per-PR CEO approval.
🤖 Reviewed by Rex (Code Reviewer Agent)
📌 Reviewed commit: 8728904e38fc0ede44dc74e4931a8a8789e8f05c
Summary
Test coverage signal: absentgap from the handover assessment: tooling was installed but nothing prevented coverage from eroding as the codebase grows.apps/web/vitest.config.ts) — added a v8coverageblock scoped to hand-writtenapp/**source (generatedapp/api/*and config files excluded so they don't dilute the number), and switched thetestscript tovitest run --coverage. Floors: lines/statements 88%, branches 90%, functions 60% (measured baseline ~90% lines / 100% branches).apps/apitest:runscript) — enabled Node's built-in--experimental-test-coveragewith--test-coverage-lines=80 --test-coverage-branches=80 --test-coverage-functions=90, excluding test files +src/test/**, source-mapped back to.tsvia the existing--enable-source-maps. Measured baseline ~85% lines..claude/CLAUDE.mdwith the intent to raise (never lower) them over time.Testing
pnpm --filter web test→ runs with coverage; passes at baseline (90.42% lines). Confirmed it fails when a floor is raised above actual (--coverage.thresholds.lines=99→ "Coverage for lines (90.42%) does not meet global threshold (99%)").pnpm --filter api test→ full clean→build→setup→run pipeline against Postgres; passes at baseline (85.51% lines). Confirmed it fails with--test-coverage-lines=99→ "85.51% line coverage does not meet threshold of 99%".pnpm format:check,pnpm lint,pnpm --filter web typecheckall green.Closes #39
Glossary
--experimental-test-coverage--test-coverage-{lines,branches,functions}it enforces thresholds and exits non-zero below them.--enable-source-maps, coverage measured on compileddist/output is reported against the original.tssource lines.Summary by CodeRabbit
Documentation
Tests