import assert from 'node:assert/strict';
import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { after, before, describe, it } from 'node:test';
import {
aggregateCoverage,
checkThresholds,
formatCoverageReport,
processCoverageReport,
runCoverageReport,
suggestThresholdIncreases,
} from './coverage-report.mjs';
const fullThresholds = { lines: 50, statements: 50, branches: 50, functions: 50 };
function location(line, column = 0) {
return { start: { line, column }, end: { line, column: column + 1 } };
}
function record({ statements = [], branches = [], functions = [] } = {}) {
return {
path: 'ignored-by-postprocessor.ts',
statementMap: Object.fromEntries(
statements.map(({ line }, index) => [String(index), location(line)]),
),
s: Object.fromEntries(statements.map(({ hits }, index) => [String(index), hits])),
branchMap: Object.fromEntries(
branches.map((_, index) => [
String(index),
{
type: 'if',
line: index + 1,
loc: location(index + 1),
locations: branches[index].map((_, locationIndex) =>
location(index + 1, locationIndex * 2),
),
},
]),
),
b: Object.fromEntries(branches.map((hits, index) => [String(index), hits])),
fnMap: Object.fromEntries(
functions.map((_, index) => [
String(index),
{
name: `fn${index}`,
decl: location(index + 1),
loc: location(index + 1),
line: index + 1,
},
]),
),
f: Object.fromEntries(functions.map((hits, index) => [String(index), hits])),
};
}
function packageConfig(packageDir, thresholds = fullThresholds) {
return { packageDir, config: { include: [], exclude: [], thresholds } };
}
function rootConfig(warningOnly = [], excludedPackages = []) {
return { warningOnly, excludedPackages };
}
function warning(overrides = {}) {
return {
package: 'group/a',
reason: 'Coverage recovery needs dedicated tests.',
addedDate: '2026-01-01',
expiryDays: 10,
assignee: 'Ada',
linear: 'TML-123',
notes: null,
...overrides,
};
}
function process({
root,
report,
packageConfigs = [packageConfig('packages/group/a')],
warnings = [],
excludedPackages = [],
now = new Date('2026-01-05T12:00:00Z'),
}) {
return processCoverageReport({
root,
report,
packageConfigs,
rootConfig: rootConfig(warnings, excludedPackages),
now,
});
}
describe('coverage report', () => {
let root;
before(async () => {
root = await mkdtemp(join(tmpdir(), 'coverage-report-'));
});
after(async () => {
await rm(root, { recursive: true, force: true });
});
it('groups absolute and root-relative paths by longest package path', () => {
const report = {
[join(root, 'packages/group/a/src/absolute.ts')]: record({
statements: [{ line: 1, hits: 1 }],
}),
'packages/group/a/src/relative.ts': record({ statements: [{ line: 2, hits: 1 }] }),
'packages/group/a/nested/src/deep.ts': record({ statements: [{ line: 3, hits: 1 }] }),
};
const packages = aggregateCoverage({
root,
report,
packageConfigs: [packageConfig('packages/group/a'), packageConfig('packages/group/a/nested')],
});
assert.deepEqual(
packages.map(({ packageDir, files }) => [packageDir, files]),
[
[
'packages/group/a',
['packages/group/a/src/absolute.ts', 'packages/group/a/src/relative.ts'],
],
['packages/group/a/nested', ['packages/group/a/nested/src/deep.ts']],
],
);
});
it('assigns cross-package imports to the source owner', () => {
const packages = aggregateCoverage({
root,
report: {
'packages/group/b/src/imported-by-a.ts': record({ statements: [{ line: 1, hits: 1 }] }),
},
packageConfigs: [packageConfig('packages/group/a'), packageConfig('packages/group/b')],
});
assert.equal(packages[0].present, false);
assert.equal(packages[1].present, true);
assert.deepEqual(packages[1].files, ['packages/group/b/src/imported-by-a.ts']);
});
it('accepts Vitest 4 Istanbul locations and metadata', async () => {
const fixture = JSON.parse(
await readFile(join(import.meta.dirname, 'fixtures/vitest-4-coverage-final.json'), 'utf8'),
);
const [result] = aggregateCoverage({
root,
report: fixture,
packageConfigs: [packageConfig('packages/group/a')],
});
assert.equal(result.present, true);
assert.deepEqual(result.metrics, {
lines: { total: 1, covered: 1, pct: 100 },
statements: { total: 1, covered: 1, pct: 100 },
branches: { total: 2, covered: 1, pct: 50 },
functions: { total: 1, covered: 1, pct: 100 },
});
});
it('aggregates lines, statements, flattened branches, and functions', () => {
const [result] = aggregateCoverage({
root,
report: {
'packages/group/a/src/a.ts': record({
statements: [
{ line: 10, hits: 0 },
{ line: 10, hits: 2 },
{ line: 11, hits: 0 },
],
branches: [
[0, 3],
[1, 0, 2],
],
functions: [0, 4],
}),
'packages/group/a/src/b.ts': record({
statements: [{ line: 10, hits: 0 }],
branches: [[1]],
functions: [1],
}),
},
packageConfigs: [packageConfig('packages/group/a')],
});
assert.deepEqual(result.metrics, {
lines: { total: 3, covered: 1, pct: (1 / 3) * 100 },
statements: { total: 4, covered: 1, pct: 25 },
branches: { total: 6, covered: 4, pct: (2 / 3) * 100 },
functions: { total: 3, covered: 2, pct: (2 / 3) * 100 },
});
});
it('uses 100 percent for zero totals', () => {
const [result] = aggregateCoverage({
root,
report: { 'packages/group/a/src/types.ts': record() },
packageConfigs: [packageConfig('packages/group/a')],
});
assert.deepEqual(result.metrics, {
lines: { total: 0, covered: 0, pct: 100 },
statements: { total: 0, covered: 0, pct: 100 },
branches: { total: 0, covered: 0, pct: 100 },
functions: { total: 0, covered: 0, pct: 100 },
});
});
it('compares equality and every optional threshold', () => {
const metrics = {
lines: { total: 2, covered: 1, pct: 50 },
statements: { total: 4, covered: 2, pct: 50 },
branches: { total: 5, covered: 2, pct: 40 },
functions: { total: 10, covered: 3, pct: 30 },
};
assert.deepEqual(checkThresholds(metrics, fullThresholds), [
{ metric: 'branches', actual: 40, threshold: 50 },
{ metric: 'functions', actual: 30, threshold: 50 },
]);
assert.deepEqual(checkThresholds(metrics, {}), []);
});
it('classifies active warnings as nonblocking deficits', () => {
const result = process({
root,
report: {
'packages/group/a/src/a.ts': record({ statements: [{ line: 1, hits: 0 }] }),
},
warnings: [warning()],
now: new Date('2026-01-11T23:59:59Z'),
});
assert.equal(result.ok, true);
assert.equal(result.packages[0].status, 'warning');
assert.equal(result.warnings.length, 1);
assert.equal(result.failures.length, 0);
assert.match(formatCoverageReport(result), /TECHNICAL DEBT/);
assert.match(formatCoverageReport(result), /Ada/);
assert.match(formatCoverageReport(result), /TML-123/);
assert.match(formatCoverageReport(result), /2026-01-11/);
});
it('blocks expired warning entries even when coverage passes', () => {
const result = process({
root,
report: {
'packages/group/a/src/a.ts': record({ statements: [{ line: 1, hits: 1 }] }),
},
warnings: [warning()],
now: new Date('2026-01-12T00:00:00Z'),
});
assert.equal(result.ok, false);
assert.equal(result.packages[0].status, 'expired-warning');
assert.equal(result.expiredWarnings.length, 1);
assert.match(formatCoverageReport(result), /EXPIRED COVERAGE WARNINGS/);
});
it('blocks ordinary deficits with metric details', () => {
const result = process({
root,
report: {
'packages/group/a/src/a.ts': record({
statements: [{ line: 1, hits: 0 }],
branches: [[0]],
functions: [0],
}),
},
});
assert.equal(result.ok, false);
assert.equal(result.packages[0].status, 'failed');
assert.deepEqual(
result.failures[0].deficits.map(({ metric }) => metric),
['lines', 'statements', 'branches', 'functions'],
);
assert.match(formatCoverageReport(result), /lines: 0\.00% < 50%/);
});
it('ignores excluded packages before owner resolution', () => {
const result = process({
root,
report: {
'packages/group/a/src/a.ts': record({ statements: [{ line: 1, hits: 1 }] }),
'packages/group/skip/src/skip.ts': record({ statements: [{ line: 1, hits: 0 }] }),
},
packageConfigs: [packageConfig('packages/group/a'), packageConfig('packages/group/skip')],
excludedPackages: ['group/skip'],
});
assert.equal(result.ok, true);
assert.deepEqual(
result.packages.map(({ packageDir }) => packageDir),
['packages/group/a'],
);
assert.deepEqual(result.skipped, ['packages/group/skip']);
});
it('rejects malformed records', () => {
const malformed = [
null,
{ ...record(), s: { 0: 'one' } },
{ ...record({ statements: [{ line: 1, hits: 1 }] }), statementMap: {} },
{
...record({ statements: [{ line: 1, hits: 1 }] }),
statementMap: { 0: location(0) },
},
{ ...record({ branches: [[1]] }), b: {} },
{ ...record({ branches: [[1, 0]] }), b: { 0: [1] } },
{ ...record(), b: { 0: [1, -1] } },
{ ...record({ functions: [1] }), f: {} },
{ ...record(), f: { 0: 1.5 } },
];
for (const value of malformed) {
assert.throws(
() =>
aggregateCoverage({
root,
report: { 'packages/group/a/src/a.ts': value },
packageConfigs: [packageConfig('packages/group/a')],
}),
/Invalid Istanbul coverage record/,
);
}
});
it('rejects unowned and outside-root paths', () => {
assert.throws(
() =>
aggregateCoverage({
root,
report: { 'packages/unknown/src/a.ts': record() },
packageConfigs: [packageConfig('packages/group/a')],
}),
/no configured package owner/i,
);
assert.throws(
() =>
aggregateCoverage({
root,
report: { [join(root, '..', 'outside.ts')]: record() },
packageConfigs: [packageConfig('packages/group/a')],
}),
/outside repository root/i,
);
assert.throws(
() =>
aggregateCoverage({
root,
report: { '../outside.ts': record() },
packageConfigs: [packageConfig('packages/group/a')],
}),
/outside repository root/i,
);
});
it('blocks absent packages with thresholds without inventing metric deficits', () => {
const result = process({ root, report: {} });
const output = formatCoverageReport(result);
assert.equal(result.ok, false);
assert.equal(result.packages[0].present, false);
assert.equal(result.packages[0].status, 'missing');
assert.equal(result.packages[0].metrics.lines.pct, 100);
assert.deepEqual(result.packages[0].deficits, []);
assert.deepEqual(result.failures, [
{ packageDir: 'packages/group/a', reason: 'absent-from-report' },
]);
assert.match(output, /BLOCKING COVERAGE FAILURES/);
assert.match(output, /Missing from coverage report/);
assert.doesNotMatch(output, /0\.00% < 50%/);
});
it('warns visibly when an active warning-only package is absent', () => {
const result = process({ root, report: {}, warnings: [warning()] });
const output = formatCoverageReport(result);
assert.equal(result.ok, true);
assert.equal(result.packages[0].status, 'missing-warning');
assert.deepEqual(result.warnings[0], {
packageDir: 'packages/group/a',
reason: 'absent-from-report',
entry: warning(),
expiryDate: '2026-01-11',
});
assert.match(output, /TECHNICAL DEBT - NONBLOCKING COVERAGE WARNINGS/);
assert.match(output, /Missing from coverage report/);
assert.doesNotMatch(output, /0\.00% < 50%/);
});
it('warns when an active warning-only package without thresholds is absent', () => {
const result = process({
root,
report: {},
packageConfigs: [packageConfig('packages/group/a', {})],
warnings: [warning()],
});
assert.equal(result.ok, true);
assert.equal(result.packages[0].status, 'missing-warning');
assert.equal(result.warnings[0].reason, 'absent-from-report');
assert.match(formatCoverageReport(result), /Missing from coverage report/);
});
it('keeps absent source-free packages without thresholds at empty 100 percent metrics', () => {
const result = process({
root,
report: {},
packageConfigs: [packageConfig('packages/group/a', {})],
});
const output = formatCoverageReport(result);
assert.equal(result.ok, true);
assert.equal(result.packages[0].present, false);
assert.equal(result.packages[0].status, 'no-threshold');
assert.equal(result.packages[0].metrics.lines.pct, 100);
assert.match(output, /ABSENT FROM REPORT/);
assert.match(output, /No source entries; no thresholds configured/);
assert.doesNotMatch(output, /NO THRESHOLDS/);
});
it('identifies empty thresholds without failing', () => {
const result = process({
root,
report: { 'packages/group/a/src/a.ts': record({ statements: [{ line: 1, hits: 0 }] }) },
packageConfigs: [packageConfig('packages/group/a', {})],
});
assert.equal(result.ok, true);
assert.equal(result.packages[0].status, 'no-threshold');
assert.match(formatCoverageReport(result), /NO THRESHOLDS/);
});
it('suggests aggregate threshold increases with margin and cap', () => {
const metrics = {
lines: { total: 100, covered: 96, pct: 96 },
statements: { total: 100, covered: 94, pct: 94 },
branches: { total: 100, covered: 90, pct: 90 },
functions: { total: 100, covered: 100, pct: 100 },
};
assert.deepEqual(
suggestThresholdIncreases(
metrics,
{ lines: 80, statements: 90, branches: 86, functions: 90 },
5,
95,
),
{
lines: { current: 80, actual: 96, suggested: 95 },
functions: { current: 90, actual: 100, suggested: 95 },
},
);
});
it('renders passing and threshold suggestion summaries', () => {
const result = process({
root,
report: {
'packages/group/a/src/a.ts': record({
statements: [{ line: 1, hits: 1 }],
branches: [[1]],
functions: [1],
}),
},
packageConfigs: [
packageConfig('packages/group/a', {
lines: 80,
statements: 80,
branches: 80,
functions: 80,
}),
],
});
const output = formatCoverageReport(result);
assert.match(output, /PASSING/);
assert.match(output, /THRESHOLD INCREASE SUGGESTIONS/);
assert.match(output, /lines: 80 -> 95/);
});
it('counts expired-warning deficits in the summary failure total', () => {
const result = process({
root,
report: {
'packages/group/a/src/a.ts': record({
statements: [{ line: 1, hits: 0 }],
branches: [[0]],
functions: [0],
}),
},
warnings: [warning()],
now: new Date('2026-01-12T00:00:00Z'),
});
assert.equal(result.failures.length, 1);
assert.match(formatCoverageReport(result), /Failures: 1/);
});
it('fails for missing and malformed root reports', async () => {
const fixture = await mkdtemp(join(tmpdir(), 'coverage-report-files-'));
try {
await writeFile(
join(fixture, 'coverage.config.json'),
JSON.stringify({ warningOnly: [], excludedPackages: [] }),
);
await mkdir(join(fixture, 'packages/group/a'), { recursive: true });
await writeFile(
join(fixture, 'packages/group/a/coverage.config.json'),
JSON.stringify({ include: [], exclude: [], thresholds: {} }),
);
await assert.rejects(() => runCoverageReport({ root: fixture }), /coverage-final\.json/);
await mkdir(join(fixture, 'coverage'), { recursive: true });
await writeFile(join(fixture, 'coverage/coverage-final.json'), '{not json');
await assert.rejects(() => runCoverageReport({ root: fixture }), /Malformed coverage report/);
await writeFile(join(fixture, 'coverage/coverage-final.json'), '[]');
await assert.rejects(
() => runCoverageReport({ root: fixture }),
/coverage report must be an object/i,
);
} finally {
await rm(fixture, { recursive: true, force: true });
}
});
});