@oorabona/vitest-monocart-coverage
v2.0.1
Published
A Vitest custom coverage provider that integrates with Monocart coverage reporting
Maintainers
Readme
@oorabana/vitest-monocart-coverage
A Vitest custom coverage provider that integrates Vitest's V8 coverage engine with Monocart coverage reporting for enhanced visualization and features.
Architecturally speaking, it is not a full stack coverage provider but instead it sits on top of Vitest coverage-v8 package to enhance it by bridging it to Monocart.
Features
- 🚀 Direct V8 Integration: Intercepts raw V8 coverage data before Istanbul conversion
- 📊 Enhanced Reports: Beautiful HTML reports with detailed coverage visualization
- ⚡ In-Memory Processing: No intermediate files, all data processed in memory
- 🎯 Zero Data Loss: Preserves all V8-specific coverage information
- 🔧 Simple Configuration: Single Vitest config, no extra setup required
- 📈 Console Output: Detailed coverage metrics in terminal
- ✅ Configuration Validation: Runtime validation of config files with clear error messages
- 🔄 Multiple Config Formats: Supports
.ts,.js,.mjs,.cjs, and.jsonconfig files - 🎨 Auto-Discovery: Automatically inherits Vitest's include/exclude patterns
- 🌐 Browser Mode Support: Works with @vitest/browser for frontend code coverage
- 🎨 CSS Coverage: Collect CSS coverage in browser environments
Why Choose Monocart over V8 Default?
Vitest's default V8 provider has coverage accuracy issues with exception handling and complex code paths. See our detailed coverage comparison that shows:
- V8 Default: 97.56% branch coverage (false negatives in exception paths)
- Monocart: 100% branch coverage (accurate real-world coverage)
Read the full analysis: Coverage Provider Comparison
Architecture & Design Decisions
V8-Only vs Dual-Mode Approach
This provider takes an opinionated V8-only approach, unlike some alternatives that support both V8 and Istanbul instrumentation. Here's our reasoning:
🎯 Our Choice: V8 + Post-Processing Enhancement
Vitest V8 Engine → Raw Coverage Data → Source Map Enrichment → Monocart ReportsBenefits:
- ⚡ Maximum Performance: No code instrumentation overhead (~10% vs ~300% for Istanbul)1
- 🧩 Architectural Simplicity: Single data path, fewer failure points
- 🚀 Modern Approach: Leverages V8's native capabilities with smart post-processing
- 📊 Istanbul-Level Accuracy: Since Vitest 3.2.0, V8 coverage uses AST-based remapping that "produces identical coverage reports to Istanbul"2
🔀 Alternative: Dual-Mode (V8/Istanbul)
Some providers offer runtime choice between V8 and Istanbul instrumentation:
Code → Istanbul Instrumentation → Modified Code → Coverage Collection
OR
Code → V8 Native Collection → Raw Data ProcessingTrade-offs:
- ✅ User Choice: Performance (V8) vs Maximum Precision (Istanbul)
- ❌ Added Complexity: Two codepaths to maintain and debug
- ❌ Performance Cost: Istanbul adds ~300% overhead when chosen1
💭 Why V8-Only Works for Most Cases
Modern V8 coverage with Vitest 3.2.0+ AST-based remapping achieves Istanbul-level accuracy2 for:
- Branch coverage in exception paths
- Complex conditional expressions
- Real-world TypeScript/JavaScript codebases
- Source map resolution in transformed code3
Istanbul instrumentation becomes valuable primarily for:
- Non-V8 environments (Firefox, Bun)2
- Edge cases in AST parsing of non-standard ECMAScript4
- Specific compliance requirements where instrumentation is mandated
🔮 Future Evolution
We remain open to adding Istanbul support if there's strong community demand, but our philosophy prioritizes:
- Performance by default (V8)
- Simplicity in architecture
- Excellence in the common case
This approach serves 95% of use cases excellently while keeping the codebase maintainable and fast.
Installation
npm install @oorabana/vitest-monocart-coverageQuick Start
Add the provider to your vitest.config.ts:
import { defineConfig } from 'vitest/config'
import { withMonocartProvider } from '@oorabana/vitest-monocart-coverage'
export default defineConfig({
test: {
include: ['tests/**/*.test.ts'],
coverage: withMonocartProvider({
outputDir: './coverage',
reports: ['html', 'console-details', 'lcov'],
name: 'My Project Coverage',
}),
},
})That's it! Run vitest --coverage and you'll get enhanced coverage reports.
Usage Modes
This provider supports both Node.js and Browser environments, allowing you to get comprehensive coverage for fullstack applications.
Node.js Mode (Default)
Use the default import for Node.js tests (unit tests, API tests, etc.):
import { defineConfig } from 'vitest/config'
import { withMonocartProvider } from '@oorabana/vitest-monocart-coverage'
export default defineConfig({
test: {
environment: 'node',
coverage: withMonocartProvider({
outputDir: './coverage-node',
reports: ['html', 'console-details', 'lcov'],
name: 'Node.js Coverage',
}),
},
})Browser Mode
Use the browser import for frontend tests with @vitest/browser:
import { defineConfig } from 'vitest/config'
import { withMonocartProvider } from '@oorabana/vitest-monocart-coverage'
export default defineConfig({
test: {
browser: {
enabled: true,
provider: 'playwright', // or 'webdriverio'
headless: true,
instances: [{ browser: 'chromium' }],
},
coverage: {
provider: 'custom',
customProviderModule: '@oorabana/vitest-monocart-coverage/browser',
customOptions: {
outputDir: './coverage-browser',
reports: ['html', 'console-details', 'lcov'],
name: 'Browser Coverage',
css: true, // Enable CSS coverage in browser mode
},
},
},
})Fullstack Projects
For projects with both Node.js and browser code, you can use separate configurations:
// vitest.config.ts - Node.js tests
import { defineConfig } from 'vitest/config'
import { withMonocartProvider } from '@oorabana/vitest-monocart-coverage'
export default defineConfig({
test: {
include: ['tests/server/**/*.test.ts'],
environment: 'node',
coverage: withMonocartProvider({
outputDir: './coverage-node',
name: 'Server Coverage',
}),
},
})// vitest.browser.config.ts - Browser tests
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
include: ['tests/client/**/*.test.ts'],
browser: {
enabled: true,
provider: 'playwright',
instances: [{ browser: 'chromium' }],
},
coverage: {
provider: 'custom',
customProviderModule: '@oorabana/vitest-monocart-coverage/browser',
customOptions: {
outputDir: './coverage-browser',
name: 'Client Coverage',
css: true,
},
},
},
})Run both configurations:
# Node.js tests
vitest --coverage
# Browser tests
vitest --config vitest.browser.config.ts --coverageHow It Works
This provider works by intercepting V8 coverage data and enriching it before passing to Monocart:
flowchart LR
A[Vitest Tests] --> B[V8 Coverage Engine]
B --> C[Provider Hook<br/>onAfterSuiteRun]
C --> D[Data Enrichment<br/>+ Source Maps<br/>+ Source Code]
D --> E[Monocart Reports]
E --> F[HTML Reports]
E --> G[Console Output]
E --> H[LCOV Files]
style A fill:#e1f5fe
style E fill:#f3e5f5
style F fill:#e8f5e8
style G fill:#e8f5e8
style H fill:#e8f5e8Key Steps:
- Vitest Configuration: Automatically sets V8 as coverage engine
- Data Interception: Captures raw coverage before Istanbul transformation
- Source Enrichment: Adds source code and maps from Vite's transform cache
- Report Generation: Delegates to Monocart for multiple output formats
Advanced Configuration
Custom Options
export default defineConfig({
test: {
coverage: withMonocartProvider({
// Basic options
name: 'My Project Coverage',
outputDir: './coverage',
reports: ['html', 'console-details', 'lcov'],
// Advanced options
sourcePath: 'src',
sourceFilter: (filePath) => !filePath.includes('node_modules'),
cleanCache: true,
logging: 'info',
// Callback after report generation
onEnd: (results) => {
console.log('Coverage complete!', results)
}
}),
},
})External Configuration
You can also use external configuration files. The provider automatically searches for config files in this order:
monocart.config.mjsmonocart.config.jsmonocart.config.cjsmonocart.config.tsmonocart.config.json
monocart.config.ts:
export default {
name: 'My Project Coverage',
outputDir: './coverage',
reports: ['html', 'console-details'],
logging: 'info',
sourceFilter: (filePath: string) => {
return !filePath.includes('test') && !filePath.includes('node_modules')
},
onEnd: (results) => {
console.log(`Coverage complete! ${results.summary.statements.pct}% statements covered`)
}
}monocart.config.json:
{
"name": "JSON Config Example",
"outputDir": "./coverage",
"reports": ["html", "lcov"],
"logging": "warn"
}vitest.config.ts:
import { defineConfig } from 'vitest/config'
import { withMonocartProvider } from '@oorabona/vitest-monocart-coverage'
export default defineConfig({
test: {
coverage: withMonocartProvider(), // Will load config file automatically
},
})Configuration Validation
The provider validates critical configuration properties at runtime:
outputDirmust be a string if providedreportsmust be an array if providedsourceFiltermust be a function if providedloggingmust be one of: "debug", "info", "warn", "error"onEndmust be a function if provided
Invalid configurations will throw clear error messages indicating the expected type and actual value received.
Configuration Options
All configuration options for the Monocart provider:
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| name | string | "Vitest Monocart Coverage" | Name displayed in coverage reports |
| outputDir | string | "./coverage" | Directory where reports will be generated |
| reports | string[] | ["v8", "console-details"] | Report formats to generate |
| lcov | boolean | true | Generate LCOV format report |
| sourcePath | string | undefined | Source path mapping for reports |
| sourceFilter | function | undefined | Function to filter which files to include |
| cleanCache | boolean | true | Clean cache before generating reports |
| logging | string | "info" | Logging level: "debug", "info", "warn", "error" |
| css | boolean | false | Enable CSS coverage collection (browser mode only) |
| onEnd | function | undefined | Callback executed after report generation |
Report Types
Available report formats for the reports option:
'html': Interactive HTML report with line-by-line coverage'console-details': Detailed console output with coverage metrics'console-summary': Summary console output'v8': Raw V8 coverage data'lcov': LCOV format (also controlled bylcovoption)
Vitest Integration
The provider automatically inherits settings from your Vitest configuration:
- Include/Exclude Patterns: Uses Vitest's
coverage.includeandcoverage.excludefor source filtering - Output Directory: Uses Vitest's
coverage.reportsDirectoryif configured - Project Name: Derives coverage name from Vitest's project name
- Clean Cache: Inherits from Vitest's
coverage.cleansetting
This ensures seamless integration with your existing Vitest setup while providing enhanced reporting capabilities.
Important Notes
Browser vs Node.js Mode Differences
| Feature | Node.js Mode | Browser Mode |
|---------|-------------|--------------|
| Import | @oorabana/vitest-monocart-coverage | @oorabana/vitest-monocart-coverage/browser |
| Environment | Node.js V8 engine | Chromium browser via CDP |
| CSS Coverage | ❌ Not available | ✅ Available with css: true |
| Dependencies | None | Requires @vitest/browser + playwright/webdriverio |
| Performance | Fastest | Slightly slower (browser startup) |
| Use Cases | Unit tests, API tests, server code | Component tests, UI integration, frontend code |
CSS Coverage Requirements
CSS coverage is only available in browser mode because it requires Chrome DevTools Protocol access:
- ✅ Browser Mode:
css: trueenables CSS coverage collection via CDP - ❌ Node.js Mode: CSS coverage is ignored (no effect)
- 🎯 Browser Support: Only works with Chromium-based browsers (Chrome, Edge, etc.)
To use CSS coverage:
// ✅ Correct: Browser mode with CSS coverage
export default defineConfig({
test: {
browser: { enabled: true, provider: 'playwright' },
coverage: {
provider: 'custom',
customProviderModule: '@oorabana/vitest-monocart-coverage/browser',
customOptions: { css: true }, // ✅ Works in browser mode
},
},
})
// ❌ Incorrect: Node.js mode (CSS ignored)
export default defineConfig({
test: {
environment: 'node',
coverage: withMonocartProvider({ css: true }), // ❌ Ignored in Node.js
},
})Documentation
- Coverage Provider Comparison - Detailed analysis of Monocart vs V8 default provider
- Release & CI Workflows - Complete guide to release processes and GitHub Actions
Acknowledgments
This project was inspired by cenfun/vitest-monocart-coverage. Special thanks to cenfun for the original implementation and inspiration.
Differences from Original
This implementation differs from the original in several key ways:
- 🔧 Enhanced Configuration: Runtime validation, multiple config file formats support (
.ts,.js,.mjs,.cjs,.json) - 🎯 Auto-Discovery: Automatic inheritance of Vitest's include/exclude patterns and settings
- ✅ Robust Error Handling: Comprehensive validation with clear error messages and graceful fallbacks
- 🧪 Complete Test Coverage: 100% branch coverage with extensive edge case testing
- 📚 Modern Architecture: Dispatch pattern for config loading, improved TypeScript support
- 🌐 Browser Mode Support: Dual Node.js/Browser support with conditional exports and CSS coverage
- 🛠️ Developer Experience: Better logging, validation, and integration with Vitest ecosystem
References
[1] Vitest Code Coverage Documentation - Performance Comparison. "The lead maintainer of Istanbul suggests 10% performance penalty for v8 vs 300% for Istanbul." Available at: vitest.dev/guide/coverage
[2] Vitest Guide - AST-Based Coverage Remapping. "Since v3.2.0 Vitest has used AST based coverage remapping for V8 coverage, which produces identical coverage reports to Istanbul. This allows users to have the speed of V8 coverage with accuracy of Istanbul coverage." Available at: vitest.dev/guide/coverage
[3] Vitest Issue #5341 - Source Map Resolution Difference. "Source map resolution difference between Istanbul and V8 coverage plugins." Available at: github.com/vitest-dev/vitest/issues/5341
[4] Monocart Coverage Reports Documentation. "AST parsing issues happen when source code is not in standard ECMAScript (like TypeScript or JSX), requiring manual compilation of the source code for these files." Available at: npmjs.com/package/monocart-coverage-reports
License
MIT
