{"id":31157447,"url":"https://github.com/oorabona/vitest-monocart-coverage","last_synced_at":"2026-01-20T17:29:52.871Z","repository":{"id":313406164,"uuid":"1050375148","full_name":"oorabona/vitest-monocart-coverage","owner":"oorabona","description":"A Vitest custom coverage provider that integrates with Monocart coverage reporting","archived":false,"fork":false,"pushed_at":"2025-09-05T20:05:37.000Z","size":170,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-05T21:25:35.577Z","etag":null,"topics":["coverage","monocart","testing","typescript","vitest"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oorabona.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-04T10:45:57.000Z","updated_at":"2025-09-05T20:05:41.000Z","dependencies_parsed_at":"2025-09-05T21:35:45.138Z","dependency_job_id":null,"html_url":"https://github.com/oorabona/vitest-monocart-coverage","commit_stats":null,"previous_names":["oorabona/vitest-monocart-coverage"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/oorabona/vitest-monocart-coverage","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oorabona%2Fvitest-monocart-coverage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oorabona%2Fvitest-monocart-coverage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oorabona%2Fvitest-monocart-coverage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oorabona%2Fvitest-monocart-coverage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oorabona","download_url":"https://codeload.github.com/oorabona/vitest-monocart-coverage/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oorabona%2Fvitest-monocart-coverage/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274704635,"owners_count":25334405,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-11T02:00:13.660Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["coverage","monocart","testing","typescript","vitest"],"created_at":"2025-09-18T22:30:30.872Z","updated_at":"2025-09-18T22:30:36.534Z","avatar_url":"https://github.com/oorabona.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @oorabana/vitest-monocart-coverage\n\n[![npm version](https://badge.fury.io/js/@oorabona%2Fvitest-monocart-coverage.svg)](https://badge.fury.io/js/@oorabona%2Fvitest-monocart-coverage)\n[![CI](https://github.com/oorabona/vitest-monocart-coverage/actions/workflows/ci.yml/badge.svg)](https://github.com/oorabona/vitest-monocart-coverage/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/oorabona/vitest-monocart-coverage/branch/main/graph/badge.svg)](https://codecov.io/gh/oorabona/vitest-monocart-coverage)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/)\n[![Vitest](https://img.shields.io/badge/tested%20with-Vitest-6E9F18.svg)](https://vitest.dev/)\n\nA Vitest custom coverage provider that integrates Vitest's V8 coverage engine with [Monocart coverage reporting](https://github.com/cenfun/monocart-coverage-reports) for enhanced visualization and features.\n\nArchitecturally 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.\n\n## Features\n\n- 🚀 **Direct V8 Integration**: Intercepts raw V8 coverage data before Istanbul conversion\n- 📊 **Enhanced Reports**: Beautiful HTML reports with detailed coverage visualization\n- ⚡ **In-Memory Processing**: No intermediate files, all data processed in memory\n- 🎯 **Zero Data Loss**: Preserves all V8-specific coverage information\n- 🔧 **Simple Configuration**: Single Vitest config, no extra setup required\n- 📈 **Console Output**: Detailed coverage metrics in terminal\n- ✅ **Configuration Validation**: Runtime validation of config files with clear error messages\n- 🔄 **Multiple Config Formats**: Supports `.ts`, `.js`, `.mjs`, `.cjs`, and `.json` config files\n- 🎨 **Auto-Discovery**: Automatically inherits Vitest's include/exclude patterns\n- 🌐 **Browser Mode Support**: Works with @vitest/browser for frontend code coverage\n- 🎨 **CSS Coverage**: Collect CSS coverage in browser environments\n\n## Why Choose Monocart over V8 Default?\n\nVitest's default V8 provider has coverage accuracy issues with exception handling and complex code paths. See our [detailed coverage comparison](./docs/coverage-comparison.md) that shows:\n\n- **V8 Default**: 97.56% branch coverage (false negatives in exception paths)\n- **Monocart**: 100% branch coverage (accurate real-world coverage)\n\nRead the full analysis: **[Coverage Provider Comparison](./docs/coverage-comparison.md)**\n\n## Architecture \u0026 Design Decisions\n\n### V8-Only vs Dual-Mode Approach\n\nThis provider takes an **opinionated V8-only approach**, unlike some alternatives that support both V8 and Istanbul instrumentation. Here's our reasoning:\n\n#### 🎯 **Our Choice: V8 + Post-Processing Enhancement**\n\n```\nVitest V8 Engine → Raw Coverage Data → Source Map Enrichment → Monocart Reports\n```\n\n**Benefits:**\n- ⚡ **Maximum Performance**: No code instrumentation overhead (~10% vs ~300% for Istanbul)\u003csup\u003e[1](#ref1)\u003c/sup\u003e\n- 🧩 **Architectural Simplicity**: Single data path, fewer failure points  \n- 🚀 **Modern Approach**: Leverages V8's native capabilities with smart post-processing\n- 📊 **Istanbul-Level Accuracy**: Since Vitest 3.2.0, V8 coverage uses AST-based remapping that \"produces identical coverage reports to Istanbul\"\u003csup\u003e[2](#ref2)\u003c/sup\u003e\n\n#### 🔀 **Alternative: Dual-Mode (V8/Istanbul)**\n\nSome providers offer runtime choice between V8 and Istanbul instrumentation:\n\n```\nCode → Istanbul Instrumentation → Modified Code → Coverage Collection\n  OR\nCode → V8 Native Collection → Raw Data Processing\n```\n\n**Trade-offs:**\n- ✅ **User Choice**: Performance (V8) vs Maximum Precision (Istanbul)\n- ❌ **Added Complexity**: Two codepaths to maintain and debug\n- ❌ **Performance Cost**: Istanbul adds ~300% overhead when chosen\u003csup\u003e[1](#ref1)\u003c/sup\u003e\n\n#### 💭 **Why V8-Only Works for Most Cases**\n\nModern V8 coverage with Vitest 3.2.0+ AST-based remapping achieves Istanbul-level accuracy\u003csup\u003e[2](#ref2)\u003c/sup\u003e for:\n- Branch coverage in exception paths\n- Complex conditional expressions  \n- Real-world TypeScript/JavaScript codebases\n- Source map resolution in transformed code\u003csup\u003e[3](#ref3)\u003c/sup\u003e\n\n**Istanbul instrumentation** becomes valuable primarily for:\n- Non-V8 environments (Firefox, Bun)\u003csup\u003e[2](#ref2)\u003c/sup\u003e\n- Edge cases in AST parsing of non-standard ECMAScript\u003csup\u003e[4](#ref4)\u003c/sup\u003e\n- Specific compliance requirements where instrumentation is mandated\n\n#### 🔮 **Future Evolution**\n\nWe remain **open to adding Istanbul support** if there's strong community demand, but our philosophy prioritizes:\n1. **Performance by default** (V8)\n2. **Simplicity in architecture** \n3. **Excellence in the common case**\n\nThis approach serves 95% of use cases excellently while keeping the codebase maintainable and fast.\n\n## Installation\n\n```bash\nnpm install @oorabana/vitest-monocart-coverage\n```\n\n## Quick Start\n\nAdd the provider to your `vitest.config.ts`:\n\n```ts\nimport { defineConfig } from 'vitest/config'\nimport { withMonocartProvider } from '@oorabana/vitest-monocart-coverage'\n\nexport default defineConfig({\n  test: {\n    include: ['tests/**/*.test.ts'],\n    coverage: withMonocartProvider({\n      outputDir: './coverage',\n      reports: ['html', 'console-details', 'lcov'],\n      name: 'My Project Coverage',\n    }),\n  },\n})\n```\n\nThat's it! Run `vitest --coverage` and you'll get enhanced coverage reports.\n\n## Usage Modes\n\nThis provider supports both **Node.js** and **Browser** environments, allowing you to get comprehensive coverage for fullstack applications.\n\n### Node.js Mode (Default)\n\nUse the default import for Node.js tests (unit tests, API tests, etc.):\n\n```ts\nimport { defineConfig } from 'vitest/config'\nimport { withMonocartProvider } from '@oorabana/vitest-monocart-coverage'\n\nexport default defineConfig({\n  test: {\n    environment: 'node',\n    coverage: withMonocartProvider({\n      outputDir: './coverage-node',\n      reports: ['html', 'console-details', 'lcov'],\n      name: 'Node.js Coverage',\n    }),\n  },\n})\n```\n\n### Browser Mode\n\nUse the browser import for frontend tests with @vitest/browser:\n\n```ts\nimport { defineConfig } from 'vitest/config'\nimport { withMonocartProvider } from '@oorabana/vitest-monocart-coverage'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      enabled: true,\n      provider: 'playwright', // or 'webdriverio'\n      headless: true,\n      instances: [{ browser: 'chromium' }],\n    },\n    coverage: {\n      provider: 'custom',\n      customProviderModule: '@oorabana/vitest-monocart-coverage/browser',\n      customOptions: {\n        outputDir: './coverage-browser',\n        reports: ['html', 'console-details', 'lcov'],\n        name: 'Browser Coverage',\n        css: true, // Enable CSS coverage in browser mode\n      },\n    },\n  },\n})\n```\n\n### Fullstack Projects\n\nFor projects with both Node.js and browser code, you can use separate configurations:\n\n```ts\n// vitest.config.ts - Node.js tests\nimport { defineConfig } from 'vitest/config'\nimport { withMonocartProvider } from '@oorabana/vitest-monocart-coverage'\n\nexport default defineConfig({\n  test: {\n    include: ['tests/server/**/*.test.ts'],\n    environment: 'node',\n    coverage: withMonocartProvider({\n      outputDir: './coverage-node',\n      name: 'Server Coverage',\n    }),\n  },\n})\n```\n\n```ts\n// vitest.browser.config.ts - Browser tests\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    include: ['tests/client/**/*.test.ts'],\n    browser: {\n      enabled: true,\n      provider: 'playwright',\n      instances: [{ browser: 'chromium' }],\n    },\n    coverage: {\n      provider: 'custom',\n      customProviderModule: '@oorabana/vitest-monocart-coverage/browser',\n      customOptions: {\n        outputDir: './coverage-browser',\n        name: 'Client Coverage',\n        css: true,\n      },\n    },\n  },\n})\n```\n\nRun both configurations:\n```bash\n# Node.js tests\nvitest --coverage\n\n# Browser tests  \nvitest --config vitest.browser.config.ts --coverage\n```\n\n## How It Works\n\nThis provider works by intercepting V8 coverage data and enriching it before passing to Monocart:\n\n```mermaid\nflowchart LR\n    A[Vitest Tests] --\u003e B[V8 Coverage Engine]\n    B --\u003e C[Provider Hook\u003cbr/\u003eonAfterSuiteRun]\n    C --\u003e D[Data Enrichment\u003cbr/\u003e+ Source Maps\u003cbr/\u003e+ Source Code]\n    D --\u003e E[Monocart Reports]\n    E --\u003e F[HTML Reports]\n    E --\u003e G[Console Output]\n    E --\u003e H[LCOV Files]\n    \n    style A fill:#e1f5fe\n    style E fill:#f3e5f5\n    style F fill:#e8f5e8\n    style G fill:#e8f5e8\n    style H fill:#e8f5e8\n```\n\n**Key Steps:**\n1. **Vitest Configuration**: Automatically sets V8 as coverage engine\n2. **Data Interception**: Captures raw coverage before Istanbul transformation\n3. **Source Enrichment**: Adds source code and maps from Vite's transform cache\n4. **Report Generation**: Delegates to Monocart for multiple output formats\n\n## Advanced Configuration\n\n### Custom Options\n\n```ts\nexport default defineConfig({\n  test: {\n    coverage: withMonocartProvider({\n      // Basic options\n      name: 'My Project Coverage',\n      outputDir: './coverage',\n      reports: ['html', 'console-details', 'lcov'],\n      \n      // Advanced options\n      sourcePath: 'src',\n      sourceFilter: (filePath) =\u003e !filePath.includes('node_modules'),\n      cleanCache: true,\n      logging: 'info',\n      \n      // Callback after report generation\n      onEnd: (results) =\u003e {\n        console.log('Coverage complete!', results)\n      }\n    }),\n  },\n})\n```\n\n### External Configuration\n\nYou can also use external configuration files. The provider automatically searches for config files in this order:\n\n1. `monocart.config.mjs`\n2. `monocart.config.js` \n3. `monocart.config.cjs`\n4. `monocart.config.ts`\n5. `monocart.config.json`\n\n**monocart.config.ts:**\n```ts\nexport default {\n  name: 'My Project Coverage',\n  outputDir: './coverage',\n  reports: ['html', 'console-details'],\n  logging: 'info',\n  sourceFilter: (filePath: string) =\u003e {\n    return !filePath.includes('test') \u0026\u0026 !filePath.includes('node_modules')\n  },\n  onEnd: (results) =\u003e {\n    console.log(`Coverage complete! ${results.summary.statements.pct}% statements covered`)\n  }\n}\n```\n\n**monocart.config.json:**\n```json\n{\n  \"name\": \"JSON Config Example\",\n  \"outputDir\": \"./coverage\",\n  \"reports\": [\"html\", \"lcov\"],\n  \"logging\": \"warn\"\n}\n```\n\n**vitest.config.ts:**\n```ts\nimport { defineConfig } from 'vitest/config'\nimport { withMonocartProvider } from '@oorabona/vitest-monocart-coverage'\n\nexport default defineConfig({\n  test: {\n    coverage: withMonocartProvider(), // Will load config file automatically\n  },\n})\n```\n\n### Configuration Validation\n\nThe provider validates critical configuration properties at runtime:\n\n- `outputDir` must be a string if provided\n- `reports` must be an array if provided  \n- `sourceFilter` must be a function if provided\n- `logging` must be one of: \"debug\", \"info\", \"warn\", \"error\"\n- `onEnd` must be a function if provided\n\nInvalid configurations will throw clear error messages indicating the expected type and actual value received.\n\n## Configuration Options\n\nAll configuration options for the Monocart provider:\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `name` | `string` | \"Vitest Monocart Coverage\" | Name displayed in coverage reports |\n| `outputDir` | `string` | \"./coverage\" | Directory where reports will be generated |\n| `reports` | `string[]` | [\"v8\", \"console-details\"] | Report formats to generate |\n| `lcov` | `boolean` | `true` | Generate LCOV format report |\n| `sourcePath` | `string` | `undefined` | Source path mapping for reports |\n| `sourceFilter` | `function` | `undefined` | Function to filter which files to include |\n| `cleanCache` | `boolean` | `true` | Clean cache before generating reports |\n| `logging` | `string` | \"info\" | Logging level: \"debug\", \"info\", \"warn\", \"error\" |\n| `css` | `boolean` | `false` | Enable CSS coverage collection (browser mode only) |\n| `onEnd` | `function` | `undefined` | Callback executed after report generation |\n\n## Report Types\n\nAvailable report formats for the `reports` option:\n\n- `'html'`: Interactive HTML report with line-by-line coverage\n- `'console-details'`: Detailed console output with coverage metrics\n- `'console-summary'`: Summary console output\n- `'v8'`: Raw V8 coverage data\n- `'lcov'`: LCOV format (also controlled by `lcov` option)\n\n## Vitest Integration\n\nThe provider automatically inherits settings from your Vitest configuration:\n\n- **Include/Exclude Patterns**: Uses Vitest's `coverage.include` and `coverage.exclude` for source filtering\n- **Output Directory**: Uses Vitest's `coverage.reportsDirectory` if configured\n- **Project Name**: Derives coverage name from Vitest's project name\n- **Clean Cache**: Inherits from Vitest's `coverage.clean` setting\n\nThis ensures seamless integration with your existing Vitest setup while providing enhanced reporting capabilities.\n\n## Important Notes\n\n### Browser vs Node.js Mode Differences\n\n| Feature | Node.js Mode | Browser Mode |\n|---------|-------------|--------------|\n| **Import** | `@oorabana/vitest-monocart-coverage` | `@oorabana/vitest-monocart-coverage/browser` |\n| **Environment** | Node.js V8 engine | Chromium browser via CDP |\n| **CSS Coverage** | ❌ Not available | ✅ Available with `css: true` |\n| **Dependencies** | None | Requires `@vitest/browser` + `playwright`/`webdriverio` |\n| **Performance** | Fastest | Slightly slower (browser startup) |\n| **Use Cases** | Unit tests, API tests, server code | Component tests, UI integration, frontend code |\n\n### CSS Coverage Requirements\n\nCSS coverage is only available in **browser mode** because it requires Chrome DevTools Protocol access:\n\n- ✅ **Browser Mode**: `css: true` enables CSS coverage collection via CDP\n- ❌ **Node.js Mode**: CSS coverage is ignored (no effect)\n- 🎯 **Browser Support**: Only works with Chromium-based browsers (Chrome, Edge, etc.)\n\nTo use CSS coverage:\n\n```ts\n// ✅ Correct: Browser mode with CSS coverage\nexport default defineConfig({\n  test: {\n    browser: { enabled: true, provider: 'playwright' },\n    coverage: {\n      provider: 'custom',\n      customProviderModule: '@oorabana/vitest-monocart-coverage/browser',\n      customOptions: { css: true }, // ✅ Works in browser mode\n    },\n  },\n})\n\n// ❌ Incorrect: Node.js mode (CSS ignored)\nexport default defineConfig({\n  test: {\n    environment: 'node',\n    coverage: withMonocartProvider({ css: true }), // ❌ Ignored in Node.js\n  },\n})\n```\n\n## Documentation\n\n- **[Coverage Provider Comparison](./docs/coverage-comparison.md)** - Detailed analysis of Monocart vs V8 default provider\n- **[Release \u0026 CI Workflows](./docs/release-workflows.md)** - Complete guide to release processes and GitHub Actions\n\n## Acknowledgments\n\nThis project was inspired by [cenfun/vitest-monocart-coverage](https://github.com/cenfun/vitest-monocart-coverage). Special thanks to cenfun for the original implementation and inspiration.\n\n### Differences from Original\n\nThis implementation differs from the original in several key ways:\n\n- **🔧 Enhanced Configuration**: Runtime validation, multiple config file formats support (`.ts`, `.js`, `.mjs`, `.cjs`, `.json`)\n- **🎯 Auto-Discovery**: Automatic inheritance of Vitest's include/exclude patterns and settings\n- **✅ Robust Error Handling**: Comprehensive validation with clear error messages and graceful fallbacks\n- **🧪 Complete Test Coverage**: 100% branch coverage with extensive edge case testing\n- **📚 Modern Architecture**: Dispatch pattern for config loading, improved TypeScript support\n- **🌐 Browser Mode Support**: Dual Node.js/Browser support with conditional exports and CSS coverage\n- **🛠️ Developer Experience**: Better logging, validation, and integration with Vitest ecosystem\n\n## References\n\n\u003ca id=\"ref1\"\u003e\u003c/a\u003e**[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](https://vitest.dev/guide/coverage)\n\n\u003ca id=\"ref2\"\u003e\u003c/a\u003e**[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](https://vitest.dev/guide/coverage)\n\n\u003ca id=\"ref3\"\u003e\u003c/a\u003e**[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](https://github.com/vitest-dev/vitest/issues/5341)\n\n\u003ca id=\"ref4\"\u003e\u003c/a\u003e**[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](https://www.npmjs.com/package/monocart-coverage-reports)\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foorabona%2Fvitest-monocart-coverage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foorabona%2Fvitest-monocart-coverage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foorabona%2Fvitest-monocart-coverage/lists"}