Wait for the directions route flight instead of three seconds

The FLY check slept a fixed 3 s and then expected a route flight, which
passed or failed on the same commit. It now waits, up to 15 s, for the
layer to report the route motion and the camera to move.
This commit is contained in:
German Khokhlov committed 2026-11-11 02:07:36 +04:00
1 parent 00cb44ad2c
commit 49b2849528
2 files changed
+101 -3

No files matched your search

+26 -3
View File
@@ -159,6 +159,28 @@ const setMode = async (mode) => {
await clickChip(`mode-${mode}`);
};
const waitForFlight = (before) =>
pollPage(
page,
(origin) => {
const { engine, dataManager } = window.__godsEyeView;
const motion = dataManager.layers
.get('directions')
.module.getFlightProgress();
const position = engine.camera.pose().position;
return (
motion?.kind === 'route' &&
motion.traveledM > 0 &&
Math.hypot(
position.x - origin.x,
position.y - origin.y,
position.z - origin.z,
) > 50
);
},
{ timeoutMs: 15000, intervalMs: 50, args: [before] },
);
const waitForRoute = () =>
page.waitForFunction(
() =>
@@ -665,12 +687,12 @@ try {
// ── 7. FLY, a mid-flight frame, and a cancel that actually stops it. ─────
const beforeFly = await cameraPose();
check('the FLY chip is offered once a route exists', await clickChip('fly'));
await sleep(3000);
const flightStarted = await waitForFlight(beforeFly);
const flying = await layerState();
const midFly = await cameraPose();
check(
'FLY starts a route flight',
flying.cameraMotion?.kind === 'route',
flightStarted && flying.cameraMotion?.kind === 'route',
JSON.stringify(flying.cameraMotion),
);
check(
@@ -699,8 +721,9 @@ try {
await setMode('car');
await waitForMode('Drive');
await whenUiSettled(page);
const beforeRefly = await cameraPose();
check('FLY is offered again after the reroute', await clickChip('fly'));
await sleep(2000);
check('the second FLY starts before CLEAR', await waitForFlight(beforeRefly));
await clickChip('clear');
await sleep(500);
+75
View File
@@ -0,0 +1,75 @@
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import test from 'node:test';
import vm from 'node:vm';
import { pollPage } from './qa/ready.mjs';
import { createFakeEngine } from '../src/globe/testing/fakeEngine.js';
// Evaluate the browser wait without launching the executable scenario.
const source = readFileSync(
new URL('./qa-directions.mjs', import.meta.url),
'utf8',
);
const waitSource = source.slice(
source.indexOf('const waitForFlight ='),
source.indexOf('const waitForRoute ='),
);
for (const startsAt of [50, 12000, null]) {
test(`directions FLY waits for owned route progress (${startsAt ?? 'never'} ms)`, async (t) => {
const engine = createFakeEngine();
t.after(() => engine.destroy());
let motion = null;
let disposed = 0;
let observedAt;
const before = engine.camera.pose().position;
const waitForFlight = vm.runInNewContext(`${waitSource}\nwaitForFlight`, {
pollPage,
window: {
__godsEyeView: {
engine,
dataManager: {
layers: new Map([
['directions', { module: { getFlightProgress: () => motion } }],
]),
},
},
},
page: {
async waitForFunction(check, options, origin) {
const predicate = () => check(origin);
assert.equal(options.timeout, 15000);
assert.equal(options.polling, 50);
assert.equal(predicate(), false, 'no owned flight yet');
motion = { kind: 'route', traveledM: 0 };
assert.equal(predicate(), false, 'arming is not a mid-flight frame');
motion = { kind: 'orbit', traveledM: 20 };
assert.equal(predicate(), false, 'another camera motion cannot pass');
motion = { kind: 'route', traveledM: 20 };
assert.equal(predicate(), false, 'the camera must have moved too');
engine.fake.setPose({ position: { ...before, y: before.y + 60 } });
for (let time = 0; time < options.timeout; time += options.polling) {
motion =
startsAt !== null && time >= startsAt
? { kind: 'route', traveledM: 20 }
: null;
if (predicate()) {
observedAt = time;
return {
dispose: async () => {
disposed++;
},
};
}
}
const error = new Error('flight did not start');
error.name = 'TimeoutError';
throw error;
},
},
});
assert.equal(await waitForFlight(before), startsAt !== null);
assert.equal(observedAt, startsAt ?? undefined);
assert.equal(disposed, startsAt === null ? 0 : 1);
});
}