Coverage CLI

Strict inputs, explicit hosts, stable exit codes.

The CLI wraps native Node and Chrome coverage without changing the shared source. Its configuration rejects ambiguous keys and paths before either collector starts.

Commands

vanilla-test coverage [all|node|chrome] [options]

vanilla-test coverage
vanilla-test coverage all
vanilla-test coverage node
vanilla-test coverage chrome

# equivalent short aliases
vanilla-test all
vanilla-test node
vanilla-test chrome
Check the terminal.

The suite report and any collector errors appear there. Use the process exit status for automation and the generated report directory for coverage details.

coverage, coverage all, and the all alias run Node first, then Chrome. The node and chrome aliases select one collector. Running vanilla-test with no arguments prints help and exits with status 0.

An ordinary assertion or threshold failure in Node does not discard its report or prevent the Chrome collector from producing its own report.

Repository contributors can use the npm scripts below. Run a script exactly as shown; append CLI options after --.

npm commandUnderlying commandPurpose
npm testnpm run test:core && npm run test:toolingRun every core and tooling test.
npm run test:corenode ./test/node.jsRun the shared core suite directly in Node.js.
npm run test:toolingnode --test ./test/tooling.js ./test/output.js ./test/server-security.js ./test/status-builder.js ./test/benchmark.jsRun CLI, report, output, server-security, benchmark-harness, and site-status tests.
npm run benchmarknode ./benchmark/run.jsRun the one-million-case native Node and Chrome end-to-end benchmark after npm ci --prefix benchmark.
npm run benchmark:smokenode ./benchmark/run.js --cases 101 ...Verify all benchmark adapters, native collectors, result validation, and report writes with a small workload.
npm run coveragenode ./bin/vanilla-test.js coverageRun the Node and Chrome collectors.
npm run coverage:nodenode ./bin/vanilla-test.js coverage nodeRun only Node coverage.
npm run coverage:chromenode ./bin/vanilla-test.js coverage chromeRun only Chrome coverage.
npm run site:statusnode ./scripts/build-site-status.js --run-toolingRefresh site status data and Shields badges from current artifacts.
npm run screenshotsnode ./scripts/screenshots.jsSmoke-test the playground in Chrome, then regenerate the browser and native-report screenshots after coverage.
npm startnode ./scripts/serve.jsServe the repository and documentation locally.
npm run coverage -- --timeout-ms 60000
npm run coverage:chrome -- --headed
npm run coverage:chrome -- --chrome-path "/opt/google/chrome/google-chrome"
Check the terminal after every npm command.

Test output and failures appear there. Coverage metrics are written to the configured reportsDirectory.

Options

OptionBehavior
--config <path>Use a JSON configuration file. Default: vanilla-test.config.json in the current directory.
--chrome-path <path>Launch an explicit Google Chrome executable. The resolved target must be an executable file.
--headedShow Chrome during the browser run, overriding chrome.headless.
--timeout-ms <ms>Override timeoutMs with a positive integer up to 3,600,000.
--helpPrint command usage.
--versionPrint the installed package version.

Options may appear once. Unknown arguments, duplicate options, or options missing a value are usage errors.

Configuration

Paths are resolved from the directory containing the configuration file, not from whichever directory contains the installed package.

{
    "entry": "./test/CI.js",
    "reportsDirectory": "./coverage",
    "thresholds": {
        "statements": 100,
        "branches": 100,
        "functions": 100,
        "lines": 100
    },
    "timeoutMs": 30000,
    "node": {
        "include": ["index.js"]
    },
    "chrome": {
        "include": ["index.js"],
        "imports": {},
        "headless": true,
        "executablePath": null
    }
}
KeyRequired/defaultContract
entryRequiredExisting project-local module exporting a default function or named run().
reportsDirectory./coverageProject-local parent for atomically staged, runtime-owned reports.
thresholdsEvery metric defaults to 100If present, contains all four numeric percentages—statements, branches, functions, and lines—from 0 through 100.
timeoutMs30000Integer from 1 through 3,600,000.
nodeRequired for all/nodeNode collector object. It may be omitted for a Chrome-only run.
node.includeRequired with nodeNonempty array of positive project-relative globs. At least one file must match.
chromeRequired for all/chromeChrome collector object. It may be omitted for a Node-only run.
chrome.includeRequired with chromeIndependent nonempty include scope for Chrome. At least one file must match.
chrome.imports{}Additional or overriding browser specifiers mapped to files inside the project.
chrome.headlesstrueBoolean selecting visible or headless Chrome. CLI --headed forces false.
chrome.executablePathnullString path or null. A config path is resolved from the configuration directory. CLI --chrome-path takes precedence.

When you run only one collector, its sibling configuration object is optional: a Node-only configuration may omit chrome, and a Chrome-only configuration may omit node. The all target requires both objects.

Choose Chrome with executablePath

