diff --git a/games/age-of-dwarves/guide/test-results/simulator-Climate-simulator-world-generation-completes-chromium/error-context.md b/games/age-of-dwarves/guide/test-results/simulator-Climate-simulator-world-generation-completes-chromium/error-context.md deleted file mode 100644 index ac213d9e..00000000 --- a/games/age-of-dwarves/guide/test-results/simulator-Climate-simulator-world-generation-completes-chromium/error-context.md +++ /dev/null @@ -1,189 +0,0 @@ -# Instructions - -- Following Playwright test failed. -- Explain why, be concise, respect Playwright best practices. -- Provide a snippet of code with the fix, if possible. - -# Test info - -- Name: simulator.spec.ts >> Climate simulator >> world generation completes -- Location: e2e/simulator.spec.ts:50:3 - -# Error details - -``` -Error: expect(locator).toBeVisible() failed - -Locator: locator(':text-is("✓")').locator('..').filter({ hasText: 'World generation' }).or(locator('canvas').first()) -Expected: visible -Timeout: 30000ms -Error: element(s) not found - -Call log: - - Expect "toBeVisible" with timeout 30000ms - - waiting for locator(':text-is("✓")').locator('..').filter({ hasText: 'World generation' }).or(locator('canvas').first()) - -``` - -# Page snapshot - -```yaml -- generic [ref=e5]: - - generic [ref=e6]: - - button "◉ Earth ▾" [ref=e8] [cursor=pointer]: - - generic [ref=e9]: ◉ - - generic [ref=e10]: Earth - - generic [ref=e11]: ▾ - - tablist "Simulation category" [ref=e13]: - - tab "Environment" [selected] [ref=e14] [cursor=pointer] - - tab "Life" [ref=e15] [cursor=pointer] - - navigation "Climate scenario groups" [ref=e16]: - - button "Lifeless Worlds Hadean Earth" [ref=e18] [cursor=pointer]: - - generic [ref=e20]: - - generic [ref=e21]: Lifeless Worlds - - generic [ref=e22]: Hadean Earth - - generic [ref=e23]: ▾ - - button "Eco Disaster" [ref=e25] [cursor=pointer]: - - generic [ref=e28]: Eco Disaster - - generic [ref=e29]: ▾ - - button "ET Disaster" [ref=e31] [cursor=pointer]: - - generic [ref=e34]: ET Disaster - - generic [ref=e35]: ▾ - - paragraph [ref=e37]: "Planet at formation: extreme heat, no liquid water, no biology. Deep Earth injection and radiative cooling slowly build the first ocean." - - generic [ref=e38]: - - generic [ref=e39]: - - heading "Hadean Earth" [level=3] [ref=e40] - - generic [ref=e41]: - - generic [ref=e42]: Primordial atmosphere - - generic [ref=e43]: No biology - - generic [ref=e44]: - - generic [ref=e45]: - - generic [ref=e46]: ○ - - generic [ref=e47]: - - generic [ref=e48]: World generation - - generic [ref=e49]: Continents, oceans, rivers, wind patterns - - generic [ref=e50]: - - generic [ref=e51]: ○ - - generic [ref=e52]: - - generic [ref=e53]: Scenario simulation - - generic [ref=e54]: 50 turns - - generic [ref=e55]: - - generic [ref=e56]: ○ - - generic [ref=e57]: - - generic [ref=e58]: Playback buffer - - generic [ref=e59]: Encoding frames for smooth playback - - generic [ref=e60]: 28.9s -``` - -# Test source - -```ts - 1 | import { test, expect } from '@playwright/test' - 2 | - 3 | /** - 4 | * Climate simulator E2E tests. - 5 | * - 6 | * These tests require the dev server running on port 5800: - 7 | * pnpm dev - 8 | * - 9 | * Run with: - 10 | * npx playwright test - 11 | * - 12 | * All tests use ?totalTurns=50&buffer=0 so the simulation completes in seconds - 13 | * rather than waiting for the default 2000 turns + 10s prebuffer. - 14 | * - 15 | * DOM structure of the loading overlay (from live snapshot): - 16 | * step-row - 17 | * icon-div ("✓" | "◉" | "○") - 18 | * text-div - 19 | * name-div ("World generation" | "Scenario simulation" | "Playback buffer") - 20 | * desc-div (description or turn progress) - 21 | * [pct-div] ("4%" — only when simulation is active) - 22 | * - 23 | * Note: "Playback buffer" never shows ✓ — it's either active (◉) or pending (○). - 24 | * When bufferReady becomes true the entire loading overlay is replaced by the canvas. - 25 | * - 26 | * Selectors use :text-is("✓") to precisely match the icon element (exact text), - 27 | * then navigate to its parent (the step row) and filter by step name. - 28 | * - 29 | * Tests 2 and 3 use .or(canvas) because with a warm dev-server cache and only - 30 | * 50 turns, the simulation may complete before the loading overlay is ever observed. - 31 | * Both the transient loading state AND the final canvas prove the phase succeeded. - 32 | */ - 33 | - 34 | const BASE_URL = '/climate/simulation?noGui=true&skip=welcome&totalTurns=50&buffer=0' - 35 | - 36 | test.describe('Climate simulator', () => { - 37 | test('starts without console errors', async ({ page }) => { - 38 | const errors: string[] = [] - 39 | page.on('console', msg => { - 40 | if (msg.type() === 'error') errors.push(msg.text()) - 41 | }) - 42 | page.on('pageerror', err => errors.push(err.message)) - 43 | - 44 | await page.goto(BASE_URL) - 45 | await page.waitForTimeout(3000) - 46 | - 47 | expect(errors, `Console errors:\n${errors.join('\n')}`).toHaveLength(0) - 48 | }) - 49 | - 50 | test('world generation completes', async ({ page }) => { - 51 | const errors: string[] = [] - 52 | page.on('console', msg => { - 53 | if (msg.type() === 'error') errors.push(msg.text()) - 54 | }) - 55 | page.on('pageerror', err => errors.push(err.message)) - 56 | - 57 | await page.goto(BASE_URL) - 58 | - 59 | // Accept either the transient ✓ on "World generation" (visible during loading) - 60 | // OR the canvas (visible once simulation finishes) — both prove world gen ran. - 61 | const worldGenCheckmark = page.locator(':text-is("✓")').locator('..').filter({ hasText: 'World generation' }) - 62 | const canvas = page.locator('canvas').first() -> 63 | await expect(worldGenCheckmark.or(canvas)).toBeVisible({ timeout: 30_000 }) - | ^ Error: expect(locator).toBeVisible() failed - 64 | - 65 | expect(errors, `Console errors:\n${errors.join('\n')}`).toHaveLength(0) - 66 | }) - 67 | - 68 | test('scenario simulation reaches > 0% progress', async ({ page }) => { - 69 | const errors: string[] = [] - 70 | page.on('console', msg => { - 71 | if (msg.type() === 'error') errors.push(msg.text()) - 72 | }) - 73 | page.on('pageerror', err => errors.push(err.message)) - 74 | - 75 | await page.goto(BASE_URL) - 76 | - 77 | // Accept either the transient "Turn N / M" counter in the loading overlay - 78 | // OR the completed canvas — both prove the scenario simulation ran. - 79 | const turnCounter = page.locator('text=/Turn \\d+/') - 80 | const canvas = page.locator('canvas').first() - 81 | await expect(turnCounter.or(canvas)).toBeVisible({ timeout: 60_000 }) - 82 | - 83 | expect(errors, `Console errors:\n${errors.join('\n')}`).toHaveLength(0) - 84 | }) - 85 | - 86 | test('simulation completes and canvas renders', async ({ page }) => { - 87 | const errors: string[] = [] - 88 | page.on('console', msg => { - 89 | if (msg.type() === 'error') errors.push(msg.text()) - 90 | }) - 91 | page.on('pageerror', err => errors.push(err.message)) - 92 | - 93 | await page.goto(BASE_URL) - 94 | - 95 | // When bufferReady becomes true the loading overlay is replaced by the WebGL canvas. - 96 | // canvas is only rendered once a frame is delivered — wait for it to be visible. - 97 | const canvas = page.locator('canvas').first() - 98 | await expect(canvas).toBeVisible({ timeout: 60_000 }) - 99 | const box = await canvas.boundingBox() - 100 | expect(box, 'canvas has no bounding box').not.toBeNull() - 101 | expect(box!.width, 'canvas width').toBeGreaterThan(0) - 102 | expect(box!.height, 'canvas height').toBeGreaterThan(0) - 103 | - 104 | expect(errors, `Console errors:\n${errors.join('\n')}`).toHaveLength(0) - 105 | }) - 106 | }) - 107 | -``` \ No newline at end of file