test: click the rendered marker position while paused — closes render-lag race (CI run #37)
CI / build + unit + e2e (pull_request) Successful in 5m0s

This commit is contained in:
2026-09-19 11:32:19 +00:00
parent 4c99dbe550
commit b6bfcedaf6
2 changed files with 26 additions and 10 deletions
+25 -10
View File
@@ -266,20 +266,35 @@ test('plane markers move while flying and the plane popup shows status + route',
}, { timeout: 15_000, message: 'waiting for the paused clock to freeze the plane position' })
.toBe(true);
// Fetch + project in one evaluate — with the sim paused above, the server's analytic
// position is static, so the projected point matches what the map renders.
// Click the RENDERED marker position, not a fresh /api/state fetch. With the sim paused
// above the server's analytic position is static — but the map renders from its own ~1 s
// poll, so right after the freeze confirmation the last rendered frame can still be up to
// one poll interval stale (tens of px at scale 1000 on this leg) and a click projected
// from a fresh fetch misses the small circle layer (CI run #37). Poll for the plane's
// rendered feature instead and project ITS coordinates — exactly what the map draws.
// Find + project in one evaluate so nothing can change between the two steps.
const pt = await page.evaluate(async () => {
const m = (window as any).__flightMap;
if (!m) return null;
const res = await fetch('/api/state', { cache: 'no-store' });
const body = (await res.json()) as StateBody;
const p = body.planes.find((x) => x.id === 'plane-starter');
if (!p || p.status !== 'flying') return null;
const projected = m.project([p.lon, p.lat]);
const rect = m.getContainer().getBoundingClientRect();
return { x: rect.left + projected.x, y: rect.top + projected.y };
const deadline = Date.now() + 5_000;
for (;;) {
let feats: Array<{ properties?: Record<string, unknown>; geometry?: { coordinates: number[] } }> = [];
try {
feats = m.queryRenderedFeatures(undefined, { layers: ['planes-flying', 'planes-grounded'] });
} catch {
// map not ready yet — keep polling
}
const f = feats.find((x) => x.properties?.id === 'plane-starter');
if (f && f.geometry) {
const projected = m.project(f.geometry.coordinates);
const rect = m.getContainer().getBoundingClientRect();
return { x: rect.left + projected.x, y: rect.top + projected.y };
}
if (Date.now() >= deadline) return null;
await new Promise((r) => setTimeout(r, 100));
}
});
expect(pt).not.toBeNull(); // the ~10 s window at scale 1000 is still open this early after departure
expect(pt, 'plane marker not rendered after pause').not.toBeNull();
await page.mouse.click(pt!.x, pt!.y);
const popup = page.getByTestId('plane-popup');