modified: .gitignore

modified:   .vscode/launch.json
	new file:   e2e/playwright-collect-coverage.spec.ts
	modified:   package-lock.json
	modified:   package.json
	modified:   playwright.config.ts
	new file:   scripts/merge-lcov.cjs
	new file:   scripts/normalize-lcov.cjs
	new file:   scripts/playwright-collect-coverage.cjs
	new file:   scripts/remap-and-report.cjs
	modified:   vite.config.ts
	new file:   vitest.config.ts
This commit is contained in:
2025-12-02 16:14:12 +10:00
parent d0eb4e953c
commit 6192bd20eb
12 changed files with 1134 additions and 10 deletions
+57
View File
@@ -0,0 +1,57 @@
// e2e/playwright-collect-coverage.spec.ts
import fs from 'fs';
import path from 'path';
import { test } from '@playwright/test';
const EVAL_TIMEOUT_MS = 5000;
const WRITE_TIMEOUT_MS = 15000;
function withTimeout<T>(p: Promise<T>, ms: number, onTimeout?: () => void) {
let timer: NodeJS.Timeout | undefined;
const timeout = new Promise<T>((res) => {
timer = setTimeout(() => {
onTimeout?.();
// @ts-ignore resolve null on timeout
res(null);
}, ms);
});
return Promise.race([p, timeout]).then((r) => {
if (timer) clearTimeout(timer);
return r;
});
}
test.afterEach(async ({ page }, testInfo) => {
try {
console.log(`Collecting coverage for: ${testInfo.title}`);
// Evaluate coverage in page, but don't hang forever
const evalPromise = page.evaluate(() => (globalThis as any).__coverage__ || null);
const coverage = await withTimeout(evalPromise, EVAL_TIMEOUT_MS, () => {
console.warn('page.evaluate for coverage timed out');
});
if (!coverage || Object.keys(coverage).length === 0) {
console.log('No coverage collected (empty or timed out).');
return;
}
const dir = path.join(process.cwd(), '.nyc_output');
await fs.promises.mkdir(dir, { recursive: true });
const safeTitle = (testInfo.title || 'test').replace(/[^a-zA-Z0-9-_]/g, '_').slice(0, 120);
const worker = typeof testInfo.workerIndex === 'number' ? testInfo.workerIndex : process.pid;
const filename = path.join(dir, `coverage-e2e-w${worker}-${Date.now()}-${safeTitle}.json`);
// write asynchronously, bounded by timeout
const writePromise = fs.promises.writeFile(filename, JSON.stringify(coverage));
await withTimeout(writePromise, WRITE_TIMEOUT_MS, () => {
console.warn('Writing coverage file timed out');
});
console.log('Wrote coverage:', filename);
} catch (error: unknown) {
const msg = error instanceof Error ? error.message : String(error);
console.warn('Failed to collect coverage from page:', msg);
}
});