fix(e2e): pass STARTER into evaluate; verify self-heal end state on fresh snapshots
CI / build + unit + e2e (pull_request) Failing after 10m42s
CI / build + unit + e2e (pull_request) Failing after 10m42s
This commit is contained in:
+3
-3
@@ -105,7 +105,7 @@ async function fitToAirports(page: Page, icaos: string[]): Promise<void> {
|
||||
// fetch can be stale by tens of px) and wait for the popup. `flyingOnly` skips grounded frames —
|
||||
// used right after dispatch, when the last rendered frame may predate it.
|
||||
async function clickPlane(page: Page, flyingOnly: boolean): Promise<void> {
|
||||
const pt = await page.evaluate(async (onlyFlying: boolean) => {
|
||||
const pt = await page.evaluate(async ({ onlyFlying, starterId }: { onlyFlying: boolean; starterId: string }) => {
|
||||
const m = (window as any).__flightMap;
|
||||
if (!m) return null;
|
||||
const deadline = Date.now() + 10_000;
|
||||
@@ -116,7 +116,7 @@ async function clickPlane(page: Page, flyingOnly: boolean): Promise<void> {
|
||||
} catch {
|
||||
// map not ready yet — keep polling
|
||||
}
|
||||
const f = feats.find((x) => x.properties?.id === STARTER && (!onlyFlying || x.properties?.flying === true));
|
||||
const f = feats.find((x) => x.properties?.id === starterId && (!onlyFlying || x.properties?.flying === true));
|
||||
if (f && f.geometry) {
|
||||
const projected = m.project(f.geometry.coordinates);
|
||||
const rect = m.getContainer().getBoundingClientRect();
|
||||
@@ -125,7 +125,7 @@ async function clickPlane(page: Page, flyingOnly: boolean): Promise<void> {
|
||||
if (Date.now() >= deadline) return null;
|
||||
await new Promise((r) => setTimeout(r, 100));
|
||||
}
|
||||
}, flyingOnly);
|
||||
}, { onlyFlying: flyingOnly, starterId: STARTER });
|
||||
expect(pt, 'plane marker not rendered').not.toBeNull();
|
||||
|
||||
// Popups are created per click and never auto-close — remove any stale ones so the testids below
|
||||
|
||||
+18
-28
@@ -154,39 +154,29 @@ async function createPackage(page: Page, fromIcao: string, toIcao: string, deadl
|
||||
return (await created.json()) as PackageState;
|
||||
}
|
||||
|
||||
// Self-heal: let any in-flight leg finish, then reposition plane-starter home via the API.
|
||||
// Self-heal: let any in-flight leg finish, then reposition plane-starter home via the API. The end
|
||||
// state is verified by ONE poll on FRESH snapshots (v1.12.0): legs now include takeoff/landing holds,
|
||||
// so a leftover leg can land at its destination after an earlier snapshot was taken — deciding from a
|
||||
// stale pre-flight snapshot let tests load cargo onto a plane that wasn't actually at the hub (409).
|
||||
async function flyHomeViaApi(page: Page): Promise<void> {
|
||||
// v0.39.0 (ISS-069): wear accumulates across the shared CI DB — restore full health and clear any
|
||||
// active repair gate from an interrupted run before the steps below act on the starter, so the
|
||||
// farthest-flyable picker and fuel pins never see a worn or broken plane.
|
||||
expect((await page.request.post('/api/test/set-health', { data: { planeId: 'plane-starter', health: 100, repairUntilMs: 0 } })).status()).toBe(200);
|
||||
const s0 = await getState(page); // ticks — a shortened gate flips the plane back to available here
|
||||
const starter = s0.planes.find((p) => p.id === 'plane-starter')!;
|
||||
if (starter.status === 'flying' || starter.locationIcao !== HUB) {
|
||||
// Fast-forward any leftover leg / repositioning flight (~20 s real time worst case at 1000×).
|
||||
await setScale(page, SCALE);
|
||||
}
|
||||
if (starter.status === 'flying') {
|
||||
await expect
|
||||
.poll(async () => (await getState(page)).planes.find((p) => p.id === 'plane-starter')?.status === 'available', {
|
||||
timeout: 240_000,
|
||||
message: 'waiting for an in-flight plane-starter to land',
|
||||
})
|
||||
.toBe(true);
|
||||
}
|
||||
if (starter.locationIcao !== HUB) {
|
||||
// Make sure the world rate is back at SCALE so the return leg fast-forwards. ISS-082: dispatch
|
||||
// auto-refuels, so a grounded plane can always start any full-tank-flyable leg when cash allows — no top-up retry needed.
|
||||
await setScale(page, SCALE);
|
||||
const flyHome = await page.request.post('/api/planes/plane-starter/fly', { data: { destIcao: HUB } });
|
||||
expect(flyHome.status()).toBe(200); // repositioning needs no package (v0.12.0 manual flight)
|
||||
await expect
|
||||
.poll(async () => (await getState(page)).planes.find((p) => p.id === 'plane-starter')?.locationIcao === HUB, {
|
||||
timeout: 240_000,
|
||||
message: 'waiting for plane-starter to land back at the hub',
|
||||
})
|
||||
.toBe(true);
|
||||
}
|
||||
// Fast-forward any leftover leg / repositioning flight (a few seconds real time worst case at 1000×).
|
||||
await setScale(page, SCALE);
|
||||
await expect.poll(async () => {
|
||||
const p = (await getState(page)).planes.find((x) => x.id === 'plane-starter')!;
|
||||
if (p.status === 'available' && p.locationIcao === HUB) return 'ok';
|
||||
if (p.status === 'available') {
|
||||
// ISS-082: dispatch auto-refuels, so a grounded plane can always start any full-tank-flyable leg
|
||||
// when cash allows — no top-up retry needed. Fail loud with the server's reason otherwise.
|
||||
const flyHome = await page.request.post('/api/planes/plane-starter/fly', { data: { destIcao: HUB } });
|
||||
if (flyHome.status() !== 200) throw new Error(`reposition home failed (${flyHome.status()}): ${await flyHome.text()}`);
|
||||
return `flying home from ${p.locationIcao}`;
|
||||
}
|
||||
return p.status; // flying or repairing — keep waiting (SCALE makes both finish quickly)
|
||||
}, { timeout: 240_000, message: 'waiting for plane-starter to be grounded at the hub' }).toBe('ok');
|
||||
// Abandon leftover loaded/expired packages (the baseline is captured AFTER this cleanup).
|
||||
const s1 = await getState(page);
|
||||
for (const pkg of s1.packages) {
|
||||
|
||||
Reference in New Issue
Block a user