Skip to content

feat(coverage): add @react-grab/playwright-coverage package - #489

Open
aidenybai wants to merge 5 commits into
mainfrom
feat/playwright-coverage-package
Open

feat(coverage): add @react-grab/playwright-coverage package#489
aidenybai wants to merge 5 commits into
mainfrom
feat/playwright-coverage-package

Conversation

@aidenybai

@aidenybai aidenybai commented Jun 25, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a dedicated @react-grab/playwright-coverage package that captures native V8 JS coverage from a Playwright run and remaps it back onto the original src/*.ts(x) sources.

  • New package packages/playwright-coverage:
    • createCoverageFixture({ rawDir }) — an auto Playwright fixture (COVERAGE-gated, Chromium-only, fully best-effort) that dumps per-test V8 coverage.
    • generateCoverageReport(options) — merges the raw dumps, inlines the dist sourcemaps, and produces v8 / lcovonly / console reports via monocart-coverage-reports.
  • Bounded memory: per-test V8 dumps are merged incrementally into one accumulator per script, and non-remappable URLs (app/vite/framework chunks) are dropped up front — so it scales to the full ~900-test suite without exhausting the heap.
  • No @bcoe/v8-coverage dependency: reuses monocart's public Util.mergeV8Coverage (the same bcoe range-tree merge) since we already depend on monocart for reporting.
  • react-grab wiring: e2e fixture now uses the package; scripts/run-coverage.ts orchestrates the run; e2e/coverage-config.ts holds the dirs + react-grab source filter; a sourcemapped, unminified build:coverage is selected in playwright.config.ts under COVERAGE.

Run with: pnpm --filter react-grab test:coverage

Test plan

  • pnpm --filter @react-grab/playwright-coverage build (dist matches exports map)
  • pnpm --filter @react-grab/playwright-coverage typecheck + lint
  • pnpm --filter react-grab typecheck (consumer resolves package types)
  • Runtime smoke: Util.mergeV8Coverage reachable; count:1 ∪ count:0 → 1
  • @react-grab/playwright-coverage#build is in react-grab's turbo build graph (pnpm build builds it first)
  • Full pnpm --filter react-grab test:coverage run produces a src-level report

Note

Low Risk
Test-only and dev-tooling paths; coverage is gated on COVERAGE and does not change production runtime behavior of react-grab.

Overview
Introduces @react-grab/playwright-coverage, a workspace package that records Chromium V8 JS coverage during Playwright tests and remaps hits onto original src/*.ts(x) via inlined dist source maps and monocart-coverage-reports (v8, lcov, console). Capture and reporting are best-effort so tests never fail on coverage errors; raw dumps are merged incrementally per script and non-remappable URLs are dropped to keep memory bounded on large suites.

react-grab wires this behind COVERAGE=1: an auto coverageCapture fixture (lazy import) runs before navigation; globalSetup / globalTeardown clear .coverage-v8 and emit filtered reports; playwright.config.ts uses build:coverage (sourcemapped, unminified) and disables reusing an existing dev server so coverage is not silently empty. Adds test:coverage, .coverage-v8 in .gitignore, and lockfile entries for monocart and related deps.

Reviewed by Cursor Bugbot for commit 0aaab8e. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Adds @react-grab/playwright-coverage to capture native V8 JS coverage in Playwright, remap it to src/*.ts(x), and output v8, lcovonly, and console reports. Coverage runs are COVERAGE-gated, lazily loaded, cleaned in globalSetup, reported in globalTeardown, and always use a fresh dev server for accurate sourcemaps.

  • New Features

    • New package @react-grab/playwright-coverage with:
      • captureCoverage(page, rawDir, use) to record per-test V8 JS coverage (Chromium-only), now flushes coverage in a finally block so failing tests still record.
      • generateCoverageReport(options) to merge dumps, inline sourcemaps, and produce reports via monocart-coverage-reports.
    • Incremental per-script merging via Util.mergeV8Coverage; ignores non-remappable URLs and inlines dist maps for accurate remap.
    • react-grab wiring: lazy import auto coverageCapture fixture; e2e/coverage-setup.ts as globalSetup; e2e/coverage-teardown.ts as globalTeardown. playwright.config.ts switches to build:coverage and never reuses a running server under COVERAGE. Adds .coverage-v8 to .gitignore.
  • Migration

    • Run coverage: pnpm --filter react-grab test:coverage (prebuilds @react-grab/playwright-coverage via pretest:coverage).
    • Notes: Chromium-only; reports in packages/react-grab/coverage/; raw dumps in packages/react-grab/.coverage-v8.

Written for commit 0aaab8e. Summary will update on new commits.

Review in cubic

Capture native V8 JS coverage from a Playwright run and remap it back onto
original src/*.ts(x) via monocart-coverage-reports.

- New package packages/playwright-coverage with createCoverageFixture (auto
  fixture, COVERAGE-gated, Chromium-only) and generateCoverageReport.
- Merges per-test V8 dumps incrementally (one accumulator per script, drops
  non-remappable URLs early) so memory stays bounded across the full suite.
- Reuses monocart's public Util.mergeV8Coverage range-tree merge instead of a
  separate @bcoe/v8-coverage dependency.
- react-grab consumes it: e2e fixture, scripts/run-coverage.ts orchestrator,
  e2e/coverage-config.ts (dirs + react-grab source filter), and a
  build:coverage (sourcemapped, unminified) build wired into playwright.config
  under COVERAGE.
@vercel

vercel Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
react-grab-storybook Ready Ready Preview, Comment Jun 25, 2026 7:24am
react-grab-website Ready Ready Preview, Comment Jun 25, 2026 7:24am

@pkg-pr-new

pkg-pr-new Bot commented Jun 25, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@react-grab/cli@489
npm i https://pkg.pr.new/grab@489
npm i https://pkg.pr.new/react-grab@489

commit: 0aaab8e

Comment thread packages/react-grab/scripts/run-coverage.ts Outdated
Replace the bespoke script that re-spawned `playwright test` with native
hooks: clean the raw V8 dir as the config loads and generate the report in
globalTeardown (both gated on COVERAGE). test:coverage is now just
`COVERAGE=1 playwright test`.
Comment thread packages/react-grab/playwright.config.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found and verified against the latest diff

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/playwright-coverage/src/report.ts">

<violation number="1" location="packages/playwright-coverage/src/report.ts:66">
P2: `/@fs/` prefix trimming is off by one, producing incorrect local file paths. This can drop remappable scripts and under-report coverage on some platforms.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/playwright-coverage/src/report.ts Outdated
Comment thread packages/react-grab/playwright.config.ts Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 4 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/react-grab/playwright.config.ts
The perf workflow runs `playwright test` after `pnpm install` with no build
step, so @react-grab/playwright-coverage's dist never exists. playwright.config
and fixtures imported it at the top level, breaking config load for every perf
run (ERR_MODULE_NOT_FOUND).

Make the package strictly opt-in: move the raw-dir clean into a COVERAGE-only
globalSetup module, and have the fixture lazily `import()` a new per-test
`captureCoverage` primitive inside its body. Non-coverage (and perf) runs now
never reference the package, so its build is no longer a hard dependency.
Replaces the createCoverageFixture factory with the smaller captureCoverage
primitive that composes with lazy loading.
Address review feedback: when COVERAGE is set, force a fresh dev server so the
sourcemapped, unminified build:coverage always runs. Reusing an existing server
(the default local non-CI case) could serve a minified dist with no sibling
.map, silently producing empty/misleading coverage.

Also self-document the /@fs/ path slice so its intent (preserve the leading
slash of the absolute path) is obvious and provably not off-by-one.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit e065353. Configure here.

Comment thread packages/playwright-coverage/src/fixture.ts
Comment thread packages/react-grab/package.json
…age run

Address review feedback:
- captureCoverage now stops/writes coverage in a finally, so a failing test
  still flushes whatever it exercised instead of dropping its coverage.
- Add pretest:coverage to build @react-grab/playwright-coverage, since the
  coverage path imports its dist (globalSetup + fixture) and `test:coverage`
  alone never built it.
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.

1 participant