A plugin for Vitest that generates a structured JSON coverage summary from V8 coverage data. This package also includes GitHub Actions for coverage reporting and badge management.
- โ Generates structured JSON coverage summary
- โ Supports V8 coverage provider
- โ Includes file-level and overall coverage statistics
- โ Tracks uncovered lines for detailed analysis
- โ Compatible with Vitest 3.0+
- ๐ GitHub Actions: Coverage reporting, badge generation, and badge upload
- ๐ท๏ธ Coverage Badges: Shields.io compatible badges
- ๐ง Modular Design: Separate actions for different use cases
npm install --save-dev vitest-v8-json-coverage-summaryThis package includes three separate GitHub Actions that can be used independently:
Creates beautiful coverage reports in pull requests.
- name: Report Coverage
  uses: glideapps/vitest-v8-json-coverage-summary/actions/[email protected]
  with:
    coverage-file: "coverage/coverage-summary.json"
    title: "๐งช Test Coverage Report"
    show-files: "true"
    coverage-threshold: "80"Generates coverage badges from coverage data.
- name: Generate Badges
  uses: glideapps/vitest-v8-json-coverage-summary/actions/[email protected]
  with:
    coverage-file: "coverage/coverage-summary.json"
    badges-dir: "badges"Uploads badges to GitHub Pages.
- name: Upload Badges to GitHub Pages
  uses: glideapps/vitest-v8-json-coverage-summary/actions/[email protected]
  with:
    coverage-file: "coverage/coverage-summary.json"
    badges-dir: "badges"
    pages-branch: "gh-pages"
    generate-badges: "true"name: Coverage Report
on:
  pull_request:
    branches: [main]
permissions:
  pull-requests: write
jobs:
  coverage:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "20"
      - run: npm ci
      - run: npm test
      - uses: glideapps/vitest-v8-json-coverage-summary/actions/[email protected]
        with:
          coverage-file: "coverage/coverage-summary.json"name: Coverage with Badges
on:
  pull_request:
    branches: [main]
  push:
    branches: [main]
permissions:
  pull-requests: write
  contents: write
jobs:
  coverage:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "20"
      - run: npm ci
      - run: npm test
      - uses: glideapps/vitest-v8-json-coverage-summary/actions/[email protected]
  badges:
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    needs: coverage
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v4
        with:
          node-version: "20"
      - run: npm ci
      - run: npm test
      - uses: glideapps/vitest-v8-json-coverage-summary/actions/[email protected]
        with:
          generate-badges: "true"| Input | Description | Required | Default | 
|---|---|---|---|
| coverage-file | Path to the coverage summary JSON file | No | coverage/coverage-summary.json | 
| token | GitHub token for creating comments | No | ${{ github.token }} | 
| title | Title for the coverage report comment | No | ๐ Coverage Report | 
| show-files | Whether to show individual file coverage details | No | true | 
| coverage-threshold | Minimum coverage percentage to consider as good (0-100) | No | 80 | 
| Input | Description | Required | Default | 
|---|---|---|---|
| coverage-file | Path to the coverage summary JSON file | No | coverage/coverage-summary.json | 
| badges-dir | Directory to output the generated badges | No | badges | 
| Input | Description | Required | Default | 
|---|---|---|---|
| coverage-file | Path to the coverage summary JSON file | No | coverage/coverage-summary.json | 
| badges-dir | Directory containing the badges to upload | No | badges | 
| pages-branch | Branch to upload badges to for GitHub Pages | No | gh-pages | 
| pages-badges-dir | Directory within the pages branch to store badges | No | badges | 
| commit-message | Commit message for badge updates | No | Update coverage badges [skip ci] | 
| generate-badges | Whether to generate badges if they don't exist | No | true | 
When GitHub Pages is enabled, badges are available at:
https://yourusername.github.io/yourrepo/badges/coverage.json
https://yourusername.github.io/yourrepo/badges/statements.json
https://yourusername.github.io/yourrepo/badges/branches.json
https://yourusername.github.io/yourrepo/badges/functions.json
https://yourusername.github.io/yourrepo/badges/lines.json
Use in your README.md:
See the examples/ directory for complete workflow examples:
- coverage-only.yml- Only coverage reporting
- badge-generator-only.yml- Only badge generation
- badge-uploader-only.yml- Only badge upload
- full-workflow.yml- Complete workflow with all actions
// vitest.config.js
export default {
  coverage: {
    provider: "v8",
    reporter: ["json-summary"],
    reportsDirectory: "coverage",
  },
};- Go to Settings โ Pages
- Set source to "Deploy from a branch"
- Select gh-pagesbranch
- Set folder to / (root)or/badges
Add the reporter to your Vitest configuration:
// vitest.config.js
import { defineConfig } from "vitest/config";
import V8JSONSummaryReporter from "vitest-v8-json-coverage-summary";
export default defineConfig({
  test: {
    coverage: {
      provider: "v8",
      reporter: ["text", "json"],
      reportsDirectory: "./coverage",
    },
    reporters: ["default", new V8JSONSummaryReporter()],
  },
});The reporter generates a coverage-summary.json file in your coverage directory with the following structure:
{
  "summary": {
    "statements": 85.5,
    "branches": 72.3,
    "functions": 90.1,
    "lines": 85.5
  },
  "files": [
    {
      "file": "src/example.js",
      "statements": 95.2,
      "branches": 80.0,
      "functions": 100.0,
      "lines": 95.2,
      "uncoveredLines": [15, 23, 45]
    }
  ]
}- statements: Percentage of statements covered
- branches: Percentage of branch paths covered
- functions: Percentage of functions covered
- lines: Percentage of lines covered (matches statements for V8)
- uncoveredLines: Array of line numbers that are not covered (optional)
The main reporter class that implements Vitest's Reporter interface.
- onInit(vitest: Vitest): Called when the reporter is initialized
- onCoverage(coverage: any): Called when coverage data is available
- onTestRunEnd(): Called when the test run ends (kept for compatibility)
Utility function that processes V8 coverage data and returns a structured summary.
The reporter uses the coverage configuration from your Vitest config:
- coverage.reportsDirectory: Directory where the summary file will be written (default:- ./coverage)
- coverage.provider: Must be set to- 'v8'for this reporter to work
After running your tests with coverage, you'll find a coverage-summary.json file that looks like this:
{
  "summary": {
    "statements": 87.5,
    "branches": 75.0,
    "functions": 92.3,
    "lines": 87.5
  },
  "files": [
    {
      "file": "src/utils.js",
      "statements": 100.0,
      "branches": 100.0,
      "functions": 100.0,
      "lines": 100.0
    },
    {
      "file": "src/main.js",
      "statements": 75.0,
      "branches": 50.0,
      "functions": 85.7,
      "lines": 75.0,
      "uncoveredLines": [12, 15, 23]
    }
  ]
}# GitHub Actions example
- name: Run tests with coverage
  run: npm test
- name: Upload coverage summary
  uses: actions/upload-artifact@v3
  with:
    name: coverage-summary
    path: coverage/coverage-summary.jsonYou can use the generated JSON to create coverage badges or integrate with coverage reporting services.
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
MIT License - see LICENSE file for details.
- Initial release
- V8 coverage support
- JSON summary generation
- File-level and overall coverage statistics