CtrlK
BlogDocsLog inGet started
Tessl Logo

testland/jest-coverage-analysis

Configures Jest's built-in coverage (Istanbul-instrumented `babel` provider or V8-native `v8` provider), wires the right `coverageReporters` for downstream consumption (`lcov` for SaaS / cross-tool, `cobertura` for Jenkins, `text-summary` for terminal, `html` for human review), authors per-file `coverageThreshold` rules that focus the gate on critical paths (vs the global-only foot-gun), and parses the per-file JSON output for PR-time deltas. Use when the project tests with Jest (or Vitest, which uses the same Istanbul/V8 provider) and the team needs PR-time coverage signal that's both local-runnable and CI-gateable.

74

Quality

93%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

Overview
Quality
Evals
Security
Files

parsing-and-anti-patterns.mdreferences/

Parsing coverage-final.json and coverage-gate anti-patterns

Companion detail for jest-coverage-analysis. The Jest / Vitest config in SKILL.md is the runnable core; this file holds the full JSON parser and the anti-pattern catalog.

The coverage-final.json shape

The json reporter writes coverage/coverage-final.json with a per-file structure keyed by absolute path:

{
  "/abs/path/src/checkout/cart.ts": {
    "path": "/abs/path/src/checkout/cart.ts",
    "statementMap": { "0": { "start": {}, "end": {} } },
    "fnMap": { },
    "branchMap": { },
    "s": { "0": 42, "1": 42, "2": 0 },
    "f": { "0": 42, "1": 0 },
    "b": { "0": [42, 0] }
  }
}

s = per-statement hit counts; f = per-function; b = per-branch arm.

Full per-file parser

// scripts/parse_jest_coverage.js
import { readFileSync } from 'node:fs';

const data = JSON.parse(readFileSync('coverage/coverage-final.json', 'utf8'));

for (const [absPath, file] of Object.entries(data)) {
  const stmts = Object.values(file.s);
  const stmtPct = (stmts.filter(c => c > 0).length / stmts.length) * 100;

  const fns = Object.values(file.f);
  const fnPct = (fns.filter(c => c > 0).length / fns.length) * 100;

  // Branch coverage: each entry is an array of arm hit counts.
  const branchEntries = Object.values(file.b);
  const branchTotal = branchEntries.flat().length;
  const branchHit = branchEntries.flat().filter(c => c > 0).length;
  const brPct = branchTotal === 0 ? 100 : (branchHit / branchTotal) * 100;

  console.log({ path: absPath, stmtPct, fnPct, brPct });
}

The coverage-summary.json file (from the json-summary reporter) is the pre-aggregated version when per-statement detail isn't needed.

Anti-patterns

Anti-patternWhy it failsFix
collectCoverage: false in CINo coverage data emitted; downstream gate is empty.--coverage flag in the test command (Step 7).
Skipping collectCoverageFromFiles with no test silently absent from denominator; coverage inflated.Always set explicitly (Step 4).
coverageThreshold.global only, no per-path rulesA new module under src/api/ joins at 0% coverage; global drops by 0.3pp; gate passes.Per-path rules for critical modules (Step 3).
Mixing babel and v8 ignore commentsOne provider misses the ignore; coverage drops mysteriously.Pick one; grep-replace if switching.
Using coverage-final.json as the gate inputPer-statement detail is huge; gate scripts slow.coverage-summary.json for whole-repo + lcov.info for per-line drilldown.
coverageDirectory: '/tmp/...' outside the repoCI artifact upload step misses it.Keep in coverage/ (default).
Threshold set at 100% on a global ruleFirst refactor fails the build; team disables coverage entirely.Set globals at the maintainable floor, not aspirational ceiling.

SKILL.md

tile.json