* test(ci): prove shared toolkit with real PromptManager host coverage * test(ci): match KikoTools Python 3.13 compatibility coverage
61 lines
3.7 KiB
JavaScript
61 lines
3.7 KiB
JavaScript
import { readFileSync, readdirSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
import { dirname, join, relative } from 'node:path';
|
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
import { spawnSync } from 'node:child_process';
|
|
import { repositoryRoot } from './vendor-viewerjs.mjs';
|
|
|
|
import { discoverSources, checkCoverage } from '@comfyassets/toolkit/testing/coverage';
|
|
export { discoverSources, checkCoverage };
|
|
const metrics = ['lines', 'branches', 'functions', 'statements'];
|
|
|
|
function run(args, env = {}) {
|
|
const result = spawnSync(process.execPath, args, { cwd: repositoryRoot, stdio: 'inherit',
|
|
env: { ...process.env, ...env } });
|
|
if (result.status !== 0) throw new Error(`Command failed (${result.status}): ${args.join(' ')}`);
|
|
}
|
|
|
|
async function main() {
|
|
const tools = dirname(fileURLToPath(import.meta.url));
|
|
const reportRoot = join(repositoryRoot, 'coverage/js');
|
|
const raw = join(reportRoot, 'raw');
|
|
const sourceRoot = join(repositoryRoot, 'web/js');
|
|
const files = discoverSources(sourceRoot);
|
|
rmSync(reportRoot, { recursive: true, force: true });
|
|
mkdirSync(raw, { recursive: true });
|
|
const tests = readdirSync(join(repositoryRoot, 'tests/js')).filter(file => file.endsWith('.test.js')).map(file => `tests/js/${file}`);
|
|
run(['--test', ...tests], { NODE_V8_COVERAGE: raw });
|
|
const playwright = join(tools, 'node_modules/@playwright/test/cli.js');
|
|
run([playwright, 'test', '--config', join(tools, 'playwright.config.mjs')]);
|
|
run([playwright, 'test', '--config', join(tools, 'playwright.workflows.config.mjs'),
|
|
'--project', 'chromium', '--project', 'touch'], { PM_JS_COVERAGE: raw });
|
|
run([join(tools, 'node_modules/c8/bin/c8.js'), 'report', '--all', '--src', sourceRoot,
|
|
'--include', 'web/js/**/*.js', '--include', 'web/js/**/*.mjs', '--temp-directory', raw, '--reports-dir', reportRoot,
|
|
'--reporter', 'text', '--reporter', 'json-summary', '--reporter', 'html']);
|
|
const summary = JSON.parse(readFileSync(join(reportRoot, 'coverage-summary.json'), 'utf8'));
|
|
const baselinePath = join(tools, 'frontend-coverage-baseline.json');
|
|
if (process.argv.includes('--update-baseline')) {
|
|
const previous = JSON.parse(readFileSync(baselinePath, 'utf8'));
|
|
const failures = checkCoverage(summary, previous, sourceRoot, files.filter(file => previous[file]));
|
|
if (failures.length) throw new Error(`Baseline updates cannot lower coverage:\n${failures.join('\n')}`);
|
|
const next = Object.fromEntries(files.map(file => {
|
|
const measured = summary[join(sourceRoot, file)];
|
|
if (!measured || metrics.some(metric => !Number.isFinite(measured[metric]?.pct))) {
|
|
throw new Error(`Missing coverage for ${file}`);
|
|
}
|
|
if (Object.keys(previous).length && !previous[file] && measured.lines.pct < 80) {
|
|
throw new Error(`New frontend files need at least 80% line coverage: ${file}`);
|
|
}
|
|
return [file, Object.fromEntries(metrics.map(metric => [metric, Math.max(previous[file]?.[metric] || 0, Math.floor(measured[metric].pct) - 2, 0)]))];
|
|
}));
|
|
writeFileSync(baselinePath, JSON.stringify(next, null, 2) + '\n');
|
|
} else {
|
|
const baseline = JSON.parse(readFileSync(baselinePath, 'utf8'));
|
|
const failures = checkCoverage(summary, baseline, sourceRoot, files);
|
|
if (failures.length) throw new Error(`Frontend coverage regressed:\n${failures.join('\n')}`);
|
|
}
|
|
console.log(`Frontend coverage passed for ${files.length} files. Report: ${relative(repositoryRoot, reportRoot)}/index.html`);
|
|
}
|
|
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
main().catch(error => { console.error(error.message); process.exitCode = 1; });
|
|
}
|