test: raise per-file coverage gate to 90 across all clients (closes #1271)#1532
Conversation
…1271) The web per-file coverage gate had drifted red: the recently-landed EMA auth feature (core/auth/ema/*) and ClientSettings components shipped undertested, and the prior 50% branch floor let business-logic branches go untested. CI does not run the coverage gate, so this accumulated. Add tests to bring every failing file above the gate and push branch coverage well past 70 across the board, then raise the per-file branches threshold 50 -> 70 in clients/web/vite.config.ts. - EMA core (emaFlow, resourceContext, jwt, wire): 50-88% -> 86-100% branch - EMA OIDC/transport (idpOidc, tokenEndpoint, transportProvider): -> 97-100% - oauthManager / discovery: 73-83% -> 88-92% - ClientSettingsModal/Form, ConnectionInfoContent: 0-88% -> 96-100% - useClientSettingsDraft / useEmaIdpLoginState hooks: 20% -> 100% - TaskStatusBadge / SortableServerCard outliers: 50% -> 100% Coverable branches reached by mocking useComputedColorScheme (dark theme), dnd-kit useSortable (isDragging), and fetch/OIDC paths. Remaining sub-100 branches are genuinely-unreachable defensive guards or happy-dom-inherent (portal / useMediaQuery / typeof window) and documented in test comments. No source files changed. Global web branch coverage 88.73% -> 90.63%. AGENTS.md updated; cli/tui/launcher stay at 50 (out of scope). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Follows the #1271 web branch-coverage audit (50 -> 70) by raising the whole per-file gate to >=90 on all four dimensions — lines, statements, functions, branches — for web, cli, tui, and launcher (core/ is measured under the web suite). A codebase-wide audit added real tests for every outlier and brought global coverage up across the board. Config: all four vitest/vite coverage configs set to 90/90/90/90. Two pure-type modules (core/mcp/import/types.ts, clients/web/server/ types.ts) added to the web coverage exclude list, matching the existing type-only exclusions. Tests: ~50 test files extended/created across core (auth, ema, mcp, remote, state, storage, react), web components/screens/server, and the cli/tui clients. Highlights: full EMA OAuth flow + transport coverage, inspectorClient/remote server backfill, every Mantine control's handler branches, and the cli unsupported-method / argv-fallback paths. Genuinely-unreachable branches are annotated at the source with justified `/* v8 ignore -- <reason> */` comments rather than lowering the gate: happy-dom-inherent paths (Mantine portal, useMediaQuery, typeof window SSR guards), React StrictMode effect replay, and provably-dead defensive guards (?? fallbacks the types make impossible, Select.onChange values outside the allowed list). No runtime logic changed; the only structural edits are two behavior-preserving refactors (ResourceTemplatePanel hoists the field value to a local so the ignore applies in JSX; ToolsScreen swaps a ternary for an if) and prettier line-wrapping. Also fixed a flaky real-timer debounce assertion in PromptArgumentsForm (asserted an exact sibling-typing interleaving that raced the 300ms debounce; now asserts the load-bearing fact — a non-empty fire-time sibling capture). AGENTS.md updated to describe the uniform 90 gate and the v8-ignore policy. All four client coverage gates, root validate, storybook (370), and smoke pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Update — scope expanded: raise the whole gate to 90/90/90/90 across all clientsBuilding on the #1271 branch-coverage audit (web branches 50 → 70), a second commit ( What changed
Verification
🤖 Generated with Claude Code |
|
@claude review |
|
Claude finished @cliffhall's task in 1m 35s —— View job Review
I focused on the non-test source changes (the risk surface), the four coverage configs, and a sample of the new tests. The ~50 test files are additive; the only runtime-adjacent edits are two behavior-preserving refactors plus Verdict: 👍 Looks good to mergeThis is a clean, well-disciplined coverage hardening. The gate raise is uniform, the unreachable-branch annotations are individually justified at the source rather than papered over by lowering the gate, and the new tests exercise real branches (rejection paths, debounce cancellation, focus-fire streams) rather than gaming the metric. What I verifiedStructural refactors are behavior-preserving ✅
Coverage configs ✅ — all four (
Flaky fix ✅ — Minor notes (non-blocking)
Nice work — the audit-and-annotate approach (rather than lowering floors) is exactly what the AGENTS.md policy calls for, and the documentation updates keep it self-explaining. |
|
Thanks for the review! Glad the audit-and-annotate approach reads cleanly. Acknowledging the three non-blocking notes — no changes made, but they're noted:
No actionable items, so not re-requesting a review. |
`readSseEvents` looped until the server closed the stream (`done`). The server closes the events stream immediately after writing the terminal `transport_error`, but under the heavy parallel scheduler pressure of a full `coverage` run (v8 instrumentation across all workers) that close can lag far enough behind the event to trip the 30s test timeout — a hang, not a wrong result. This made the test intermittently fail under `npm run coverage` (it passed in isolation and under CI's lighter `test:integration`). Stop reading as soon as the terminal `transport_error` event arrives (cancelling the reader) instead of waiting only for `done`. That event is always the last one the session queue emits, so nothing is lost, and the test no longer depends on stream-close timing. The `done` break is kept for any stream that closes first. Verified green across two consecutive full `npm run test:coverage` runs (3094 tests) where it previously hung, plus isolation (~0.5s). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Addressed finding 3 (the Root cause: Verified green across two consecutive full @claude review |
|
Claude finished @cliffhall's task in 56s —— View job Review — commit
|
|
Thanks for the thorough re-review and for verifying the terminal-event invariant against the source (
No actionable items, so not re-requesting. Finding 3 resolved — thanks! |
Closes #1271.
Summary
This PR hardens the test-coverage gate in two stages, both on this branch:
core/auth/ema/*) and ClientSettings components shipped undertested, and the 50% branch floor let real business-logic branches go untested (CI doesn't run the coverage gate, so it accumulated unnoticed). Every per-file branch outlier was audited and covered.The gate
All four vitest/vite coverage configs now enforce
perFile: 90/90/90/90. Two pure-type modules (core/mcp/import/types.ts,clients/web/server/types.ts) were added to the web exclude list, matching the existing type-only exclusions.Tests added
~50 test files were extended or created, fanned out across parallel agents over disjoint clusters:
inspectorClient.ts+remoteClientTransport.ts+ Hono remoteserver.tsbackfill, messageTrackingTransport, sessionStorage, resolveSource, state reducers, store-io--method+ argv-fallback paths; tui logger + uriTemplateToFormUnreachable branches
Genuinely-unreachable branches are annotated at the source with justified
/* v8 ignore -- <reason> */comments rather than lowering the gate — happy-dom-inherent paths (Mantine portal,useMediaQuery,typeof windowSSR guards), React StrictMode effect replay, and provably-dead defensive guards (?? fallbacks the types make impossible,Select.onChangevalues outside the allowed list).No runtime logic changed. The only structural source edits are two behavior-preserving refactors — ResourceTemplatePanel hoists a field value to a local so a JSX-attribute ignore applies, and ToolsScreen swaps a ternary for an
ifso the dead arm's ignore takes effect — plus prettier line-wrapping. A flaky real-timer debounce assertion inPromptArgumentsFormwas also made deterministic (it asserted an exact sibling-typing interleaving that raced the 300 ms debounce; now asserts the load-bearing fact — a non-empty fire-time sibling capture).Verification
npm run validate(all clients) — clean (format / lint / build / typecheck).npm run test:storybook— 370 play-tests pass.npm run smoke— launcher / cli / tui / web all pass.connect-crash.test.ts(a pre-existing integration test, untouched here) can hit its 60 s subprocess timeout under the heavy parallel load of a fullcoveragerun, but passes in isolation (~0.5 s) and under CI's lightertest:integrationstep — which is what CI runs (CI does not runcoverage).Docs
AGENTS.mdupdated to describe the uniform 90 gate and thev8 ignorepolicy for genuinely-unreachable branches.🤖 Generated with Claude Code