mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-14 07:12:21 +00:00
fix(cockpit): an application subject's wait for the floor is bounded, a late asynchronous hold is released, and a hold never counts as the user's selection
- A subject with no height at all waits at most COCKPIT_GROUND_WAIT_TIMEOUT_MS for the floor, its HUD updating and reading ACQUIRING SURFACE; then the view ends and the provider gets its subject back (there is no height of its own to fall back to). - A hold that returns a promise is refused as before and released again once it settles, unless that subject is being ridden by then; release must tolerate a second call. - Rail and Transit stamp selectedAtMs only for a user's selection (a click, focusTrain or focusVehicle); a deselection clears it, and a train or vehicle selected only by a hold reads null.
This commit is contained in:
1 parent
1e4060f6ba
commit
4c33552105
13 files changed
+239
-28
No files matched your search
@@ -15,6 +15,7 @@ import CockpitView from './views/CockpitView.vue';
|
||||
import ContextView from './views/ContextView.vue';
|
||||
import { cockpitSubjectProviders } from '../cockpitSubjectProviders.js';
|
||||
import { getLocale, setLocale } from '../i18n/index.js';
|
||||
import { COCKPIT_GROUND_WAIT_TIMEOUT_MS } from './cockpitPresentation.js';
|
||||
import { vesselCockpitInfo } from '../layers/vessels/cockpitSubject.js';
|
||||
|
||||
const LAT = 47;
|
||||
@@ -528,18 +529,28 @@ test('a frame with no height and a cold floor never stands the eye on the ellips
|
||||
const clock = manualClock(t, 10_000);
|
||||
const ride = subjectProvider();
|
||||
ride.subject.frame = { ...ride.subject.frame, heightM: null };
|
||||
const { cockpit, shots, setFloor } = fixture(t, { providers: [ride] });
|
||||
// Nothing to stand on from the first frame: the camera waits where it is.
|
||||
const { $, cockpit, shots, setFloor } = fixture(t, { providers: [ride] });
|
||||
// Nothing to stand on from the first frame: the camera waits where it is,
|
||||
// its HUD saying so and still read from the provider.
|
||||
setFloor(undefined);
|
||||
cockpit.syncEntry();
|
||||
assert.equal(cockpit.enter(), true);
|
||||
const before = shots.length;
|
||||
const huds = () => ride.calls.filter(([name]) => name === 'hud').length;
|
||||
const hudsBefore = huds();
|
||||
for (let i = 0; i < 5; i += 1) {
|
||||
clock.advance(16);
|
||||
clock.advance(200);
|
||||
cockpit.update();
|
||||
}
|
||||
await settle();
|
||||
assert.equal(shots.length, before, 'no camera placed');
|
||||
assert.equal(cockpit.active, true, 'the view waits');
|
||||
assert.ok(huds() > hudsBefore, 'the HUD is not frozen');
|
||||
assert.equal($('#cockpit-aircraft-meta').textContent, 'ACQUIRING SURFACE');
|
||||
assert.equal(
|
||||
$('#cockpit-aircraft-meta').getAttribute('data-tone'),
|
||||
'warning',
|
||||
);
|
||||
// The floor arrives: the eye stands on it.
|
||||
setFloor(FLOOR_M);
|
||||
clock.advance(16);
|
||||
@@ -561,6 +572,60 @@ test('a frame with no height and a cold floor never stands the eye on the ellips
|
||||
assert.ok(Math.abs(shotHeight(shots) - (FLOOR_M + 3.5)) < 0.01);
|
||||
});
|
||||
|
||||
test('a floor that never comes ends the view after the bounded wait, releasing the subject', async (t) => {
|
||||
const clock = manualClock(t, 10_000);
|
||||
const ride = subjectProvider();
|
||||
ride.subject.frame = { ...ride.subject.frame, heightM: null };
|
||||
const { $, cockpit, shots, setFloor } = fixture(t, { providers: [ride] });
|
||||
setFloor(undefined);
|
||||
cockpit.syncEntry();
|
||||
assert.equal(cockpit.enter(), true);
|
||||
const before = shots.length;
|
||||
// Acquiring, the HUD updating, for just under the wait...
|
||||
for (let elapsed = 0; elapsed < COCKPIT_GROUND_WAIT_TIMEOUT_MS - 250;) {
|
||||
clock.advance(250);
|
||||
elapsed += 250;
|
||||
cockpit.update();
|
||||
}
|
||||
await settle();
|
||||
assert.equal(cockpit.active, true);
|
||||
assert.equal($('#cockpit-aircraft-meta').textContent, 'ACQUIRING SURFACE');
|
||||
// ...then no guessed height: the view ends and the subject goes back.
|
||||
clock.advance(500);
|
||||
cockpit.update();
|
||||
assert.equal(cockpit.active, false);
|
||||
assert.equal(shots.length, before, 'never placed on a guess');
|
||||
assert.deepEqual(lastRelease(ride.calls), ['release', 'a1', false]);
|
||||
});
|
||||
|
||||
test('an asynchronous hold that lands after entry was refused is released again', async (t) => {
|
||||
let heldId = null;
|
||||
const releases = [];
|
||||
const ride = subjectProvider({
|
||||
hold: async (id) => {
|
||||
await Promise.resolve();
|
||||
heldId = id;
|
||||
return true;
|
||||
},
|
||||
release: (id, options) => {
|
||||
releases.push([id, options.restore]);
|
||||
heldId = null;
|
||||
},
|
||||
});
|
||||
const { cockpit, warned } = fixture(t, { providers: [ride] });
|
||||
cockpit.syncEntry();
|
||||
assert.equal(cockpit.enter(), false, 'refused at once');
|
||||
assert.deepEqual(releases, [['a1', false]]);
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
assert.equal(heldId, null, 'the late hold is let go');
|
||||
assert.deepEqual(releases, [
|
||||
['a1', false],
|
||||
['a1', false],
|
||||
]);
|
||||
assert.equal(cockpit.active, false);
|
||||
assert.match(warned[0], /hold\(\) returned a promise/);
|
||||
});
|
||||
|
||||
test('a provider’s labels, entry face and look follow a change of language', async (t) => {
|
||||
t.after(() => setLocale('en'));
|
||||
setLocale('en');
|
||||
|
||||
Reference in new issue
Block a user