Skip to content

feat: add test coverage run with vitest + v8#364

Merged
brianmhunt merged 8 commits intomainfrom
test/coverage
May 5, 2026
Merged

feat: add test coverage run with vitest + v8#364
brianmhunt merged 8 commits intomainfrom
test/coverage

Conversation

@phillipc
Copy link
Copy Markdown
Member

@phillipc phillipc commented Apr 22, 2026

Summary

Recovering a lost feature: Adds a bun run test:coverage script that produces a v8 coverage report against the authoritative chromium browser project.

Changes

  • package.json β€” new test:coverage script: bun run build && bunx vitest run --coverage --project browser. Adds @vitest/coverage-v8 as a devDependency (pinned exact 4.1.4 β€” its declared peerDependencies: { vitest: 4.1.4 } is exact, so a caret on both sides would warn on the next patch bump).
  • vitest.config.ts β€” adds a top-level coverage block (v8 provider; reporters: text, text-summary, html, lcov, json-summary; outputs to coverage/). Includes packages/*/dist/**/*.js (so v8 picks up actually-executed code) and both packages/*/src/**/*.ts and builds/*/src/**/*.ts (so source-map remapping surfaces TS line numbers in the report). Index-barrel exclude is anchored to packages/ only so builds/{knockout,reference}/src/index.ts (the only real src file in each build) is not silently dropped.
  • tools/build.ts β€” switches esbuild from --sourcemap=external to --sourcemap=linked. Published dist/*.js gain one trailing //# sourceMappingURL=... comment line so v8 can remap coverage back to the original TS sources. .map files were already shipped in npm tarballs (files: ["dist/"]), so no consumer-facing 404 risk.
  • .gitignore β€” adds COVERAGE.md. The snapshot rots on every run that isn't followed by a commit; reintroduce later when test:coverage deterministically rewrites it.

Verification

  • bun run test:coverage exits 0; report written to coverage/.
  • The authoritative real-browser matrix (bun run test) is unchanged β€” coverage is opt-in via the new script.

Notes

  • Coverage runs against the chromium project only. Firefox/WebKit are not covered β€” JavaScriptCore and SpiderMonkey don't expose V8's coverage protocol. The matrix's job is correctness across engines; coverage's job is "what code did we exercise" β€” Chromium is a sufficient proxy because the spec set is identical across all three browsers.
  • Published dist/*.js artifacts gain one trailing //# sourceMappingURL=... comment line. No other build-output changes.
  • Coverage is not gated in CI; that's a follow-up. Land opt-in, gate later once stability is proven.

Summary by CodeRabbit

New Features

  • Introduced test coverage reporting with support for multiple output formats (HTML, LCOV, JSON, and text summaries).

Chores

  • Updated build sourcemap generation configuration.
  • Added test coverage analysis tooling dependencies.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

Warning

Rate limit exceeded

@brianmhunt has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 1 minute and 5 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

βŒ› How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 98c21a3d-6fdb-400b-82ba-9482d1c00b5d

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between fd1644b and 503c5c3.

πŸ“’ Files selected for processing (2)
  • .github/workflows/coverage.yml
  • vitest.config.ts
πŸ“ Walkthrough

Walkthrough

This pull request sets up code coverage reporting infrastructure for the project. It adds Vitest coverage configuration with V8 as the provider, introduces a test coverage script, updates the build system to emit linked sourcemaps, adds the coverage dependency, and removes the outdated coverage report file from version control.

Changes

Code Coverage Setup

Layer / File(s) Summary
Coverage Configuration
vitest.config.ts
Introduces test.coverage with V8 provider, adds multiple reporters (text, text-summary, html, lcov, json-summary), and defines include/exclude globs for packages/*/src, packages/*/dist, and builds/*/src while excluding specs, helpers, types, and index barrels.
Build Support
tools/build.ts
Changes esbuild sourcemap from --sourcemap=external to --sourcemap=linked to support coverage instrumentation.
Package Management
package.json
Adds test:coverage script that runs build and then executes Vitest with coverage for the browser project; adds @vitest/coverage-v8@^4.1.4 to devDependencies.
Housekeeping
.gitignore, COVERAGE.md
Adds COVERAGE.md to gitignore list and removes the outdated coverage report file.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A coverage setup, clear and bright,
With V8 shining, measuring might,
Linked sourcemaps guide the way,
Old reports now pass away,
Tests report with colors of light!

