CI / policy (push) Successful in 7s
CI / validate (push) Successful in 41s
CI / build (push) Successful in 36s
CI / policy (pull_request) Successful in 10s
CI / validate (pull_request) Successful in 32s
CI / security (push) Successful in 1m3s
CI / test (push) Successful in 3m3s
CI / build (pull_request) Successful in 23s
CI / security (pull_request) Successful in 57s
CI / test (pull_request) Successful in 3m25s
CI / benchmark (push) Successful in 5m19s
CI / benchmark (pull_request) Successful in 4m48s
CI / images (push) Successful in 1m20s
CI / required (push) Successful in 3s
CI / images (pull_request) Successful in 54s
CI / required (pull_request) Successful in 1s
The generated HTML and Cobertura reports no longer show unmeasured branch and function coverage as 100%. Poll and waitFor deadlines use performance.now so frozen dates cannot make them loop forever, the malformed-configuration test covers undefined again next to the empty array, compose health checks honor PORT, and the migration spec lists only what is still open. Refs #291, #292, #293 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
56 lines
2.2 KiB
JavaScript
56 lines
2.2 KiB
JavaScript
// Converts coverage/lcov.info (Bun) to HTML and Cobertura. Run: bun scripts/coverage-reports.mjs
|
|
// shortcut: line coverage only, Bun's lcov has no usable branch/function data; revisit if Bun adds it.
|
|
// Totals here sum lines (8351/8578); Bun's text table averages per-file percentages, so it reads lower.
|
|
import { readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
import { join, resolve } from 'node:path';
|
|
import libCoverage from 'istanbul-lib-coverage';
|
|
import libReport from 'istanbul-lib-report';
|
|
import reports from 'istanbul-reports';
|
|
|
|
const map = libCoverage.createCoverageMap({});
|
|
const loc = (line) => ({ start: { line, column: 0 }, end: { line, column: 1 } });
|
|
for (const record of readFileSync('coverage/lcov.info', 'utf8').split('end_of_record')) {
|
|
const file = /^SF:(.+)$/m.exec(record)?.[1];
|
|
if (!file) continue;
|
|
const statementMap = {};
|
|
const s = {};
|
|
for (const [, line, hits] of record.matchAll(/^DA:(\d+),(\d+)/gm)) {
|
|
statementMap[line] = loc(+line);
|
|
s[line] = +hits;
|
|
}
|
|
map.addFileCoverage({
|
|
path: resolve(file),
|
|
statementMap,
|
|
s,
|
|
fnMap: {},
|
|
f: {},
|
|
branchMap: {},
|
|
b: {},
|
|
});
|
|
}
|
|
const context = libReport.createContext({ dir: 'coverage', coverageMap: map });
|
|
for (const name of ['html', 'cobertura']) reports.create(name).execute(context);
|
|
|
|
// Istanbul reports 0 branches/functions as 100%; relabel them instead of claiming coverage.
|
|
const rewrite = (file, edit) => writeFileSync(file, edit(readFileSync(file, 'utf8')));
|
|
for (const page of readdirSync('coverage', { recursive: true }).filter((f) => f.endsWith('.html')))
|
|
rewrite(join('coverage', page), (html) =>
|
|
html
|
|
.replace(
|
|
/<span class="strong">100% <\/span>(\s*<span class="quiet">(?:Branches|Functions)<\/span>\s*<span class='fraction'>)0\/0</g,
|
|
'<span class="strong">n/a </span>$1not collected<',
|
|
)
|
|
.replace(
|
|
/<td data-value="100" class="pct \w+">100%<\/td>(\s*)<td data-value="0" class="abs \w+">0\/0<\/td>/g,
|
|
'<td data-value="0" class="pct">n/a</td>$1<td data-value="0" class="abs">not collected</td>',
|
|
),
|
|
);
|
|
rewrite('coverage/cobertura-coverage.xml', (xml) =>
|
|
xml
|
|
.replaceAll('branch-rate="1"', 'branch-rate="0"')
|
|
.replace(
|
|
'<coverage ',
|
|
'<!-- Line coverage only: bun test does not collect branch or function coverage. -->\n<coverage ',
|
|
),
|
|
);
|