C8 coverage provider for Vitest testing framework enabling comprehensive code coverage analysis using the C8 JavaScript coverage tool
npx @tessl/cli install tessl/npm-vitest--coverage-c8@0.33.0The @vitest/coverage-c8 package provides a C8 coverage provider integration for the Vitest testing framework. It enables comprehensive code coverage analysis using the C8 JavaScript coverage tool, which leverages V8's built-in code coverage capabilities. This provider handles source map remapping for accurate coverage reporting in TypeScript and bundled code.
npm install @vitest/coverage-c8import coverageC8 from "@vitest/coverage-c8";
// coverageC8 provides: getProvider, startCoverage, takeCoverage, stopCoverageFor CommonJS environments:
const coverageC8 = require("@vitest/coverage-c8");Direct import of coverage functions:
import { startCoverage, takeCoverage, stopCoverage } from "@vitest/coverage-c8";Configure Vitest to use the C8 coverage provider:
// vitest.config.ts
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
coverage: {
provider: 'c8',
reporter: ['text', 'html', 'json'],
exclude: ['node_modules/', '**/*.test.ts'],
allowExternal: false,
excludeNodeModules: true,
},
},
});Run tests with coverage:
npx vitest run --coverageUsing coverage functions programmatically:
import { startCoverage, takeCoverage, stopCoverage } from '@vitest/coverage-c8';
// Start collecting coverage
startCoverage();
// Your test code here...
// Take a coverage snapshot
const coverage = await takeCoverage();
console.log(coverage.result.length); // Number of covered files
// Stop coverage collection
stopCoverage();The package is built around several key components:
C8CoverageProvider class extending BaseCoverageProvider and implementing Vitest's CoverageProvider interfacestartCoverage, takeCoverage, stopCoverage) for interacting with V8 coverage data using Node.js Inspector APIThe main export provides a coverage provider module that integrates with Vitest's coverage system.
/**
* Main module export providing coverage provider and collection functions
*/
interface CoverageProviderModule {
/** Factory for creating a new coverage provider */
getProvider(): Promise<C8CoverageProvider>;
/** Start coverage collection using Node.js inspector */
startCoverage(): void;
/** Take coverage snapshot and return filtered results */
takeCoverage(): Promise<{ result: Profiler.ScriptCoverage[] }>;
/** Stop coverage collection and disconnect inspector */
stopCoverage(): void;
}
/**
* Default export object structure
*/
const coverageModule: CoverageProviderModule;
export default coverageModule;Core coverage provider class that handles collection, processing, and reporting.
/**
* C8 coverage provider implementing CoverageProvider interface
*/
class C8CoverageProvider extends BaseCoverageProvider implements CoverageProvider {
name: string; // Always 'c8'
ctx: Vitest;
options: ResolvedCoverageOptions<'c8'>;
coverages: Profiler.TakePreciseCoverageReturnType[];
/** Initialize the provider with Vitest context and configuration */
initialize(ctx: Vitest): void;
/** Get resolved coverage options */
resolveOptions(): ResolvedCoverageOptions<'c8'>;
/** Clean coverage directory and reset coverage data */
clean(clean?: boolean): Promise<void>;
/** Collect coverage data after suite run */
onAfterSuiteRun(meta: AfterSuiteRunMeta): void;
/** Generate and write coverage reports */
reportCoverage(reportContext?: ReportContext): Promise<void>;
/** Resolve reporters from various configuration options */
resolveReporters(configReporters: NonNullable<BaseCoverageOptions['reporter']>): ResolvedCoverageOptions['reporter'];
/** Check collected coverage against configured thresholds */
checkThresholds({ coverageMap, thresholds, perFile }: {
coverageMap: CoverageMap;
thresholds: Record<'lines' | 'functions' | 'statements' | 'branches', number | undefined>;
perFile?: boolean;
}): void;
/** Update thresholds when current coverage is above configured thresholds */
updateThresholds({ configurationFile, coverageMap, thresholds, perFile }: {
coverageMap: CoverageMap;
thresholds: Record<'lines' | 'functions' | 'statements' | 'branches', number | undefined>;
perFile?: boolean;
configurationFile?: string;
}): void;
}Low-level functions for interacting with V8's coverage system through Node.js Inspector API.
/**
* Start coverage collection using Node.js inspector
* Connects to inspector and enables precise coverage tracking
*/
function startCoverage(): void;
/**
* Take a coverage snapshot and return filtered results
* Filters out node_modules and non-file URLs using internal filterResult function
* Only includes files that start with 'file://' and don't contain '/node_modules/'
* @returns Promise resolving to coverage data with filtered script coverage
*/
function takeCoverage(): Promise<{ result: Profiler.ScriptCoverage[] }>;
/**
* Stop coverage collection and disconnect inspector
* Disables profiler and closes inspector session
*/
function stopCoverage(): void;C8-specific coverage configuration options extending base coverage options.
/**
* Configuration options specific to C8 coverage provider
*/
interface CoverageC8Options extends BaseCoverageOptions {
/** Allow files from outside of current working directory */
allowExternal?: boolean; // default: false
/** Exclude coverage under /node_modules/ */
excludeNodeModules?: boolean; // default: true
/** Directories used when --all is enabled */
src?: string[];
/** Shortcut for 100% coverage thresholds on all metrics */
100?: boolean; // default: false
/** Watermarks for statements, lines, branches and functions */
watermarks?: {
statements?: [number, number];
functions?: [number, number];
branches?: [number, number];
lines?: [number, number];
};
}
/**
* Base coverage options shared across all providers
*/
interface BaseCoverageOptions {
/** Enable coverage collection */
enabled?: boolean; // default: false
/** Files included in coverage as glob patterns */
include?: string[]; // default: ['**']
/** File extensions to include in coverage */
extension?: string | string[]; // default: ['.js', '.cjs', '.mjs', '.ts', '.tsx', '.jsx', '.vue', '.svelte']
/** Files excluded from coverage as glob patterns */
exclude?: string[];
/** Include all files, including untested ones */
all?: boolean; // default: false
/** Clean coverage results before running tests */
clean?: boolean; // default: true
/** Clean coverage report on watch rerun */
cleanOnRerun?: boolean; // default: true
/** Directory to write coverage report to */
reportsDirectory?: string;
/** Coverage reporters to use */
reporter?: CoverageReporter | CoverageReporter[] | CoverageReporterWithOptions[];
/** Skip files with 100% coverage in reports */
skipFull?: boolean; // default: false
/** Check thresholds per file */
perFile?: boolean; // default: false
/** Coverage thresholds */
lines?: number;
functions?: number;
branches?: number;
statements?: number;
/** Update thresholds automatically when coverage is higher */
thresholdAutoUpdate?: boolean; // default: false
/** Generate coverage report even when tests fail */
reportOnFailure?: boolean; // default: true
}Available coverage report formats and their configuration.
/**
* Available coverage reporters from Istanbul
*/
type CoverageReporter =
| 'clover'
| 'cobertura'
| 'html'
| 'html-spa'
| 'json'
| 'json-summary'
| 'lcov'
| 'lcovonly'
| 'none'
| 'teamcity'
| 'text'
| 'text-lcov'
| 'text-summary';
/**
* Reporter with configuration options
*/
type CoverageReporterWithOptions = [CoverageReporter, object];Types for coverage collection and reporting context.
/**
* Context passed to reportCoverage method
*/
interface ReportContext {
/** Indicates whether all tests were run (false for selective test runs) */
allTestsRun?: boolean;
}
/**
* Metadata from suite run containing coverage data
*/
interface AfterSuiteRunMeta {
/** Coverage data collected during suite execution */
coverage: Profiler.TakePreciseCoverageReturnType;
}
/**
* Coverage map from Istanbul library
*/
interface CoverageMap {
files(): string[];
fileCoverageFor(filename: string): FileCoverage;
getCoverageSummary(): CoverageSummary;
}
/**
* Coverage summary with metrics
*/
interface CoverageSummary {
data: {
lines: { pct: number };
functions: { pct: number };
statements: { pct: number };
branches: { pct: number };
};
lines: { pct: number };
functions: { pct: number };
statements: { pct: number };
branches: { pct: number };
}
/**
* File coverage information
*/
interface FileCoverage {
toSummary(): CoverageSummary;
}
/**
* V8 profiler types from Node.js inspector
*/
namespace Profiler {
interface TakePreciseCoverageReturnType {
result: ScriptCoverage[];
}
interface ScriptCoverage {
scriptId: string;
url: string;
functions: FunctionCoverage[];
}
interface FunctionCoverage {
functionName: string;
ranges: CoverageRange[];
isBlockCoverage: boolean;
}
interface CoverageRange {
startOffset: number;
endOffset: number;
count: number;
}
}The package handles several error scenarios:
Important: This package is deprecated and being replaced by @vitest/coverage-v8. The provider automatically displays a deprecation warning when initialized:
DEPRECATION @vitest/coverage-c8 is being replaced by @vitest/coverage-v8.
See https://github.com/vitest-dev/vitest/pull/3339 for more information.Users should migrate to the newer V8 coverage provider for better performance and maintainability.