Skip to content

pokujs/coverage

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

93 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Poku's Logo

@pokujs/coverage

Stage: Experimental 🧟

Enjoying Poku? Give him a star to show your support

GitHub Workflow Status (Node.js) GitHub Workflow Status (Bun) GitHub Workflow Status (Deno)
GitHub Workflow Status (Linux) GitHub Workflow Status (OSX) GitHub Workflow Status (Windows)


☔️ @pokujs/coverage is a Poku plugin that unifies coverage collection across Node.js, Deno, and Bun.

Tip

  • @pokujs/coverage supports JSONC, YAML, and TOML config files. You can also use JavaScript and TypeScript by setting the options directly in the plugin.
  • The default reporter is designed for easy consumption by LLMs, pinpointing uncovered code with precise locations.

Why

  • Move and combine entire test suites between Node.js, Deno, and Bun with zero configuration changes.
  • Know exactly what is and isn't tested across each runtime using the same test suite.
  • Whether it's CommonJS, ES Modules, TypeScript, or both, just install and use it.

Quickstart

Install

npm i -D @pokujs/coverage

Usage

{
  "scripts": {
    "test:bun": "bun poku --coverage",
    "test:deno": "deno run -A npm:poku --coverage",
    "test:node": "poku --coverage"
  }
}
  • Then run the tests and a coverage summary will be printed after the suite results.

Options

Option Type Default Node.js Deno Bun
reporter Reporter | Reporter[] 'text'
include string[] []
exclude string[] list
all boolean false
src string | string[] [cwd]
extension string | string[] list
checkCoverage boolean | number undefined
statements number 0
branches number 0
functions number 0
lines number 0
perFile boolean false
skipFull boolean false
skipEmpty boolean false
watermarks Partial<Watermarks> [50, 80]
hyperlinks boolean | IDE true
reportsDirectory string './coverage'
excludeAfterRemap boolean true
tempDirectory string auto
clean boolean auto
config string | false undefined

Tip

.nycrc and .c8rc config files are supported and are automatically remapped, for example:

  • "check-coverage": true"checkCoverage": true
  • "100": truecheckCoverage: 100

Note

On Bun, branches and excludeAfterRemap options are silently ignored.


› reporter

Reporter Node.js Deno Bun
'text'
'lcov'
'lcovonly'
'text-lcov'
'text-summary'
'teamcity'
'json'
'json-summary'
'cobertura'
'clover'
'none'
'v8'
'jsc'

Note

  • On Bun, 'v8' falls back to 'jsc'.
  • On Node.js or Deno, 'jsc' falls back to 'v8'.
{
  "reporter": ["text", "lcov"]
}

› include

Glob patterns for files to include. When non-empty, only matching files appear in reports.

{
  "include": ["src/**"]
}

› exclude

Glob patterns for files to exclude. Replaces the default list when provided.

{
  "exclude": ["test/**", "**/*.spec.ts"]
}

› all

Walk the filesystem and report every source file under cwd, including those never touched by tests (reported as zero coverage).

{
  "all": true
}

› src

Root directories searched when all: true. Overrides cwd as the default walk root. Useful for monorepos. Relative paths are resolved against cwd.

{
  "all": true,
  "src": ["./packages/core/src", "./packages/api/src"]
}

› extension

File extensions considered by all: true discovery. Overrides the default list entirely.

{
  "all": true,
  "extension": [".ts", ".vue"]
}

› checkCoverage

Fail the run when coverage falls below the configured thresholds.

  • true: enable the check with all thresholds at 0 (silent no-op unless at least one per-metric threshold is set).
  • number: default threshold applied to every metric. Per-metric root keys override.
  • false / undefined: disabled.
{
  "checkCoverage": 95,
  "branches": 80
}

Above: statements, functions, and lines require 95; branches requires 80.


› statements

Minimum statements coverage percentage. Requires checkCoverage to be active.

{
  "checkCoverage": true,
  "statements": 90
}

› branches

Minimum branches coverage percentage. Requires checkCoverage to be active.

{
  "checkCoverage": true,
  "branches": 80
}

› functions

Minimum functions coverage percentage. Requires checkCoverage to be active.

{
  "checkCoverage": true,
  "functions": 90
}

› lines

Minimum lines coverage percentage. Requires checkCoverage to be active.

{
  "checkCoverage": true,
  "lines": 95
}

› perFile

Enforce thresholds per file instead of on aggregated totals.

{
  "checkCoverage": 95,
  "perFile": true
}

› skipFull

Hide fully-covered files (every non-null metric ≥ 100%) from the text reporter table. Totals are unaffected.

{
  "skipFull": true
}

› skipEmpty

Hide files with no executable code from the text reporter table. Totals are unaffected.

{
  "skipEmpty": true
}

› watermarks

[lowMax, highMin] thresholds for classifying percentages as low / medium / high in the text reporter.

{
  "watermarks": {
    "lines": [60, 85],
    "branches": [60, 85],
    "functions": [60, 85],
    "statements": [60, 85]
  }
}

› hyperlinks

