diff --git a/scripts/terminal-bench.mjs b/scripts/terminal-bench.mjs index 7e1074b..1604fdb 100644 --- a/scripts/terminal-bench.mjs +++ b/scripts/terminal-bench.mjs @@ -142,6 +142,7 @@ async function main() { const { chromium } = await importPlaywright(); fs.mkdirSync(options.outputDir, { recursive: true }); + console.error(`[terminal-bench] launching browser${browserLaunchLabel(options)}`); const browser = await chromium.launch(browserLaunchOptions(options)); const results = []; try { @@ -162,6 +163,9 @@ async function main() { } async function runScenario(browser, options, viewport) { + console.error( + `[terminal-bench] ${viewport.name}: starting ${options.lines} line output`, + ); const context = await browser.newContext({ viewport: { width: viewport.width, height: viewport.height }, deviceScaleFactor: 1, @@ -188,13 +192,16 @@ async function runScenario(browser, options, viewport) { requestAnimationFrame(sample); }); - const command = `for i in $(seq 1 ${options.lines}); do printf 'bench-%05d abcdefghijklmnopqrstuvwxyz\\\\n' "$i"; done`; + const command = `for i in $(seq 1 ${options.lines}); do printf 'bench-%05d abcdefghijklmnopqrstuvwxyz\\n' "$i"; done`; const startedAt = performance.now(); await page.locator(".terminal-screen").click(); - await page.keyboard.type(command); + await page.keyboard.insertText(command); await page.keyboard.press("Enter"); - await waitForBenchLine(page, options.lines, options.timeoutMs); + await waitForBenchLine(page, options.lines, options.timeoutMs, viewport.name); const elapsedMs = round(performance.now() - startedAt); + console.error( + `[terminal-bench] ${viewport.name}: output observed in ${elapsedMs}ms`, + ); const probe = await page.evaluate(() => window.__terminalBench || {}); frameSamples.push( @@ -272,6 +279,16 @@ function browserLaunchOptions(options) { return {}; } +function browserLaunchLabel(options) { + if (options.browserChannel) { + return ` channel=${options.browserChannel}`; + } + if (options.browserExecutable) { + return ` executable=${options.browserExecutable}`; + } + return ""; +} + export function pngSmokeFromBuffer(buffer) { const signature = buffer.subarray(0, 8).toString("hex"); const isPng = signature === "89504e470d0a1a0a"; @@ -287,19 +304,50 @@ export function pngSmokeFromBuffer(buffer) { }; } -async function waitForBenchLine(page, lines, timeoutMs) { +async function waitForBenchLine(page, lines, timeoutMs, viewportName) { const marker = `bench-${String(lines).padStart(5, "0")}`; const minHistoryRows = Math.max(1, lines - 200); - await page.waitForFunction( - ({ text, minHistoryRows }) => { - const probe = window.__terminalBench || {}; - return ( - document.body.innerText.includes(text) || - (probe.historyRows || 0) >= minHistoryRows + const deadline = performance.now() + timeoutMs; + let lastLogAt = 0; + let lastStatus = null; + + while (performance.now() < deadline) { + const status = await page.evaluate( + ({ text, minHistoryRows }) => { + const probe = window.__terminalBench || {}; + const bodyText = document.body?.innerText || ""; + const historyRows = Number(probe.historyRows || 0); + return { + matched: bodyText.includes(text) || historyRows >= minHistoryRows, + renderCount: Number(probe.renderCount || 0), + historyRows, + screenRows: Number(probe.screenRows || 0), + renderer: String(probe.renderer || ""), + mode: String(probe.mode || ""), + }; + }, + { text: marker, minHistoryRows }, + ); + lastStatus = status; + if (status.matched) { + return status; + } + + if (performance.now() - lastLogAt >= 5000) { + console.error( + `[terminal-bench] ${viewportName}: waiting for ${marker}; ` + + `historyRows=${status.historyRows}/${minHistoryRows}, ` + + `screenRows=${status.screenRows}, renderCount=${status.renderCount}`, ); - }, - { text: marker, minHistoryRows }, - { timeout: timeoutMs }, + lastLogAt = performance.now(); + } + await page.waitForTimeout(1000); + } + + throw new Error( + `Timed out waiting for terminal output ${marker}. Last status: ${JSON.stringify( + lastStatus, + )}`, ); }