mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-11 13:52:19 +00:00
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:
1 parent
00cb44ad2c
commit
49b2849528
2 files changed
+101
-3
No files matched your search
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user