Skip to content

stevez/nextcov-example

Repository files navigation

nextcov-example

A Todo app demonstrating three-tier testing with 100% merged coverage using nextcov.

Overview

This is a todo-app using React, Next.js and TypeScript. The idea is mostly from this article, and the code is referenced from here.

Key Highlights:

  • Three-tier testing: Unit + Component + Integration (100% merged coverage)
  • V8 code coverage collection using nextcov
  • Coverage merging with statement normalization
  • json-server as mock server for SSR tests
  • GitHub Actions CI pipeline

Constraint: The current solution for SSR test is by changing the mock server data before each test, which means tests can only be run serially. Parallel testing is not supported at the moment.

Quick Start

# Install dependencies
npm install

# Start mock server (in one terminal)
npm run mock

# Start development server (in another terminal)
npm run dev

Open http://localhost:3000 with your browser to see the result.

Testing

This project uses a three-tier testing strategy with Vitest for unit and component tests and Playwright for integration tests, with coverage collection and merging powered by nextcov.

Test Types

Test Type Environment Best For Coverage Focus
Unit jsdom Utilities, hooks, logic Business logic, validation
Component Real browser (Playwright) UI components, interactions React components, browser APIs
Integration Full Next.js server User flows, pages Server components, SSR

Unit Tests (Vitest + jsdom)

Fast unit tests running in jsdom environment for utilities and hooks.

# Run unit tests with coverage
npm run test:unit

# Run tests in watch mode
npm run test:watch

# Run with Vitest UI dashboard
npm run test:unit:ui

Coverage output: ./coverage/unit

View report: npm run lcov:unit

Component Tests (Vitest + Playwright Browser)

Real browser tests using Vitest browser mode with Playwright. Components render in an actual browser with real DOM APIs, CSS, and user interactions.

# Run component tests (headless)
npm run test:component

# Run with visible browser for debugging
npm run test:component:headed

Coverage output: ./coverage/component

View report: npm run lcov:component

Integration Tests (Playwright)

Full end-to-end tests using Playwright that test the complete application including React Server Components and SSR.

# Run integration tests (local)
# 1. Build for local testing
npm run build:local

# 2. Start mock server and Next.js server
npm run start:integration

# 3. Run Playwright tests (in another terminal)
npm run playwright-test

# Or run all-in-one (CI mode)
npm run integration-test

Coverage output: ./coverage/integration

View report: npm run lcov:integration

Coverage

This project uses nextcov to collect V8 coverage from all three test types and merge them into a unified report.

# Run all tests (unit + component)
npm test

# Run integration tests (see steps above)

# Merge all coverage sources into a single report
npm run coverage:merge

Coverage Output:

  • Unit test coverage: coverage/unit/
  • Component test coverage: coverage/component/
  • Integration test coverage: coverage/integration/
  • Merged coverage: coverage/merged/ (HTML report at coverage/merged/index.html)

View merged report: npm run lcov:merged

Coverage by Test Type:

Test Type Overall % What It Covers
Unit Tests ~36% Utilities, hooks
Component Tests ~52% UI components (TodoList, TodoItem)
Integration Tests ~88% Pages, server components, SSR
Merged 100% Complete picture of your application

Why Three Test Types?

Each test type excels at different aspects:

  1. Unit tests - Fast, isolated tests for business logic that doesn't need a browser
  2. Component tests - Real browser rendering for components that use browser APIs (localStorage, CSS, events)
  3. Integration tests - Full integration testing including React Server Components which can't be unit tested

Coverage Normalization

Before merging, the coverage:strip script removes import statements and Next.js directives from unit/component coverage. This normalizes statement counts between environments:

  • jsdom doesn't count imports as statements
  • Real browser counts imports as executable statements
  • Next.js bundled has different statement structure

The strip script ensures apples-to-apples comparison when merging.

Available Scripts

Development

  • npm run dev - Start Next.js development server
  • npm run build - Build for production
  • npm run start - Start production server
  • npm run mock - Start json-server mock API

Testing

  • npm test - Run unit + component tests with coverage
  • npm run test:unit - Run unit tests only (jsdom)
  • npm run test:unit:ui - Run unit tests with Vitest UI dashboard
  • npm run test:watch - Run unit tests in watch mode
  • npm run test:component - Run component tests (browser)
  • npm run test:component:headed - Run component tests with visible browser

Integration Testing

  • npm run build:local - Build with E2E mode enabled
  • npm run start:integration - Start Next.js + mock server
  • npm run playwright-test - Run Playwright tests
  • npm run integration-test - All-in-one integration test (CI)

Coverage

  • npm run coverage:strip - Normalize coverage data
  • npm run coverage:merge - Merge all coverage sources
  • npm run lcov:unit - Open unit coverage report
  • npm run lcov:component - Open component coverage report
  • npm run lcov:integration - Open integration coverage report
  • npm run lcov:merged - Open merged coverage report

Test Stack

  • Vitest: Test runner for unit and browser tests
  • @vitest/browser: Browser testing with Playwright provider
  • Playwright: Integration testing and browser automation
  • nextcov: V8 coverage collection for Next.js with Playwright
  • @vitest/coverage-v8: V8 coverage for Vitest tests
  • json-server: Mock REST API for SSR testing

CI/CD

The GitHub Actions workflow runs all tests and merges coverage:

  1. Run unit tests (npm run test:unit)
  2. Run component tests (npm run test:component)
  3. Build for integration testing (npm run build:local)
  4. Run integration tests (npm run integration-test)
  5. Merge all coverage (npm run coverage:merge)

See .github/workflows/ci.yml for details.

About

An example to use nextcov coverage library

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors