// Runs the end-to-end suites. No arguments: all of them, in parallel. Names: only those, e.g. `bun run e2e canvas tags`. import { spawn } from 'node:child_process'; import { readdirSync } from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); const electron = path.join(root, 'node_modules/.bin/electron'); const want = process.argv.slice(2); const all = readdirSync(path.join(root, 'test')).filter((f) => /^e2e.*\.test\.cjs$/.test(f)).sort(); const files = want.length ? all.filter((f) => want.some((w) => f === `e2e-${w}.test.cjs` || f === `e2e.test.cjs` && w === 'e2e')) : all; if (!files.length) { console.error(`No suite matches: ${want.join(', ')}`); process.exit(2); } // Timing-sensitive suites (they measure frame rate) run alone, after the rest, so the others can't slow them down. const SERIAL = ['e2e-board-drag.test.cjs']; const started = Date.now(); const run = (file) => new Promise((resolve) => { const t0 = Date.now(); const child = spawn(electron, [path.join('test', file), '--ozone-platform=headless'], { cwd: root }); let out = ''; child.stdout.on('data', (d) => (out += d)); child.stderr.on('data', (d) => (out += d)); child.on('close', (code) => { const lines = out.split('\n').filter((l) => /^(PASS|FAIL)|passed!|failed|harness/.test(l) && !/Fontconfig/.test(l)); const fails = lines.filter((l) => l.startsWith('FAIL') || /failed|harness/.test(l)); resolve({ file, code, secs: ((Date.now() - t0) / 1000).toFixed(0), fails, checks: lines.filter((l) => l.startsWith('PASS')).length }); }); }); const parallel = files.filter((f) => !SERIAL.includes(f)); const results = await Promise.all(parallel.map(run)); for (const f of files.filter((f) => SERIAL.includes(f))) results.push(await run(f)); for (const r of results) { const ok = r.code === 0; console.log(`${ok ? 'ok ' : 'FAIL'} ${r.file.padEnd(28)} ${String(r.checks).padStart(3)} checks ${r.secs}s`); if (!ok) for (const l of r.fails) console.log(' ' + l); } console.log(`\n${results.filter((r) => r.code === 0).length}/${results.length} suites passed in ${((Date.now() - started) / 1000).toFixed(0)}s`); process.exit(results.every((r) => r.code === 0) ? 0 : 1);