πŸš₯ Pre-merge checks | βœ… 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
βœ… Passed checks (4 passed)
Check name Status Explanation
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check βœ… Passed The PR title 'feat: add test coverage run with vitest + v8' directly and concisely describes the primary change: adding test coverage functionality using Vitest and V8.
Linked Issues check βœ… Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check βœ… Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/coverage

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@phillipc phillipc requested a review from brianmhunt April 22, 2026 21:28
@brianmhunt
Copy link
Copy Markdown
Member

brianmhunt commented May 5, 2026

Will pick this up and address must-fix items on branch.

Must fix:

  1. vitest.config.ts:14 comment claims cli-happy-dom; script targets --project browser. Reword.
  2. Include missing builds/*/dist/**/*.js. Builds disappear from report.
  3. **/index.ts exclude drops builds/{knockout,reference}/src/index.ts β€” the only src file in each build. Tighten to packages/*/index.ts.

Worth deciding:
4. --sourcemap=external β†’ linked adds //# sourceMappingURL= to every published dist/*.js. Acknowledge in PR body.
5. Chromium-only coverage; matrix is chromium+firefox+webkit. Targets game easily.
6. No CI gate. Opt-in only β†’ numbers rot.

Notes:

  • COVERAGE.md hand-committed; not produced by test:coverage.
  • @vitest/coverage-v8 ^4.1.4 peer-pins exact vitest: 4.1.4. Drop carets.
  • test:coverage rebuilds; doubles cost vs test.

…itignore COVERAGE.md

Address adversarial-review findings on the coverage harness:

- vitest.config.ts comment claimed cli-happy-dom but the script runs
  --project browser. Reword to match reality (Playwright Chromium = V8
  runtime) and document the Firefox/WebKit caveat (JSC/SpiderMonkey
  don't expose V8's coverage protocol).
- Anchor the index-barrel exclude to packages/ only. The previous
  **/index.ts pattern silently masked builds/{knockout,reference}/src/
  index.ts β€” the ONLY src file in each build, containing real
  configuration (Builder wiring, options, jsx.render). builds/* now
  appears in the report again via source-map remap from
  builds/*/src/**/*.ts.
- Drop hand-committed COVERAGE.md and gitignore it. The snapshot
  rotted on every run that wasn't followed by a commit. Reintroduce
  later when test:coverage deterministically rewrites it.
- Pin @vitest/coverage-v8 to exact 4.1.4 (drop the caret).
  @vitest/coverage-v8 declares peerDependencies: { vitest: 4.1.4 }
  exact; caret on both sides will warn on the next patch bump.
  @vitest/browser and @vitest/browser-playwright keep their carets
  because their own peer-deps allow it.

Considered but rejected: adding builds/*/dist/**/*.js to include.
That sweeps in browser.js / browser.min.js / common.js / index.js
(8 files across 2 builds) where only browser.min.js is actually
executed by tests. The minified bundle is also strictly worse to
instrument than the unminified packages/*/dist/**/*.js paths that
already cover the same code. Source-map remap from builds/*/src is
sufficient.

Adversarial review: two parallel subagents on this branch + a
verification pass on the proposed edits. Initial draft included
builds/*/dist/**/*.js; verification subagent flagged false-positive
0% rows for unexecuted bundles; rolled back.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
vitest.config.ts (1)

57-58: ⚠️ Potential issue | 🟑 Minor | ⚑ Quick win

Comment wording is now misleading for the coverage entrypoint.

Line 57 says β€œAdditive CLI coverage,” but test:coverage targets only --project browser. Please reword to avoid implying this project contributes to that coverage run.

