Files
gods-eye-view/src/hudPageVisibility.test.mjs
T
Sameh Khamis c03b4a7643 feat(hud): render the Intel HUD from a store
IntelHUD no longer builds #intel-hud with innerHTML or writes its readouts
by id: it publishes its readouts, typing summary, REC blink, visibility,
layout variant and style colors through its publish option to the gev-hud
store, and the intel-hud application view renders them. The corners render
from mount so the panel layout controllers register them as obstacles.

The vessel layer presents the selected vessel's readout through
src/hudReadouts.js, which IntelHUD follows, instead of writing into the
HUD. The Cyber sonar state answers a HUD toggle from IntelHUD's visibility
rather than the class the view renders on its next update.
2026-10-31 22:18:50 -07:00

91 lines
2.7 KiB
JavaScript

// The HUD's 250 ms telemetry readout skips ticks in a hidden page, except in
// an inline panel, whose host may report it hidden while it is on screen.
//
// hud.js imports `mgrs`, which Node's ESM loader cannot read named exports
// from, so a module hook swaps it for a stub before the import (the same
// setup as hudAltitudeDatum.test.mjs).
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { hudReadouts } from './testSupport/hudReadouts.mjs';
import { registerHooks } from 'node:module';
const MGRS_STUB_URL = 'gev-test-stub:mgrs';
registerHooks({
resolve(specifier, context, next) {
if (specifier === 'mgrs') return { url: MGRS_STUB_URL, shortCircuit: true };
return next(specifier, context);
},
load(url, context, next) {
if (url === MGRS_STUB_URL) {
return {
format: 'module',
shortCircuit: true,
source: 'export function forward() { return "10SEG55776339"; }\nexport default { forward };\n',
};
}
return next(url, context);
},
});
const { IntelHUD } = await import('./hud.js');
function installHiddenPage() {
const { elements, publish } = hudReadouts();
const previousDocument = globalThis.document;
globalThis.document = {
hidden: true,
visibilityState: 'hidden',
getElementById: (id) => elements.get(id) ?? null,
querySelectorAll: () => [],
addEventListener() {},
removeEventListener() {},
};
const viewer = {
camera: {
pitch: -Math.PI / 2,
positionCartographic: { latitude: 0.7, longitude: -1.2, height: 500 },
computeViewRectangle: () => undefined,
moveStart: { addEventListener() {}, removeEventListener() {} },
moveEnd: { addEventListener() {}, removeEventListener() {} },
},
};
return {
alt: () => elements.get('hud-alt').textContent,
viewer,
publish,
restore() {
if (previousDocument === undefined) delete globalThis.document;
else globalThis.document = previousDocument;
},
};
}
test('the HUD readout pauses in a hidden page but keeps updating in an inline panel', (t) => {
t.mock.timers.enable({ apis: ['setInterval'] });
const page = installHiddenPage();
let hud;
try {
hud = new IntelHUD(page.viewer, { publish: page.publish });
hud._visible = true;
t.mock.timers.tick(250);
assert.equal(
page.alt(),
'ALT: --m SUN: --° EL',
'a hidden page skips the telemetry tick',
);
globalThis.GEV_EMBED_INLINE = true;
t.mock.timers.tick(250);
assert.match(
page.alt(),
/^ALT: 500m/,
'an inline panel reported hidden keeps its readout updating',
);
} finally {
delete globalThis.GEV_EMBED_INLINE;
hud?.destroy();
page.restore();
}
});