Controls clickable file links in the text reporter.

  • true: plain file:// links.
  • <ide>: emit IDE-specific URLs.
  • false: disabled.

Available:

  • 'vscode'
  • 'jetbrains'
  • 'cursor'
  • 'windsurf'
  • 'vscode-insiders'
{
  "hyperlinks": "vscode"
}

› reportsDirectory

Directory where report files are written. Resolved relative to the Poku working directory.

{
  "reportsDirectory": "./coverage"
}

› excludeAfterRemap

When true, globs match original source paths (post source-map remap). When false, globs match transpiled paths (pre-remap, mirrors c8).

{
  "excludeAfterRemap": false
}

› tempDirectory

Directory where raw coverage data is written. When omitted, a temp dir is created and cleaned up automatically.

{
  "tempDirectory": "./.tmp-coverage"
}

› clean

Override temp-directory cleanup at teardown.

  • undefined: auto (clean only if auto-generated).
  • true: always clean.
  • false: never clean.
{
  "clean": false
}

› config

Path to a config file, or false to disable auto-discovery.

{
  "config": ".coveragerc"
}

You can also specify the config path via CLI:

poku --coverage --coverageConfig=.coveragerc test/

Tip

When no config is specified, the plugin automatically searches for the following files in the working directory (in order):

  • .coveragerc, .coveragerc.json, .coveragerc.jsonc, .coveragerc.toml, .coveragerc.yaml, .coveragerc.yml
  • .nycrc, .nycrc.json, .nycrc.jsonc, .nycrc.toml, .nycrc.yaml, .nycrc.yml
  • .c8rc, .c8rc.json, .c8rc.jsonc, .c8rc.toml, .c8rc.yaml, .c8rc.yml

Examples

Require --coverage flag

When using via plugin, by default, coverage runs whenever the plugin is active. Use requireFlag to only collect coverage when --coverage is passed to the CLI:

// poku.config.js
import { coverage } from '@pokujs/c8';
import { defineConfig } from 'poku';

export default defineConfig({
  plugins: [
    coverage({
      requireFlag: true,
    }),
  ],
});
# No coverage (plugin is a no-op)
poku test/

# With coverage
poku --coverage test/

Note

Priority order:

  • For config file discovery: --coverageConfig (CLI) > config (plugin option) > auto-discovery
  • For coverage options: plugin options > config file options

🍞 Why Bun Users Should Care

@pokujs/coverage extends Bun's coverage by tapping into the JSC Inspector directly, unlocking:

  • The full set of reporters (html, html-spa, jsc, json, json-summary, cobertura, clover, teamcity, text-summary, etc.).
  • Consistent options across runtimes (all,checkCoverage, include, exclude, extension, skipFull, skipEmpty, watermarks, etc.).
  • Support for /* jsc ignore */ directives (next, start/stop).
  • Real function names with per-function execution counts.
  • Accurate line hit counts derived from basic blocks, instead of binary covered/uncovered.
  • A richer LCOV built from the JSC data, with function records and real per-line counts.

Note

Branch coverage is not yet available under Bun. This is a limitation of the JSC Inspector, which Bun depends on.


🦕 Why Deno Users Should Care

  • The full set of reporters (html-spa, v8, json, json-summary, cobertura, clover, teamcity, text-summary, etc.).
  • Consistent options across runtimes (all, checkCoverage, include, exclude, extension, skipFull, skipEmpty, watermarks, etc.).
  • Compatibility with .nycrc / .c8rc config files, easing migration from existing coverage setups.

How It Works

  • 🐢 Under Node.js, the plugin sets NODE_V8_COVERAGE before Poku spawns tests. On teardown, the plugin reads the V8 JSON files from <tempDir> and forwards the data.
  • 🦕 Under Deno, the plugin sets DENO_COVERAGE_DIR before Poku spawns tests. On teardown, the plugin shells out to deno coverage <tempDir> and forwards the data.
  • 🍞 Under Bun, the plugin attaches to the JSC Inspector over WebSocket and captures basic-block execution counts via Runtime.getBasicBlocks. On teardown, the plugin reads the JSON files from <tempDir> and forwards the data.

File Exclusions

The plugin strips the following files from every report before they are emitted, so the numbers reflect only the source code you actually care about:

  • Every file Poku passes through its runner hook is recorded and dropped from reports since they are test files.
  • node_modules/ and .git/. directories are unconditionally banned from coverage output.

Acknowledgements and Credits

@pokujs/coverage internally adapts parts of the projects v8-to-istanbul, @jridgewell/trace-mapping, and istanbul-reports for multi-runtime support, enabling Istanbul reports for both Node.js, Deno, and Bun.

  • .js, .css, .png, and .ico assets from html and html-spa reporters are copied verbatim from istanbul-reports.

Also, a special thanks to c8 and Monocart Coverage Reports, repositories that served as a study base and as a reference for comparing results.


License

MIT © wellwelwel and contributors.

About

☔️ The world's first V8 and JSC coverage tool to generate reports for Node.js, Bun, Deno, and TypeScript at the same time.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Contributors