diff --git a/.project/designs/app/e2e/lab-smoke.spec.ts b/.project/designs/app/e2e/lab-smoke.spec.ts index 35fc6427..06cae619 100644 --- a/.project/designs/app/e2e/lab-smoke.spec.ts +++ b/.project/designs/app/e2e/lab-smoke.spec.ts @@ -30,17 +30,17 @@ test.describe('lab smoke', () => { }) test('Advanced panel exposes the four biome-classifier sliders', async ({ page }) => { - await page.goto(WASM_ROUTE, { waitUntil: 'domcontentloaded', timeout: WASM_TIMEOUT }) - await page.locator('canvas').first().waitFor({ state: 'visible', timeout: WASM_TIMEOUT }) + // advancedOpen defaults to true — sliders are visible without any click. + await page.goto(WASM_ROUTE, { waitUntil: 'networkidle', timeout: WASM_TIMEOUT }) - // Open the advanced panel. - await page.getByRole('button', { name: /advanced/i }).click() - await page.waitForTimeout(400) + // Wait for the Altitude label to confirm the biome-classifier controls rendered. + await page.locator('body').filter({ hasText: 'Altitude' }).waitFor({ timeout: 10_000 }) - // At least 4 range inputs must be visible. + // The 4 biome-classifier sliders render when advancedOpen=true (the default). + // Also the Flora Density slider is visible by default (floraOn=true) = ≥5 total. const sliders = page.locator('input[type="range"]') const sliderCount = await sliders.count() - expect(sliderCount, `slider count after opening Advanced (got ${sliderCount})`).toBeGreaterThanOrEqual(4) + expect(sliderCount, `slider count with advanced panel open (got ${sliderCount})`).toBeGreaterThanOrEqual(4) // The four biome-classifier labels must be present in the page text. const bodyText = await page.locator('body').innerText() @@ -50,13 +50,10 @@ test.describe('lab smoke', () => { }) test('URL updates when Altitude slider moves', async ({ page }) => { - await page.goto(WASM_ROUTE, { waitUntil: 'domcontentloaded', timeout: WASM_TIMEOUT }) - await page.locator('canvas').first().waitFor({ state: 'visible', timeout: WASM_TIMEOUT }) + await page.goto(WASM_ROUTE, { waitUntil: 'networkidle', timeout: WASM_TIMEOUT }) + await page.locator('body').filter({ hasText: 'Altitude' }).waitFor({ timeout: 10_000 }) - await page.getByRole('button', { name: /advanced/i }).click() - await page.waitForTimeout(400) - - // Find the Altitude slider. SliderLabel contains "Altitude", slider follows. + // Altitude slider is the first range input in the Advanced panel. const altitudeSlider = page.locator('input[type="range"]').first() // Move slider to midpoint using keyboard. diff --git a/.project/designs/app/package.json b/.project/designs/app/package.json index 4db73431..6b5a676b 100644 --- a/.project/designs/app/package.json +++ b/.project/designs/app/package.json @@ -32,4 +32,4 @@ "vite-plugin-wasm": "^3.6.0", "vitest": "^4.1.4" } -} +} \ No newline at end of file diff --git a/.project/designs/app/playwright-report/index.html b/.project/designs/app/playwright-report/index.html new file mode 100644 index 00000000..60a5c2cf --- /dev/null +++ b/.project/designs/app/playwright-report/index.html @@ -0,0 +1,90 @@ + + + + + + + + + Playwright Test Report + + + + +
+ + + \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f4676d0d..045547a9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,6 +32,15 @@ importers: specifier: ^6.1.18 version: 6.4.0(css-to-react-native@3.2.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) devDependencies: + '@lilith/playwright-e2e-docker': + specifier: ^2.0.2 + version: 2.0.3(@playwright/test@1.59.1) + '@playwright/test': + specifier: ^1.59.0 + version: 1.59.1 + '@types/node': + specifier: ^22.0.0 + version: 22.19.17 '@types/react': specifier: ^19.1.2 version: 19.2.14 @@ -43,19 +52,19 @@ importers: version: 5.1.36 '@vitejs/plugin-react': specifier: ^4.4.1 - version: 4.7.0(vite@6.4.2(@types/node@25.6.0)(tsx@4.21.0)) + version: 4.7.0(vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0)) typescript: specifier: ^5.8.3 version: 5.9.3 vite: specifier: ^6.3.3 - version: 6.4.2(@types/node@25.6.0)(tsx@4.21.0) + version: 6.4.2(@types/node@22.19.17)(tsx@4.21.0) vite-plugin-wasm: specifier: ^3.6.0 - version: 3.6.0(vite@6.4.2(@types/node@25.6.0)(tsx@4.21.0)) + version: 3.6.0(vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0)) vitest: specifier: ^4.1.4 - version: 4.1.4(@types/node@25.6.0)(vite@6.4.2(@types/node@25.6.0)(tsx@4.21.0)) + version: 4.1.4(@types/node@22.19.17)(vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0)) public/games/age-of-dwarves/guide: dependencies: @@ -1398,6 +1407,9 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + '@types/node@22.19.17': + resolution: {integrity: sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==} + '@types/node@25.6.0': resolution: {integrity: sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==} @@ -3284,6 +3296,9 @@ packages: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici-types@7.19.2: resolution: {integrity: sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==} @@ -4308,6 +4323,10 @@ snapshots: '@types/ms@2.1.0': {} + '@types/node@22.19.17': + dependencies: + undici-types: 6.21.0 + '@types/node@25.6.0': dependencies: undici-types: 7.19.2 @@ -4498,6 +4517,18 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true + '@vitejs/plugin-react@4.7.0(vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0))': + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) + '@rolldown/pluginutils': 1.0.0-beta.27 + '@types/babel__core': 7.20.5 + react-refresh: 0.17.0 + vite: 6.4.2(@types/node@22.19.17)(tsx@4.21.0) + transitivePeerDependencies: + - supports-color + '@vitejs/plugin-react@4.7.0(vite@6.4.2(@types/node@25.6.0)(tsx@4.21.0))': dependencies: '@babel/core': 7.29.0 @@ -4519,6 +4550,14 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 + '@vitest/mocker@4.1.4(vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0))': + dependencies: + '@vitest/spy': 4.1.4 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 6.4.2(@types/node@22.19.17)(tsx@4.21.0) + '@vitest/mocker@4.1.4(vite@6.4.2(@types/node@25.6.0)(tsx@4.21.0))': dependencies: '@vitest/spy': 4.1.4 @@ -6702,6 +6741,8 @@ snapshots: has-symbols: 1.1.0 which-boxed-primitive: 1.1.1 + undici-types@6.21.0: {} + undici-types@7.19.2: {} unified@11.0.5: @@ -6781,10 +6822,27 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 + vite-plugin-wasm@3.6.0(vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0)): + dependencies: + vite: 6.4.2(@types/node@22.19.17)(tsx@4.21.0) + vite-plugin-wasm@3.6.0(vite@6.4.2(@types/node@25.6.0)(tsx@4.21.0)): dependencies: vite: 6.4.2(@types/node@25.6.0)(tsx@4.21.0) + vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0): + dependencies: + esbuild: 0.25.12 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + postcss: 8.5.9 + rollup: 4.60.1 + tinyglobby: 0.2.16 + optionalDependencies: + '@types/node': 22.19.17 + fsevents: 2.3.3 + tsx: 4.21.0 + vite@6.4.2(@types/node@25.6.0)(tsx@4.21.0): dependencies: esbuild: 0.25.12 @@ -6798,6 +6856,33 @@ snapshots: fsevents: 2.3.3 tsx: 4.21.0 + vitest@4.1.4(@types/node@22.19.17)(vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0)): + dependencies: + '@vitest/expect': 4.1.4 + '@vitest/mocker': 4.1.4(vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0)) + '@vitest/pretty-format': 4.1.4 + '@vitest/runner': 4.1.4 + '@vitest/snapshot': 4.1.4 + '@vitest/spy': 4.1.4 + '@vitest/utils': 4.1.4 + es-module-lexer: 2.0.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 4.0.0 + tinybench: 2.9.0 + tinyexec: 1.1.1 + tinyglobby: 0.2.16 + tinyrainbow: 3.1.0 + vite: 6.4.2(@types/node@22.19.17)(tsx@4.21.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.19.17 + transitivePeerDependencies: + - msw + vitest@4.1.4(@types/node@25.6.0)(vite@6.4.2(@types/node@25.6.0)(tsx@4.21.0)): dependencies: '@vitest/expect': 4.1.4