Queue UI fixes: disable would-409 controls, hover trace from landing airport, grounded queues draw dotted lines (ISS-077, v0.41.0)
CI / build + unit + e2e (pull_request) Successful in 9m11s
CI / build + unit + e2e (pull_request) Successful in 9m11s
This commit is contained in:
@@ -350,6 +350,64 @@ test('dotted queue line renders the queued path on the map (ISS-043 part 2)', as
|
||||
}).toBe(HUB);
|
||||
});
|
||||
|
||||
test('grounded plane with a pre-built queue draws its dotted route from its airport (ISS-077)', async ({ page }) => {
|
||||
test.setTimeout(300_000); // self-heal + map assertions only — no flight in this test
|
||||
await flyHomeViaApi(page); // deterministic: the starter sits grounded at EDDF
|
||||
|
||||
await page.goto('/');
|
||||
await waitForAirportCount(page);
|
||||
|
||||
// Pre-build a two-leg route while GROUNDED via the raw API (queuing is allowed from any state,
|
||||
// ISS-043 part 1) — no package or flight needed. The dotted line must chain HUB → DEST → QUEUE.
|
||||
const q1 = await page.request.post('/api/planes/plane-starter/queue', { data: { destIcao: DEST } });
|
||||
expect(q1.status()).toBe(200);
|
||||
const q2 = await page.request.post('/api/planes/plane-starter/queue', { data: { destIcao: QUEUE } });
|
||||
expect(q2.status()).toBe(200);
|
||||
|
||||
// All chain endpoints must be in-viewport for queryRenderedFeatures to see them.
|
||||
await fitToAirports(page, [HUB, DEST, QUEUE]);
|
||||
|
||||
const hubLL = await airportLonLat(page, HUB);
|
||||
const destLL = await airportLonLat(page, DEST);
|
||||
const queueLL = await airportLonLat(page, QUEUE);
|
||||
const near = (a: [number, number], b: [number, number]) =>
|
||||
Math.abs(a[0] - b[0]) <= QUEUE_ROUTE_EPS_DEG && Math.abs(a[1] - b[1]) <= QUEUE_ROUTE_EPS_DEG;
|
||||
|
||||
await expect.poll(async () => {
|
||||
const feats = (await renderedFeatures(page, ['queue-routes'])) as Array<{
|
||||
properties?: Record<string, unknown>;
|
||||
geometry?: { type: string; coordinates: [number, number][] };
|
||||
}>;
|
||||
// Filter to real LineString segments — keeps this poll callback total. "None yet" → keep polling.
|
||||
const segs = feats.filter(
|
||||
(f): f is { properties?: Record<string, unknown>; geometry: { type: 'LineString'; coordinates: [number, number][] } } =>
|
||||
!!f.geometry && f.geometry.type === 'LineString' && Array.isArray(f.geometry.coordinates) && f.geometry.coordinates.length >= 2,
|
||||
);
|
||||
if (!segs.length) return false;
|
||||
// The chain HUB → DEST → QUEUE may be clipped into per-tile segments — check across all of them:
|
||||
// some segment STARTS within EPS of the hub (the plane's airport, NOT a flight destination)…
|
||||
const startsAtHub = segs.some((f) => near(f.geometry.coordinates[0], hubLL));
|
||||
// …some ENDS within EPS of the last queued airport…
|
||||
const endsAtQueue = segs.some((f) => {
|
||||
const c = f.geometry.coordinates;
|
||||
return near(c[c.length - 1], queueLL);
|
||||
});
|
||||
// …and the chain passes THROUGH the first queued airport — an interior joint point survives in
|
||||
// whichever tile contains it (not guaranteed to be a segment endpoint after clipping).
|
||||
const passesThroughDest = segs.some((f) => f.geometry.coordinates.some((c) => near(c, destLL)));
|
||||
// Every rendered feature belongs to plane-starter.
|
||||
const ownedByStarter = feats.every((f) => f.properties?.planeId === 'plane-starter');
|
||||
return startsAtHub && endsAtQueue && passesThroughDest && ownedByStarter;
|
||||
}, { timeout: 15_000, message: `waiting for the dotted queue line ${HUB} → ${DEST} → ${QUEUE}` }).toBe(true);
|
||||
|
||||
// Cleanup: cancel both queued legs (index 0 twice — each cancel shifts the rest down) so the
|
||||
// starter stays grounded at HUB with an empty queue. No flight happened, nothing else to reset.
|
||||
const c1 = await page.request.post('/api/planes/plane-starter/queue/cancel', { data: { index: 0 } });
|
||||
expect(c1.status()).toBe(200);
|
||||
const c2 = await page.request.post('/api/planes/plane-starter/queue/cancel', { data: { index: 0 } });
|
||||
expect(c2.status()).toBe(200);
|
||||
});
|
||||
|
||||
test('landing auto-starts the next queued leg (ISS-043 chain end-to-end)', async ({ page }) => {
|
||||
test.setTimeout(300_000); // self-heal + two chained legs at scale 1000
|
||||
await flyHomeViaApi(page);
|
||||
|
||||
Reference in New Issue
Block a user