diff --git a/games/age-of-dwarves/guide/e2e/diag.spec.ts b/games/age-of-dwarves/guide/e2e/diag.spec.ts index e322fed8..5d56ac84 100644 --- a/games/age-of-dwarves/guide/e2e/diag.spec.ts +++ b/games/age-of-dwarves/guide/e2e/diag.spec.ts @@ -1,48 +1,39 @@ import { test } from '@playwright/test' -test('check if worker sends ready within 30s', async ({ page }) => { - const msgs: string[] = [] - const errors: string[] = [] +test('network: watch WASM + worker requests', async ({ page }) => { + const requests: string[] = [] + const failures: string[] = [] - page.on('console', msg => { - const text = msg.text() - msgs.push(`[${msg.type()}] ${text}`) - if (msg.type() === 'error') errors.push(text) - }) - page.on('pageerror', e => errors.push(e.message)) - - // Add debug tracing via page.addInitScript - await page.addInitScript(() => { - const origWorker = window.Worker - // @ts-ignore - window.Worker = function(url: string, opts: WorkerOptions) { - console.log('[TRACE] Worker created:', url) - const w = new origWorker(url, opts) - const origPost = w.postMessage.bind(w) - w.postMessage = (msg: unknown, ...args: unknown[]) => { - console.log('[TRACE] worker.postMessage:', JSON.stringify(msg).slice(0, 200)) - return (origPost as Function)(msg, ...args) - } - const origOnmsg = Object.getOwnPropertyDescriptor(w, 'onmessage') - w.addEventListener('message', (e: MessageEvent) => { - const data = e.data as { type: string } - console.log('[TRACE] worker.onmessage:', data?.type) - }) - return w + page.on('request', req => { + const url = req.url() + if (url.includes('wasm') || url.includes('worker') || url.includes('physics')) { + requests.push(`[req] ${req.method()} ${url}`) } - // @ts-ignore - window.Worker.prototype = origWorker.prototype }) + page.on('response', res => { + const url = res.url() + if ((url.includes('wasm') || url.includes('worker') || url.includes('physics')) && !res.ok()) { + failures.push(`[fail:${res.status()}] ${url}`) + } + }) + page.on('requestfailed', req => { + const url = req.url() + if (url.includes('wasm') || url.includes('worker') || url.includes('physics')) { + failures.push(`[reqfail] ${url}: ${req.failure()?.errorText}`) + } + }) + page.on('console', msg => { + if (msg.type() === 'error' || msg.text().includes('[SimWorker]') || msg.text().includes('[TRACE]')) { + console.log(`[${msg.type()}] ${msg.text()}`) + } + }) + page.on('pageerror', e => console.log('[pageerror]', e.message)) await page.goto('/climate/simulation?noGui=true&skip=welcome') - await page.waitForTimeout(20000) + await page.waitForTimeout(10000) - console.log('=== MESSAGES ===') - msgs.forEach(m => console.log(m)) - - const spans = await page.evaluate(() => - Array.from(document.querySelectorAll('span')) - .map(s => s.textContent?.trim()).filter(Boolean) - ) - console.log('Spans:', spans.join('|')) + console.log('=== REQUESTS ===') + requests.forEach(r => console.log(r)) + console.log('=== FAILURES ===') + failures.forEach(f => console.log(f)) }) diff --git a/src/packages/guide/src/components/climate-sim/ClimateSimDisplay.tsx b/src/packages/guide/src/components/climate-sim/ClimateSimDisplay.tsx index 00c15d99..c390767b 100644 --- a/src/packages/guide/src/components/climate-sim/ClimateSimDisplay.tsx +++ b/src/packages/guide/src/components/climate-sim/ClimateSimDisplay.tsx @@ -198,7 +198,7 @@ export function ClimateSimDisplay({ easterEggs }: ClimateSimDisplayProps): React // ── kick off simulation when worker is ready or scenario changes ────── useEffect(() => { if (!isReady) return - if (workerScenarios.has(activeScenarioId)) return + if (workerScenarios.get(activeScenarioId)?.bufferReady) return workerRun(activeScenarioId, initialTurns, bufferFrames, worldSeed) }, [isReady, activeScenarioId, workerScenarios, workerRun, initialTurns, bufferFrames, worldSeed])