e2e: relocation self-heal legs at FAST rate — pure arrival waits (v1.9.0)
CI / build + unit + e2e (pull_request) Successful in 5m31s
CI / build + unit + e2e (pull_request) Successful in 5m31s
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v1.9.0 — 2026-09-27 20:57
|
||||||
|
- **E2E speedup follow-up (test-only, no game code changed).** `e2e/relocation.spec.ts`'s self-heal helper `flyHomeViaApi` now fast-forwards its cleanup legs at the v1.8.0 `FAST = 10_000` rate instead of a blanket `SCALE = 1000` — every scale-dependent wait in that file is a pure arrival wait (status `'available'` / `locationIcao === HUB`) with no mid-leg observation, so the higher rate is safe and the now-unused `SCALE` constant was dropped. Expected CI wall time for the file drops from ~40 s to ~25 s (~2–3 s off test 1, ~10–11 s each off tests 2 and 3). Test 3's deliberate `setScale(page, 1)` guard is untouched; `map.spec.ts` wheel-zoom (real-time-bound) and `multiplayer.spec.ts`'s N-player clock (measures sim-vs-real elapsed time) stay as-is.
|
||||||
|
|
||||||
## v1.8.0 — 2026-09-27 20:13
|
## v1.8.0 — 2026-09-27 20:13
|
||||||
- **E2E speedup (test-only, no game code changed).** Every Playwright spec that fast-forwards legs now uses the fastest rate its assertions allow instead of a blanket `SCALE = 1000`: pure arrival waits (no mid-leg observation) run at `FAST` — a lagged tick can only land a plane sooner, never skip an observed state. Expected CI wall time for the affected tests drops ~5–6× overall (e.g. the antimeridian test's relocation chains go from ~3 min to ~15 s per direction; two-planes' parallel-flight test loses its ~24 s afterEach heal leg).
|
- **E2E speedup (test-only, no game code changed).** Every Playwright spec that fast-forwards legs now uses the fastest rate its assertions allow instead of a blanket `SCALE = 1000`: pure arrival waits (no mid-leg observation) run at `FAST` — a lagged tick can only land a plane sooner, never skip an observed state. Expected CI wall time for the affected tests drops ~5–6× overall (e.g. the antimeridian test's relocation chains go from ~3 min to ~15 s per direction; two-planes' parallel-flight test loses its ~24 s afterEach heal leg).
|
||||||
- **Per-test rates.** `actions.spec.ts` + `hover.spec.ts` + `two-planes.spec.ts`: new local `FAST = 10_000` for expiry fast-forwards, landing waits and fly-home cleanups. `queue.spec.ts`: same `FAST`, plus `CHAIN = 4_000` for the auto-chain observation (max per-tick advance 2 s × S stays below the LEMD-length leg's ~1e7 sim-ms duration so one lagged tick can't complete it before a poll sees the chained state); its refuel-before-chained-leg test moves to an explicit `2_000` with the fuel lower bound relaxed from `> 1.3×required` to `> required` (at 2_000× the snapshot can land ~0.4×required into leg 2's burn under dind load; a wrong top-up level still lands far below the bound, and the exact level stays pinned by the unchanged cash assertion). `map-interactions.spec.ts`: `FAST = 50_000` for chain hops (≤3400 km each) and arrival waits.
|
- **Per-test rates.** `actions.spec.ts` + `hover.spec.ts` + `two-planes.spec.ts`: new local `FAST = 10_000` for expiry fast-forwards, landing waits and fly-home cleanups. `queue.spec.ts`: same `FAST`, plus `CHAIN = 4_000` for the auto-chain observation (max per-tick advance 2 s × S stays below the LEMD-length leg's ~1e7 sim-ms duration so one lagged tick can't complete it before a poll sees the chained state); its refuel-before-chained-leg test moves to an explicit `2_000` with the fuel lower bound relaxed from `> 1.3×required` to `> required` (at 2_000× the snapshot can land ~0.4×required into leg 2's burn under dind load; a wrong top-up level still lands far below the bound, and the exact level stays pinned by the unchanged cash assertion). `map-interactions.spec.ts`: `FAST = 50_000` for chain hops (≤3400 km each) and arrival waits.
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ test.beforeEach(async ({ page }) => { await authenticate(page); });
|
|||||||
// works for FLYING planes — it then appends to POST /api/planes/{id}/queue instead of flying now.
|
// works for FLYING planes — it then appends to POST /api/planes/{id}/queue instead of flying now.
|
||||||
// Marker-size regression is covered by the existing e2e/map.spec.ts click tests, not here.
|
// Marker-size regression is covered by the existing e2e/map.spec.ts click tests, not here.
|
||||||
|
|
||||||
const SCALE = 1000; // test rate for fast-forwarding legs — keeps cleanup flights to seconds of real time
|
const FAST = 10_000; // pure arrival waits (no mid-leg observation) — cleanup legs land in ~1 s
|
||||||
const WORLD = 24; // the fixed world rate (ISS-117) — must match lib/worldClock.ts
|
const WORLD = 24; // the fixed world rate (ISS-117) — must match lib/worldClock.ts
|
||||||
const HUB = 'EDDF'; // Frankfurt Main — the seeded starter plane's home base (lib/game/seed.ts)
|
const HUB = 'EDDF'; // Frankfurt Main — the seeded starter plane's home base (lib/game/seed.ts)
|
||||||
// LFRS Nantes Atlantique — same isolated marker as e2e/map.spec.ts. The v0.70.0 default view ([0,0] z2)
|
// LFRS Nantes Atlantique — same isolated marker as e2e/map.spec.ts. The v0.70.0 default view ([0,0] z2)
|
||||||
@@ -93,8 +93,8 @@ async function flyHomeViaApi(page: Page): Promise<void> {
|
|||||||
let s = await getState(page);
|
let s = await getState(page);
|
||||||
let plane = s.planes.find((p) => p.id === 'plane-starter')!;
|
let plane = s.planes.find((p) => p.id === 'plane-starter')!;
|
||||||
if (plane.status === 'flying' || plane.locationIcao !== HUB) {
|
if (plane.status === 'flying' || plane.locationIcao !== HUB) {
|
||||||
// Fast-forward any leftover leg / repositioning flight (~20 s real time worst case at 1000×).
|
// Fast-forward any leftover leg / repositioning flight (~2 s real time worst case at FAST).
|
||||||
await setScale(page, SCALE);
|
await setScale(page, FAST);
|
||||||
}
|
}
|
||||||
if (plane.status === 'flying') {
|
if (plane.status === 'flying') {
|
||||||
// While flying, locationIcao stays at the DEPARTURE airport — re-read state after landing
|
// While flying, locationIcao stays at the DEPARTURE airport — re-read state after landing
|
||||||
@@ -104,8 +104,8 @@ async function flyHomeViaApi(page: Page): Promise<void> {
|
|||||||
plane = s.planes.find((p) => p.id === 'plane-starter')!;
|
plane = s.planes.find((p) => p.id === 'plane-starter')!;
|
||||||
}
|
}
|
||||||
if (plane.locationIcao !== HUB) {
|
if (plane.locationIcao !== HUB) {
|
||||||
// Make sure the world rate is back at SCALE so the return leg fast-forwards.
|
// Make sure the world rate is back at FAST so the return leg fast-forwards.
|
||||||
await setScale(page, SCALE);
|
await setScale(page, FAST);
|
||||||
const res = await page.request.post(`/api/planes/${plane.id}/fly`, { data: { destIcao: HUB } });
|
const res = await page.request.post(`/api/planes/${plane.id}/fly`, { data: { destIcao: HUB } });
|
||||||
expect(res.ok()).toBeTruthy(); // repositioning needs no package (v0.12.0 manual flight)
|
expect(res.ok()).toBeTruthy(); // repositioning needs no package (v0.12.0 manual flight)
|
||||||
await expect.poll(async () => ((await getState(page)).planes.find((p) => p.id === 'plane-starter')!.locationIcao), { timeout: 240_000 }).toBe(HUB);
|
await expect.poll(async () => ((await getState(page)).planes.find((p) => p.id === 'plane-starter')!.locationIcao), { timeout: 240_000 }).toBe(HUB);
|
||||||
@@ -122,7 +122,7 @@ test.afterEach(async ({ page }) => {
|
|||||||
test.describe.configure({ mode: 'serial' }); // shared live DB — order matters within this file
|
test.describe.configure({ mode: 'serial' }); // shared live DB — order matters within this file
|
||||||
|
|
||||||
test('left pane Relocate section relocates a grounded plane', async ({ page }) => {
|
test('left pane Relocate section relocates a grounded plane', async ({ page }) => {
|
||||||
test.setTimeout(300_000); // self-heal (worst case ~20 s at 1000×) + one short leg
|
test.setTimeout(300_000); // self-heal (worst case ~2 s at FAST) + one short leg
|
||||||
await flyHomeViaApi(page);
|
await flyHomeViaApi(page);
|
||||||
|
|
||||||
// Full tank before departure — deterministic baseline (ISS-082 hook; dispatch would auto-refuel anyway).
|
// Full tank before departure — deterministic baseline (ISS-082 hook; dispatch would auto-refuel anyway).
|
||||||
@@ -154,7 +154,7 @@ test('left pane Relocate section relocates a grounded plane', async ({ page }) =
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('airport popup offers Relocate options for grounded planes', async ({ page }) => {
|
test('airport popup offers Relocate options for grounded planes', async ({ page }) => {
|
||||||
test.setTimeout(300_000); // self-heal (worst case ~20 s at 1000×) + one leg to LFRS
|
test.setTimeout(300_000); // self-heal (worst case ~2 s at FAST) + one leg to LFRS
|
||||||
await flyHomeViaApi(page);
|
await flyHomeViaApi(page);
|
||||||
|
|
||||||
// Full tank before departure — deterministic baseline (ISS-082 hook; dispatch would auto-refuel anyway).
|
// Full tank before departure — deterministic baseline (ISS-082 hook; dispatch would auto-refuel anyway).
|
||||||
@@ -221,7 +221,7 @@ test('airport popup offers Relocate options for grounded planes', async ({ page
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('airport popup Relocate queues a leg for a flying plane', async ({ page }) => {
|
test('airport popup Relocate queues a leg for a flying plane', async ({ page }) => {
|
||||||
test.setTimeout(300_000); // self-heal (worst case ~20 s at 1000×) + one short leg, fast-forwarded in cleanup
|
test.setTimeout(300_000); // self-heal (worst case ~2 s at FAST) + one short leg, fast-forwarded in cleanup
|
||||||
await flyHomeViaApi(page);
|
await flyHomeViaApi(page);
|
||||||
|
|
||||||
// Full tank before departure — deterministic baseline (ISS-082 hook; dispatch would auto-refuel anyway).
|
// Full tank before departure — deterministic baseline (ISS-082 hook; dispatch would auto-refuel anyway).
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "flight-ops",
|
"name": "flight-ops",
|
||||||
"version": "1.8.0",
|
"version": "1.9.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev -p 3000",
|
"dev": "next dev -p 3000",
|
||||||
|
|||||||
Reference in New Issue
Block a user