diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d6e2f9..814a57e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - **E2e hover spec mechanics fixed after CI run #32** (`e2e/hover.spec.ts`, no app changes): the fleet-row wait now polls up to 30 s with a diagnostic that distinguishes "server has no plane-starter" from "DOM didn't render" (the browser's /api/state poll can lag node-side requests right after page load, leaving the pane in its loading state); the open-package test fits the map to both endpoint airports before asserting — `queryRenderedFeatures` only returns features inside the current viewport and the default Frankfurt-centered view leaves LEMD off-screen - **Decisive hover test-1 diagnostics (run #33 transient)**: the fleet-row poll now reports on every failed attempt what the NODE side sees (`/api/state` plane ids + cash via `page.request`) vs what the BROWSER last polled — new dev hook `window.__flightLastSnapshot` set in `lib/useGameState.ts` after each successful fetch (planeIds/cash/timeScale/timestamp, client-only) — plus the fleet section's HTML (`fleet-list` outerHTML or left-pane text), so a future failure can distinguish server divergence from a render bug - **CI removes the stale e2e DB volume at run start** (`.gitea/workflows/ci.yml`, "Prepare e2e network"): `docker volume rm flight-ci_flight-db 2>/dev/null || true` — an interrupted run skips the end-of-run cleanup and leaks its used game state into later runs (run #33's instance showed spent cash from a pre-#26 seed), while tests assume seeded state +- **Hover e2e test 1 used the wrong fleet-row testid** (`e2e/hover.spec.ts`): it waited for `data-testid="plane-starter"`, but rows are rendered as `plane-${p.id}` and the server id already carries the `plane-` prefix — so the real testid is **`plane-plane-starter`** and the "missing row" failures in runs #32–#34 were deterministic selector misses, not transient state (run #34's diagnostics proved it: the fleet-list HTML contained `
  • `). The selector is now derived from `/api/state` (starter plane id, or the single plane) and used for both the visibility poll and the hover ## v0.14.0 — 2026-09-19 08:45 - **Time-scale slider reworked to a 10-step ladder up to 1000× (ISS-006).** The old power-of-two ladder `1/2/4/8/16/32/64` is replaced by the discrete values `1, 2, 5, 10, 25, 50, 100, 250, 500, 1000` (each step roughly doubles the speed). The server clamp range widens from `[1, 64]` to `[1, 1000]` (`MAX_TIME_SCALE` in `lib/sim/engine.ts`, enforced by `clampTimeScale`; out-of-range values are still clamped, never rejected), and the OpenAPI spec's `timeScale` bounds + description follow. The slider mapping helpers in `lib/timeScale.ts` now place off-ladder scales at the nearest ladder step **by log distance** (the old `log2` formula assumed a pure power-of-two ladder); round-trip, monotonicity and endpoint-exactness are preserved diff --git a/e2e/hover.spec.ts b/e2e/hover.spec.ts index aa939b1..11341ee 100644 --- a/e2e/hover.spec.ts +++ b/e2e/hover.spec.ts @@ -164,7 +164,12 @@ test('hovering a fleet row highlights the plane on the map', async ({ page }) => await page.goto('/'); await waitForAirportCount(page); - const row = page.locator('li[data-testid="plane-starter"]'); + // Fleet rows are
  • and the server id already carries the "plane-" + // prefix (run #34: the real testid is plane-plane-starter) — derive it from /api/state, never hardcode. + const planes = (await getState(page)).planes; + const starterId = planes.find((p) => p.id.endsWith('starter'))?.id ?? (planes.length === 1 ? planes[0].id : undefined); + expect(starterId).toBeDefined(); + const row = page.locator(`li[data-testid="plane-${starterId}"]`); // The browser's /api/state polls can lag node-side requests right after a fresh page load // (useGameState keeps loading=true until the first success → no fleet rows yet), so poll with // diagnostics: on timeout the message compares what the NODE side sees vs what the BROWSER @@ -195,8 +200,8 @@ test('hovering a fleet row highlights the plane on the map', async ({ page }) => await row.hover(); await expect.poll(async () => { const feats = (await renderedFeatures(page, ['planes-highlight'])) as Array<{ properties: Record }>; - return feats.length > 0 && feats[0].properties.id === 'plane-starter'; - }, { timeout: 15_000, message: 'waiting for the planes-highlight layer to show plane-starter' }).toBe(true); + return feats.length > 0 && feats[0].properties.id === starterId; + }, { timeout: 15_000, message: `waiting for the planes-highlight layer to show ${starterId}` }).toBe(true); await unhover(page); await expect.poll(async () => (await renderedFeatures(page, ['planes-highlight'])).length, {