Proposed wording tweak
-      // Additive CLI coverage β€” happy-dom.
-      // Intent: prove the binding engine works in a JS DOM (SSR, headless, TUI adapters).
+      // Additional CLI project (happy-dom) for JS-DOM execution scenarios.
+      // Note: `bun run test:coverage` targets `--project browser`.
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@vitest.config.ts` around lines 57 - 58, Update the misleading comment
"Additive CLI coverage β€” happy-dom." near the browser project coverage entry so
it doesn’t imply inclusion in the global test:coverage run; change it to clearly
state that this entry only targets the browser project (e.g., mention "--project
browser" or "browser-only coverage") and that it does not add to the overall CLI
coverage aggregate for other projects or the test:coverage script.
πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@vitest.config.ts`:
- Around line 57-58: Update the misleading comment "Additive CLI coverage β€”
happy-dom." near the browser project coverage entry so it doesn’t imply
inclusion in the global test:coverage run; change it to clearly state that this
entry only targets the browser project (e.g., mention "--project browser" or
"browser-only coverage") and that it does not add to the overall CLI coverage
aggregate for other projects or the test:coverage script.

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4fea9e2b-d6fe-4915-b2bf-c267f6c77701

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 733bbb1 and fd1644b.

β›” Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
πŸ“’ Files selected for processing (5)
  • .gitignore
  • COVERAGE.md
  • package.json
  • tools/build.ts
  • vitest.config.ts
πŸ’€ Files with no reviewable changes (1)
  • COVERAGE.md

Brian M Hunt and others added 2 commits May 5, 2026 08:05
CI lint failed: Biome wanted the include array inline. format --write
fixes it. Behavior unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…in report

Local run with the prior config showed builds/{knockout,reference}
missing from coverage entirely β€” including builds/*/src/**/*.ts is
necessary but not sufficient because v8 only instruments executed
code, and the test runner loads the IIFE bundle, not src.

builds/*/dist/browser.min.js is what builds/knockout/helpers/
vitest-setup.js imports. v8 instruments the minified output;
source-map remap (enabled by tools/build.ts switch to
--sourcemap=linked earlier in this PR) surfaces the original
builds/*/src/index.ts lines in the report.

Other dist outputs (browser.js, index.cjs, index.mjs, common.js)
are alternate formats not loaded by the test runner; including
them would add 0%-coverage rows. Pin to browser.min.js explicitly.

Verified locally: builds/knockout/src/index.ts at 100% / builds/
reference/src/index.ts at 60% (jsx.render uncovered β€” pre-existing
gap exposed). Overall lines coverage 92.03% β†’ 94.35%.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Runs vitest+v8 coverage on every PR and every push to main. Outputs:

- Workflow run summary table (lines / statements / branches / functions
  with covered/total counts) for at-a-glance visibility.
- coverage-data artifact (coverage-summary.json + lcov.info, ~220 KB,
  30-day retention) β€” small enough that future closed-loop tooling can
  download a base commit's data to compute deltas.
- coverage-html artifact (lcov-report HTML, ~5 MB, 7-day retention,
  main-only) for human download via the workflow run page.

Open-loop only β€” no PR comment, no delta gate. Closed-loop dark-factory
feedback (post deltas to the PR; gate regressions) is a follow-up;
the first attempt at the gate logic shipped four blockers in
adversarial review (gh run download flag, missing reporter file,
PATCH body encoding, heredoc terminator indentation), so split out
and ship the simple version first.

Adversarial review: subagent on this branch verified the simple
flow works in the Playwright container, container pin matches
build-and-test.yml, permissions defaults are sufficient, and the
artifact-namespace + concurrency-group combination doesn't collide.
The closed-loop design + its known blockers are tracked as a
follow-up issue.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Coverage workflow's summary step uses jq to format the run-summary
table. The Playwright noble image ships without jq β†’ exit 127.
Install via apt-get before the step.

Pre-merge verification gap: I claimed the workflow was verified locally.
It wasn't run in a container that mirrors CI; the local run on macOS
used the system jq. Fix here, but adversarial process should have
spawned a container parity check.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Member

@brianmhunt brianmhunt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ‘ great idea, thanks @phillipc

@brianmhunt brianmhunt merged commit ec8231f into main May 5, 2026
10 checks passed
@brianmhunt brianmhunt deleted the test/coverage branch May 5, 2026 12:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants