/** * Local development runner for scoped e2e tests. * * Detects which diagrams changed (comparing HEAD against a base ref) and * invokes Playwright with only the matching spec files. Falls back to the full * suite when shared code is touched. * * Playwright starts the dev server automatically when it is not already running * (see playwright.config.ts webServer). * * Usage via pnpm: * pnpm e2e:scope # base ref defaults to 'develop' * E2E_BASE_REF=main pnpm e2e:scope # override base ref */ import { execSync, spawn } from 'child_process'; import { detectScope, SKIP } from './e2e-diagram-scope.mjs'; const base = process.argv[2] ?? process.env.E2E_BASE_REF ?? 'develop'; let changedFiles: string[] = []; try { const output = execSync(`git diff --name-only ${base} HEAD`, { encoding: 'utf8' }); changedFiles = output.split('\n').filter(Boolean); } catch { /* eslint-disable no-console */ console.warn(`[e2e:scope] Could not diff against "${base}" — running full suite.`); } const spec = detectScope(changedFiles); if (spec === SKIP) { /* eslint-disable no-console */ console.log('[e2e:scope] Only docs/ignorable files changed — nothing to test.'); process.exit(0); } const playwrightArgs = ['test']; if (spec) { /* eslint-disable no-console */ console.log(`[e2e:scope] Scoped run:\n ${spec.split(',').join('\n ')}`); for (const pattern of spec.split(',')) { playwrightArgs.push(pattern); } } else { /* eslint-disable no-console */ console.log('[e2e:scope] Running full e2e suite (shared code changed or scope undetermined).'); } const child = spawn('playwright', playwrightArgs, { stdio: 'inherit' }); child.on('exit', (code) => process.exit(code ?? 0));