null is the portable default, not a placeholder. It tells vanilla-test to check CHROME_PATH, standard Google Chrome Stable locations on Windows, macOS, and Linux, then Chrome executable names available on PATH.

{
    "chrome": {
        "include": ["index.js"],
        "imports": {},
        "headless": true,
        "executablePath": null
    }
}

Use a committed string when every machine shares one nonstandard installation. JSON requires Windows backslashes to be escaped:

{
    "chrome": {
        "include": ["index.js"],
        "imports": {},
        "headless": true,
        "executablePath": "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe"
    }
}

For machine-specific and CI installations, leave the config at null and use an environment or command-line override:

# PowerShell
$env:CHROME_PATH = 'C:\Program Files\Google\Chrome\Application\chrome.exe'
npm run coverage:chrome
npm run coverage:chrome -- --chrome-path 'D:\Browsers\Chrome\chrome.exe'

# macOS or Linux shell
CHROME_PATH=/usr/bin/google-chrome-stable npm run coverage:chrome
npm run coverage:chrome -- --chrome-path "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
Check the terminal.

A missing, non-file, or non-executable Chrome path is reported as a harness error with exit status 2.

Keep Chrome's sandbox enabled by default. On an isolated Linux CI runner that cannot provide a usable Chrome sandbox, opt out for that job only:

VANILLA_TEST_CHROME_NO_SANDBOX=1 npm run coverage
Check the terminal. This is a CI escape hatch, not a normal default.

The variable accepts only 0, 1, an empty value, or an unset value; empty and unset both preserve the sandbox. 1 adds Chrome's --no-sandbox flag and reduces browser isolation; do not use it on a general-purpose workstation or an untrusted shared runner.

PrecedenceSourcePath base
1 (highest)--chrome-path <path>Current shell directory
2String chrome.executablePathConfiguration-file directory
3CHROME_PATHEnvironment value
4Stable-location and PATH discoveryOperating system

Entry result contract

The imported entry may return synchronously or asynchronously. Its result must expose consistent ok and failureCount values:

{ ok: true, failureCount: 0 }
{ ok: false, failureCount: 2 }

Missing, negative, non-integer, or contradictory values are harness failures. This prevents an incomplete or malformed suite from being treated as a successful run.

Path and import safety

  • Entry, reports, included source, and browser-import targets must stay inside the configuration root after real-path resolution.
  • Include scopes accept positive globs only; absolute paths, parent traversal, and ! negation are rejected.
  • Browser import targets must be local files. Remote URLs and protocol-relative URLs are rejected.
  • The temporary browser server permits only GET and HEAD, requires its exact loopback Host, denies dotfiles and common secret/key paths, and rejects traversal and link escapes.
  • The Chrome page blocks requests outside the bound coverage origin; local responses add CSP, CORP, no-referrer, no-sniff, frame-denial, and no-store headers.
  • Unknown configuration keys are errors rather than silently ignored settings.
Configuration is an allowlist.

Keep source scope and browser imports narrow enough that a coverage run cannot accidentally serve or measure unrelated files.

Exit statuses

StatusMeaningCI interpretation
0Tests and coverage thresholds passed.Success.
1An assertion failed or a coverage threshold was missed.Product/test failure.
2Usage, configuration, missing runtime prerequisite, launch, timeout, or malformed-result failure.Harness/infrastructure failure.
130The process was interrupted by SIGINT or SIGTERM.Cancelled/interrupted run.

Output layout

coverage/
  node/
    .vanilla-test-coverage.json
    index.html
    lcov.info
    coverage-summary.json
    test-results.json
  chrome/
    .vanilla-test-coverage.json
    index.html
    lcov.info
    coverage-summary.json
    test-results.json
    vanilla-test-chrome.png
ArtifactMeaning
index.htmlStandalone project-owned native V8 coverage report.
lcov.infoNative metrics in conventional LCOV transport form.
coverage-summary.jsonAggregate and per-file native metric totals.
test-results.jsonPlain, ANSI-free suite status, counts, and descriptions.
.vanilla-test-coverage.jsonRuntime ownership marker used to protect unrelated directories.
vanilla-test-chrome.pngSuccessful Chrome harness screenshot; Chrome output only.

A collector builds a complete report in a temporary sibling directory. After a valid completed run—even a test or threshold failure—it atomically replaces only a report carrying the matching ownership marker. An unowned directory is refused. Configuration, harness, timeout, collector, or interruption failures clean up staging and preserve the previous known-good report. Running both collectors retains both final reports. The documentation site's coverage page normalizes those summaries and links the complete published reports.

CI recipe

- run: npm ci
- run: npm test
- run: npm run coverage -- --chrome-path "$CHROME_PATH"
Check the CI terminal log.

Keep the exit status and uploaded runtime reports as separate evidence for each gate.

Install Google Chrome Stable explicitly in CI and log the exact Node and Chrome versions beside the artifacts. Treat the Node test matrix, coverage collectors, and packed-artifact smoke as separate required gates before publishing quality data.