/** * Browser smoke test: serve the built app, load the demo data, run a * short benchmark, and check that scores and the explorer arrive. Uses * the system Chrome; no microphone is involved (demo data is synthetic). * Run `npm run build` first, then `vite-node scripts/smoke-browser.ts`. */ import { chromium } from 'playwright-core'; import { preview } from 'vite'; const server = await preview({ preview: { port: 4173, strictPort: false } }); const url = server.resolvedUrls!.local[0]; console.log('serving', url); const browser = await chromium.launch({ executablePath: '/usr/bin/google-chrome', headless: true, }); const page = await browser.newPage(); const errors: string[] = []; page.on('pageerror', (e) => errors.push(`pageerror: ${e.message}`)); page.on('console', (m) => { if (m.type() === 'error') errors.push(`console: ${m.text()}`); }); try { await page.goto(url, { waitUntil: 'networkidle' }); await page.click('#load-demo'); await page.waitForFunction(() => document.querySelectorAll('.type-row').length === 3); const counts = await page.$$eval('.type-row .count', (els) => els.map((e) => e.textContent)); console.log('type rows:', counts); // shrink the benchmark so the smoke test stays quick await page.evaluate(() => { const inputs = [...document.querySelectorAll('#config-grid input')]; const set = (label: string, v: string) => { const el = inputs.find((i) => i.parentElement!.textContent!.includes(label))!; el.value = v; el.dispatchEvent(new Event('change')); }; set('dataset duration', '15'); set('events per type', '15'); set('runs', '2'); }); await page.click('#run-bench'); await page.waitForFunction( () => document.getElementById('status')!.textContent!.includes('benchmark complete'), undefined, { timeout: 180000 }, ); const rows = await page.$$eval('#results > table.results tr', (trs) => trs.slice(1).map((tr) => [...tr.children].map((td) => td.textContent).join(' | '))); console.log('results:'); for (const r of rows) console.log(' ', r); const explorerVisible = await page.$eval('#explorer', (c) => (c as HTMLCanvasElement).height > 100); console.log('explorer canvas populated:', explorerVisible); // accuracy of the two real baselines should beat 0.5 on demo data const accs = rows.map((r) => Number(r.split('|')[1].trim().split(' ')[0])); if (rows.length !== 5) throw new Error(`expected 5 result rows, got ${rows.length}`); if (!(accs[0] > 0.5 && accs[1] > 0.5)) throw new Error(`accuracies too low: ${accs.join(', ')}`); if (errors.length) throw new Error(`page errors:\n${errors.join('\n')}`); console.log('SMOKE PASS'); } finally { await browser.close(); await server.close(); }