If you've ever tried to get test coverage for React Server Components, you know the frustration. Unit testing frameworks like Jest and Vitest can't render server components — they require the full Next.js runtime. So you write E2E tests with Playwright, but then you're left wondering: "What's actually being covered?"
nextcov solves this problem by collecting V8 coverage from both client and server during Playwright E2E tests, then merging it with your unit and component test coverage for a complete picture.
The Testing Landscape in 2025
Modern Next.js applications have three layers that need testing:
| Layer | What to Test | Best Tool |
|---|---|---|
| Utilities & Hooks | Pure functions, custom hooks | Vitest (unit tests) |
| Client Components | React components with user interaction | Vitest Browser Mode (component tests) |
| Server Components | RSC, server actions, full pages | Playwright (E2E tests) |
Vitest Browser Mode — Great for Client Components
Vitest's Browser Mode is excellent for component testing. It runs tests in a real browser, giving you accurate DOM behavior and event handling. Combined with @vitest/coverage-v8, you get proper coverage for your client components.
But there's a limitation: Vitest Browser Mode only works for client components. Server components require the full Next.js runtime — they can't be rendered in isolation.
The Server Component Gap
React Server Components (RSC) are notoriously difficult to test:
- They run only on the server — Can't be rendered in jsdom or even a real browser
- Async components fetch data directly — Mocking becomes complex and unreliable
- Tight coupling with Next.js runtime — Server actions, cookies, headers require the full framework
The practical solution? Test server components through E2E tests with Playwright, where they run in their natural environment.
But this creates a coverage gap. You have coverage from unit tests, coverage from component tests... but nothing from E2E tests.
nextcov Fills the Gap
nextcov completes the coverage picture by collecting V8 coverage during Playwright E2E tests:
| Test Type | Coverage Tool | What It Covers |
|---|---|---|
| Unit (Vitest) | @vitest/coverage-v8 | Utilities, hooks, logic |
| Component (Vitest Browser) | @vitest/coverage-v8 | Client components |
| E2E (Playwright) | nextcov | Server components, pages, user flows |
And the best part? nextcov merges all three into a single unified report.
Real Results
In a production Next.js application:
| Coverage Type | Lines |
|---|---|
| Unit Tests | ~45% |
| Component Tests | ~35% |
| E2E Tests (nextcov) | ~46% |
| Merged | ~88% |
Each test type contributes coverage that others can't reach. The merged report shows exactly what's tested and what's not.
How It Works
Unlike traditional coverage tools that work within a single Node.js process, nextcov coordinates coverage collection across three separate environments:
- Test Runner (Playwright) — orchestrates tests
- Next.js Server (Node.js) — runs server components
- Browser (Chromium) — runs client components
For the browser, nextcov uses Playwright's CDP integration to collect V8 coverage. For the server, it uses Node.js's built-in NODE_V8_COVERAGE environment variable, triggered via Chrome DevTools Protocol.
This multi-process approach is what makes nextcov unique compared to tools like c8 or @vitest/coverage-v8, which only work within a single process.
Quick Start
# Install
npm install nextcov --save-dev
# Interactive setup
npx nextcov init
The init command creates all the necessary configuration files:
-
e2e/global-setup.ts— Initialize coverage collection -
e2e/global-teardown.ts— Finalize and generate reports -
e2e/fixtures/test-fixtures.ts— Playwright fixture for per-test coverage - Updates to
playwright.config.tsandnext.config.ts
Then run your E2E tests with coverage:
# Build with source maps
E2E_MODE=true npm run build
# Start server with coverage enabled and run tests
NODE_V8_COVERAGE=.v8-coverage NODE_OPTIONS='--inspect=9230' npm start &
npx playwright test
Merging All Coverage
The real power comes from merging E2E coverage with your unit and component test coverage:
# Merge all coverage sources
npx nextcov merge coverage/unit coverage/component coverage/e2e -o coverage/merged
This produces a unified HTML report showing the complete coverage picture — what's covered by unit tests, component tests, E2E tests, and what's still missing.
Detecting V8 Coverage Blind Spots
Even with complete test coverage, V8 has limitations. Certain JSX patterns cannot be tracked for branch coverage:
// These patterns are NOT tracked by V8
function MyComponent({ error, user }) {
return (
<div>
{error && <ErrorMessage />} {/* logical AND */}
{user ? <LoggedIn /> : <LoggedOut />} {/* ternary */}
</div>
)
}
nextcov includes a check command to scan your codebase for these patterns:
npx nextcov check src/
Example output:
V8 Coverage Blind Spots Found:
────────────────────────────────────────────────────────────
src/components/ReviewForm.tsx:69:9
⚠ JSX logical AND (V8 cannot track branch coverage)
src/components/ui/Input.tsx:25:26
⚠ JSX ternary operator (V8 cannot track branch coverage)
────────────────────────────────────────────────────────────
Found 2 issues in 2 files
The Complete Testing Strategy
Here's the recommended approach for Next.js applications:
- Unit tests (Vitest) — Test utilities, hooks, and pure logic
- Component tests (Vitest Browser Mode) — Test client components in isolation
- E2E tests (Playwright + nextcov) — Test server components, pages, and user flows
-
Merge coverage — Get the complete picture with
nextcov merge
This gives you fast feedback from unit and component tests during development, comprehensive E2E tests for critical user flows, and a unified coverage report that shows exactly what's tested.
Features
- Next.js + Vite support — Works with both frameworks
- Client + Server coverage — Browser and Node.js in one report
-
Dev mode support — Works with
next dev(no production build required) - Auto-detection — Automatically detects dev vs production mode
- Source map support — Maps bundled code back to original TypeScript/JSX
- Multi-source merge — Combine unit, component, and E2E coverage
-
Blind spot detection — Find V8 coverage limitations with
nextcov check - Multiple reporters — HTML, LCOV, JSON, text-summary
Try It Out
- GitHub: https://github.com/stevez/nextcov
- npm: https://www.npmjs.com/package/nextcov
- Example Project: https://github.com/stevez/nextcov-example
If you're building a Next.js application and want complete test coverage visibility across unit, component, and E2E tests, give nextcov a try.
Top comments (0)