mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 18:34:02 +00:00
Extract instance-owned civil-flight components
This commit is contained in:
1 parent
cf149ecfc0
commit
7c7e83c9e3
33 files changed
+6190
-5284
No files matched your search
@@ -1,3 +1,4 @@
|
||||
import { readLayerSource } from '../testSupport/readLayerSource.mjs';
|
||||
import { dispatchCockpitModeChanged, enter, exit, _adoptTrackedEntity } from '../ui/cockpitTrackingController.js';
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
@@ -15,8 +16,8 @@ import militaryFlightsLayer, {
|
||||
const SUBJECT = 'abc123';
|
||||
const NEXT_SUBJECT = 'def456';
|
||||
|
||||
const FLIGHTS_SOURCE = readFileSync(new URL('./flights.js', import.meta.url), 'utf8');
|
||||
const MILITARY_SOURCE = readFileSync(new URL('./militaryFlights.js', import.meta.url), 'utf8');
|
||||
const FLIGHTS_SOURCE = readLayerSource(new URL('./flights.js', import.meta.url));
|
||||
const MILITARY_SOURCE = readLayerSource(new URL('./militaryFlights.js', import.meta.url));
|
||||
|
||||
const LAYERS = [
|
||||
{
|
||||
@@ -108,7 +109,7 @@ test('Cockpit lifecycle publishes one normalized aircraft identity to both detec
|
||||
['commercial', FLIGHTS_SOURCE],
|
||||
['military', MILITARY_SOURCE],
|
||||
]) {
|
||||
const consumer = /function _applyCockpitState\(detail = \{\}\) \{[\s\S]*?\n\}/
|
||||
const consumer = /function (?:parts\.\w+\.)?_applyCockpitState\(detail = \{\}\) \{[\s\S]*?\n\}/
|
||||
.exec(source)?.[0];
|
||||
assert.ok(consumer, `${name} Cockpit consumer is defined`);
|
||||
assert.match(consumer, /detail\?\.subjectId/);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { readLayerSource } from '../testSupport/readLayerSource.mjs';
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
@@ -25,7 +26,7 @@ function numericConstant(source, name) {
|
||||
}
|
||||
|
||||
for (const layer of LAYERS) {
|
||||
const source = readFileSync(layer.path, 'utf8');
|
||||
const source = readLayerSource(layer.path);
|
||||
|
||||
test(`${layer.name}: every GLB creation bypasses the tile-contended frame-spread queue`, () => {
|
||||
const calls = [...source.matchAll(/Cesium\.Model\.fromGltfAsync\(\{([\s\S]*?)\}\)/g)];
|
||||
@@ -37,11 +38,11 @@ for (const layer of LAYERS) {
|
||||
});
|
||||
|
||||
test(`${layer.name}: Cockpit 3D obeys the shared Display toggle`, () => {
|
||||
const regime = /function _modelRegimeActive\(\) \{[\s\S]*?\n\}/.exec(source)?.[0];
|
||||
const regime = /function (?:parts\.\w+\.)?_modelRegimeActive\(\) \{[\s\S]*?\n\}/.exec(source)?.[0];
|
||||
assert.ok(regime, '_modelRegimeActive is defined');
|
||||
assert.match(regime, /if \(!_models3dEnabled\) return false;/,
|
||||
assert.match(regime, /if \(!(?:flightState\.)?_models3dEnabled\) return false;/,
|
||||
'OFF must keep Cockpit AIR contacts in 2D');
|
||||
assert.doesNotMatch(regime, /!_models3dEnabled\s*&&\s*!_cockpitContactMode/,
|
||||
assert.doesNotMatch(regime, /!(?:flightState\.)?_models3dEnabled\s*&&\s*!(?:flightState\.)?_cockpitContactMode/,
|
||||
'Cockpit must not bypass the owner-visible Display toggle');
|
||||
});
|
||||
|
||||
@@ -51,13 +52,13 @@ for (const layer of LAYERS) {
|
||||
// owns. The tracked regime is DEFAULT-ON by camera distance (2026-08-19), so
|
||||
// it no longer routes through the toggle-gated `_modelRegimeActive` — the
|
||||
// suppression is now an explicit early return.
|
||||
const regime = /function _trackedModelRegimeActive\(\) \{[\s\S]*?\n\}/.exec(source)?.[0];
|
||||
const regime = /function (?:parts\.\w+\.)?_trackedModelRegimeActive\(\) \{[\s\S]*?\n\}/.exec(source)?.[0];
|
||||
assert.ok(regime, '_trackedModelRegimeActive is defined');
|
||||
assert.match(regime, /if \(!_trackedIcao \|\| _cockpitContactMode \|\|[\s\S]*?return false;/,
|
||||
assert.match(regime, /if \(!(?:flightState\.)?_trackedIcao \|\| (?:flightState\.)?_cockpitContactMode \|\|[\s\S]*?return false;/,
|
||||
'_trackedModelRegimeActive excludes cockpit');
|
||||
const tracked = /function _updateTrackedModel\(\)[\s\S]*?\n if \(!active\)/.exec(source)?.[0];
|
||||
const tracked = /function (?:parts\.\w+\.)?_updateTrackedModel\(\)[\s\S]*?\n if \(!active\)/.exec(source)?.[0];
|
||||
assert.ok(tracked, '_updateTrackedModel is defined');
|
||||
assert.match(tracked, /_trackedModelRegimeActive\(\)/,
|
||||
assert.match(tracked, /(?:parts\.\w+\.)?_trackedModelRegimeActive\(\)/,
|
||||
'the tracked-model driver uses the cockpit-aware predicate');
|
||||
});
|
||||
|
||||
@@ -68,14 +69,14 @@ for (const layer of LAYERS) {
|
||||
assert.equal(numericConstant(source, 'MODEL_ALL_KEEP_M'), 450_000);
|
||||
assert.equal(numericConstant(source, 'COCKPIT_MODEL_MAX'), 60);
|
||||
|
||||
const add = /function _modelAddDistM\(\) \{[\s\S]*?\n\}/.exec(source)?.[0];
|
||||
const keep = /function _modelKeepDistM\(\) \{[\s\S]*?\n\}/.exec(source)?.[0];
|
||||
assert.match(add, /_models3dMode === 'all' \? MODEL_ALL_ADD_M : MODEL_PROX_ADD_M/);
|
||||
assert.match(keep, /_models3dMode === 'all' \? MODEL_ALL_KEEP_M : MODEL_PROX_KEEP_M/);
|
||||
const add = /function (?:parts\.\w+\.)?_modelAddDistM\(\) \{[\s\S]*?\n\}/.exec(source)?.[0];
|
||||
const keep = /function (?:parts\.\w+\.)?_modelKeepDistM\(\) \{[\s\S]*?\n\}/.exec(source)?.[0];
|
||||
assert.match(add, /(?:flightState\.)?_models3dMode === 'all' \? MODEL_ALL_ADD_M : MODEL_PROX_ADD_M/);
|
||||
assert.match(keep, /(?:flightState\.)?_models3dMode === 'all' \? MODEL_ALL_KEEP_M : MODEL_PROX_KEEP_M/);
|
||||
assert.doesNotMatch(add, /COCKPIT_MODEL_ADD_M/);
|
||||
assert.doesNotMatch(keep, /COCKPIT_MODEL_KEEP_M/);
|
||||
|
||||
const cap = /function _modelCap\(\) \{[\s\S]*?\n\}/.exec(source)?.[0];
|
||||
const cap = /function (?:parts\.\w+\.)?_modelCap\(\) \{[\s\S]*?\n\}/.exec(source)?.[0];
|
||||
assert.match(cap, /Math\.min\(COCKPIT_MODEL_MAX/,
|
||||
'Cockpit keeps its 60-model performance ceiling');
|
||||
});
|
||||
@@ -92,15 +93,15 @@ for (const layer of LAYERS) {
|
||||
'near contacts and model fallbacks retain the class-derived aircraft silhouette');
|
||||
assert.match(source, /bb\.rotation = 0;/,
|
||||
'far dots are reset to a rotation-free presentation');
|
||||
assert.match(source, /\(!_cockpitContactMode \|\| isCockpitNear\) && \(doRotations \|\| revealed\)/,
|
||||
assert.match(source, /\(!(?:flightState\.)?_cockpitContactMode \|\| isCockpitNear\) && \(doRotations \|\| revealed\)/,
|
||||
'near 2D silhouettes continue to receive projected course');
|
||||
assert.match(source, /if \(bb\.show\) bb\.show = false; \/\/ hand off ONLY once the model renders/,
|
||||
'the gap-proof billboard-to-model handoff remains intact');
|
||||
});
|
||||
|
||||
test(`${layer.name}: Cockpit exit clears near state before restoring map presentation`, () => {
|
||||
const setMode = /function _setCockpitContactMode\([\s\S]*?\n\}/.exec(source)?.[0];
|
||||
assert.match(setMode, /else _cockpitNearContacts = new Set\(\);/);
|
||||
assert.match(setMode, /for \(const \[icao24, bb\] of _billboards\) _applyFleetBillboardPresentation\(icao24, bb\);/);
|
||||
const setMode = /function (?:parts\.\w+\.)?_setCockpitContactMode\([\s\S]*?\n\}/.exec(source)?.[0];
|
||||
assert.match(setMode, /else (?:flightState\.)?_cockpitNearContacts = new Set\(\);/);
|
||||
assert.match(setMode, /for \(const \[icao24, bb\] of (?:flightState\.)?_billboards\) (?:parts\.\w+\.)?_applyFleetBillboardPresentation\(icao24, bb\);/);
|
||||
});
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { readLayerSource } from '../testSupport/readLayerSource.mjs';
|
||||
// src/data/detectionRenderDemand.test.mjs
|
||||
//
|
||||
// Detection must not hold the render loop open — and must not drop work on the
|
||||
@@ -427,7 +428,7 @@ test('the render-governor gate covers the parked case, with teeth on the painter
|
||||
// promptness goes with them, silently. This test is where that shows up.
|
||||
test('aircraft brackets stay prompt because the aircraft layers hold the render loop', async () => {
|
||||
for (const file of ['./flights.js', './militaryFlights.js']) {
|
||||
const source = await readFile(new URL(file, import.meta.url), 'utf8');
|
||||
const source = readLayerSource(new URL(file, import.meta.url));
|
||||
const enable = /\n enable\([\s\S]*?\n \},/.exec(source)?.[0];
|
||||
assert.ok(enable, `${file}: enable() is still identifiable`);
|
||||
assert.match(
|
||||
|
||||
+36
-5210
File diff suppressed because it is too large.
Load diff
@@ -1,3 +1,4 @@
|
||||
import { readLayerSource } from '../testSupport/readLayerSource.mjs';
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
|
||||
@@ -365,21 +366,21 @@ test('a fresh boot starts 3D aircraft ON in proximity — codec, both layers, an
|
||||
// first-run session actually boots from.
|
||||
const { readFile } = await import('node:fs/promises');
|
||||
for (const name of ['flights.js', 'militaryFlights.js']) {
|
||||
const source = await readFile(new URL(`./${name}`, import.meta.url), 'utf8');
|
||||
assert.match(source, /^let _models3dEnabled = true;$/m,
|
||||
const source = readLayerSource(new URL(`./${name}`, import.meta.url));
|
||||
assert.match(source, /^\s*(?:let |flightState\.)_models3dEnabled = true;$/m,
|
||||
`${name}: the fleet starts armed, matching the codec default`);
|
||||
assert.match(source, /^let _models3dMode = 'proximity';/m,
|
||||
assert.match(source, /^\s*(?:let |flightState\.)_models3dMode = 'proximity';/m,
|
||||
`${name}: and starts in proximity, matching the codec default`);
|
||||
}
|
||||
const ui = await readFile(new URL('../ui/applicationShell.js', import.meta.url), 'utf8');
|
||||
assert.match(ui, /^\s*this\._models3dEnabled = true;$/m,
|
||||
assert.match(ui, /^\s*this\.(?:flightState\.)?_models3dEnabled = true;$/m,
|
||||
'ui.js: the DISPLAY rail believes 3D is on before any layer-state sync arrives');
|
||||
assert.match(ui, /this\._models3dMode = 'proximity';/,
|
||||
assert.match(ui, /this\.(?:flightState\.)?_models3dMode = 'proximity';/,
|
||||
'ui.js: and believes the mode is proximity');
|
||||
const html = await readFile(new URL('../../index.html', import.meta.url), 'utf8');
|
||||
assert.match(html, /class="pp-toggle-btn active" id="models3d-toggle" aria-pressed="true"/,
|
||||
'index.html: the 3D button paints lit on first paint, before ui.js runs — and says so');
|
||||
assert.match(ui, /this\._models3dBtn\?\.setAttribute\(\s*'aria-pressed',\s*String\(this\._models3dEnabled\),?\s*\)/,
|
||||
assert.match(ui, /this\._models3dBtn\?\.setAttribute\(\s*'aria-pressed',\s*String\(this\.(?:flightState\.)?_models3dEnabled\),?\s*\)/,
|
||||
'ui.js: and keeps aria-pressed synchronized, so the lit state is not colour-only');
|
||||
assert.match(html, /class="pp-slider-row visible" id="models3d-mode-row"/,
|
||||
'index.html: and the Proximity/All row paints open with it');
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { readLayerSource } from '../testSupport/readLayerSource.mjs';
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
@@ -297,7 +298,7 @@ test('Contacts live repaint restores only stable identity and never retargets an
|
||||
});
|
||||
|
||||
test('Contacts continuation target is the visible explanatory note', () => {
|
||||
const source = fs.readFileSync(new URL('./militaryAwareness.js', import.meta.url), 'utf8');
|
||||
const source = readLayerSource(new URL('./militaryAwareness.js', import.meta.url));
|
||||
assert.match(
|
||||
source,
|
||||
/<p class="military-awareness-note" tabindex="-1" data-awareness-focus-continuation>Open-source mapped\/observed context\./,
|
||||
@@ -1352,11 +1353,11 @@ test('hasContact declines while a layer is disabled, whatever its maps still hol
|
||||
// disable() hides the collection but keeps the records, so a map lookup
|
||||
// alone would report a preserved subject as FRESH from hidden stale data.
|
||||
for (const [name, source, guard] of [
|
||||
['flights', fs.readFileSync(new URL('./flights.js', import.meta.url), 'utf8'),
|
||||
/hasContact\(icao24\) \{\s*\n\s*if \(!_billboardCollection \|\| !_billboardCollection\.show \|\| _billboards\.size === 0\) return null;/],
|
||||
['militaryFlights', fs.readFileSync(new URL('./militaryFlights.js', import.meta.url), 'utf8'),
|
||||
/hasContact\(icao24\) \{\s*\n\s*if \(!_billboardCollection \|\| !_billboardCollection\.show \|\| _billboards\.size === 0\) return null;/],
|
||||
['aisLiveVessels', fs.readFileSync(new URL('./aisLiveVessels.js', import.meta.url), 'utf8'),
|
||||
['flights', readLayerSource(new URL('./flights.js', import.meta.url)),
|
||||
/hasContact\(icao24\) \{\s*\n\s*if \(!(?:flightState\.)?_billboardCollection \|\| !(?:flightState\.)?_billboardCollection\.show \|\| (?:flightState\.)?_billboards\.size === 0\) return null;/],
|
||||
['militaryFlights', readLayerSource(new URL('./militaryFlights.js', import.meta.url)),
|
||||
/hasContact\(icao24\) \{\s*\n\s*if \(!(?:flightState\.)?_billboardCollection \|\| !(?:flightState\.)?_billboardCollection\.show \|\| (?:flightState\.)?_billboards\.size === 0\) return null;/],
|
||||
['aisLiveVessels', readLayerSource(new URL('./aisLiveVessels.js', import.meta.url)),
|
||||
/hasContact\(mmsi\) \{\s*\n\s*if \(!state\.enabled \|\| !state\.vesselMap \|\| state\.vesselMap\.size === 0\) return null;/],
|
||||
]) {
|
||||
assert.match(source, guard, `${name}.hasContact must decline while the layer is disabled`);
|
||||
@@ -1527,14 +1528,14 @@ test('a deliberate source clear still fully clears the subject', () => {
|
||||
test('production eviction sites actually tag their clears', () => {
|
||||
// The event contract above is worthless if the real cull paths never set the
|
||||
// origin, so pin the three production call sites.
|
||||
const flightsSource = fs.readFileSync(new URL('./flights.js', import.meta.url), 'utf8');
|
||||
const militarySource = fs.readFileSync(new URL('./militaryFlights.js', import.meta.url), 'utf8');
|
||||
const vesselsSource = fs.readFileSync(new URL('./aisLiveVessels.js', import.meta.url), 'utf8');
|
||||
const flightsSource = readLayerSource(new URL('./flights.js', import.meta.url));
|
||||
const militarySource = readLayerSource(new URL('./militaryFlights.js', import.meta.url));
|
||||
const vesselsSource = readLayerSource(new URL('./aisLiveVessels.js', import.meta.url));
|
||||
|
||||
for (const [name, source] of [['flights', flightsSource], ['militaryFlights', militarySource]]) {
|
||||
assert.match(
|
||||
source,
|
||||
/if \(icao24 === _trackedIcao\) \{\s*\n\s*_clearTracking\(false, \{ evicted: true \}\);/,
|
||||
/if \(icao24 === (?:flightState\.)?_trackedIcao\) \{\s*\n\s*(?:parts\.\w+\.)?_clearTracking\(false, \{ evicted: true \}\);/,
|
||||
`${name} must mark its aged-out cull as an eviction`,
|
||||
);
|
||||
assert.match(
|
||||
@@ -1553,7 +1554,7 @@ test('production eviction sites actually tag their clears', () => {
|
||||
// The tag alone is not enough — see the behavioral test in
|
||||
// firmsInteraction.test.mjs. The clear must also run BEFORE renderCurrentLod,
|
||||
// whose registration sweep deletes the record the clear needs to see.
|
||||
const firmsSource = fs.readFileSync(new URL('./firmsHeatmap.js', import.meta.url), 'utf8');
|
||||
const firmsSource = readLayerSource(new URL('./firmsHeatmap.js', import.meta.url));
|
||||
const evictedClear = firmsSource.indexOf('clearSelectedEntityContextForLayer(id, { evicted: true });');
|
||||
const lodRebuild = firmsSource.indexOf('renderCurrentLod(true);\n if (reselected) selectFire(reselected);');
|
||||
assert.ok(evictedClear > 0, 'FIRMS must mark a refresh-vanished selection as an eviction');
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { readLayerSource } from '../testSupport/readLayerSource.mjs';
|
||||
// Regression test for the giant-military-jet bug: MODEL_SCALE must put every
|
||||
// rendered aircraft at REAL-WORLD size, whatever the GLB's native scale is.
|
||||
//
|
||||
@@ -358,7 +359,7 @@ function nativeVisualCenter(file) {
|
||||
// --- per-layer constants, read from source (see header) --------------------
|
||||
|
||||
function layerConstants(sourceFile) {
|
||||
const src = fs.readFileSync(path.join(ROOT, sourceFile), 'utf8');
|
||||
const src = readLayerSource(path.join(ROOT, sourceFile));
|
||||
const scale = src.match(/\bconst MODEL_SCALE = ([\d.]+);/);
|
||||
assert.ok(scale, `${sourceFile}: MODEL_SCALE not found`);
|
||||
const belly = src.match(/\bconst MODEL_BELLY_OFFSET_NATIVE = ([\d.]+);/);
|
||||
@@ -367,8 +368,8 @@ function layerConstants(sourceFile) {
|
||||
}
|
||||
|
||||
function normalBillboardScaleByDistance(sourceFile) {
|
||||
const src = fs.readFileSync(path.join(ROOT, sourceFile), 'utf8');
|
||||
const fn = src.match(/function _normalBillboardScaleByDistance\(\) \{([\s\S]*?)\n\}/);
|
||||
const src = readLayerSource(path.join(ROOT, sourceFile));
|
||||
const fn = src.match(/function (?:parts\.\w+\.)?_normalBillboardScaleByDistance\(\) \{([\s\S]*?)\n\}/);
|
||||
assert.ok(fn, `${sourceFile}: _normalBillboardScaleByDistance not found`);
|
||||
const scalar = fn[1].match(/NearFarScalar\((\d+), ([\d.]+), (\d+), ([\d.]+)\)/);
|
||||
assert.ok(scalar, `${sourceFile}: billboard NearFarScalar not found`);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { readLayerSource } from '../testSupport/readLayerSource.mjs';
|
||||
// src/data/tr3bRegistry.test.mjs
|
||||
// TR-3B conversion Easter egg: registry state, sprite-variant selection,
|
||||
// class-label override, and the render-path invariants that keep a converted
|
||||
@@ -227,7 +228,7 @@ test('a conversion survives a poll refresh, in both the billboard and the tracke
|
||||
|
||||
test('both flight layers keep a converted contact 2D and visible (render invariants)', async () => {
|
||||
for (const name of ['flights.js', 'militaryFlights.js']) {
|
||||
const source = await readFile(new URL(`./${name}`, import.meta.url), 'utf8');
|
||||
const source = readLayerSource(new URL(`./${name}`, import.meta.url));
|
||||
|
||||
// 1. The 3D model handoff is SUPPRESSED for a converted contact — there is
|
||||
// no TR-3B GLB, so the triangle billboard stays the visual.
|
||||
@@ -237,13 +238,13 @@ test('both flight layers keep a converted contact 2D and visible (render invaria
|
||||
// (2026-08-19), so the suppression moved from a conjunct on
|
||||
// `_modelRegimeActive()` to an explicit early return. The invariant is
|
||||
// unchanged: a converted contact never reaches the model handoff.
|
||||
assert.match(source, /if \(!_trackedIcao \|\| _cockpitContactMode \|\| isTr3b\(_trackedIcao\)\) \{/,
|
||||
assert.match(source, /if \(!(?:flightState\.)?_trackedIcao \|\| (?:flightState\.)?_cockpitContactMode \|\| isTr3b\((?:flightState\.)?_trackedIcao\)\) \{/,
|
||||
`${name}: the standalone tracked model is suppressed for a converted contact`);
|
||||
|
||||
// 2. The billboard is never hidden by that suppression — it must keep
|
||||
// satisfying the getNearby/getDetectableObjects visibility guards, so a
|
||||
// converted contact still works in Contacts and Cockpit.
|
||||
assert.match(source, /if \(bb && id !== _trackedIcao\) bb\.show = true;|if \(modelled && id !== _trackedIcao\) modelled\.show = true;/,
|
||||
assert.match(source, /if \(bb && id !== (?:flightState\.)?_trackedIcao\) bb\.show = true;|if \(modelled && id !== (?:flightState\.)?_trackedIcao\) modelled\.show = true;/,
|
||||
`${name}: converting restores the billboard the model handoff had hidden`);
|
||||
|
||||
// 3. Every aircraftIcon() CALL SITE routes through the kind resolver, so no
|
||||
@@ -253,7 +254,7 @@ test('both flight layers keep a converted contact 2D and visible (render invaria
|
||||
const callSites = code.match(/aircraftIcon\(\s*[^;]*?\)/g) || [];
|
||||
assert.equal(callSites.length >= 4, true, `${name}: expected the known aircraftIcon call sites`);
|
||||
for (const call of callSites) {
|
||||
assert.match(call, /aircraftIcon\(\s*_iconKind\(/,
|
||||
assert.match(call, /aircraftIcon\(\s*(?:parts\.rendering\.)?_iconKind\(/,
|
||||
`${name}: ${call.replace(/\s+/g, ' ')} must resolve its sprite kind through _iconKind`);
|
||||
}
|
||||
|
||||
@@ -271,7 +272,7 @@ test('conversions are session-scoped and no lifecycle path clears them', async (
|
||||
// should still show the triangle. Only a page reload resets it — so no
|
||||
// production code may clear the registry.
|
||||
for (const name of ['flights.js', 'militaryFlights.js', '../ui/applicationShell.js']) {
|
||||
const source = await readFile(new URL(`./${name}`, import.meta.url), 'utf8');
|
||||
const source = readLayerSource(new URL(`./${name}`, import.meta.url));
|
||||
assert.doesNotMatch(source, /clearTr3bRegistry/,
|
||||
`${name}: teardown must not clear session conversions`);
|
||||
}
|
||||
@@ -406,10 +407,10 @@ test('a converted contact never consumes a 3D model CAP SLOT', async () => {
|
||||
// in the fleet tick (no seam to drive headlessly), so this asserts the guard's
|
||||
// POSITION rather than replaying the four-pass selection.
|
||||
for (const name of ['flights.js', 'militaryFlights.js']) {
|
||||
const source = await readFile(new URL(`./${name}`, import.meta.url), 'utf8');
|
||||
const source = readLayerSource(new URL(`./${name}`, import.meta.url));
|
||||
// Anchor on the MODEL-eligibility loop (keepDistSq), not the unrelated
|
||||
// ambient-enrichment candidate loop that also builds a `cand`.
|
||||
const loop = /const cand = \[\];\s*\n\s*for \(const \[icao, bb\] of _billboards\)[\s\S]*?cand\.push\(/.exec(source)?.[0];
|
||||
const loop = /const cand = \[\];\s*\n\s*for \(const \[icao, bb\] of (?:flightState\.)?_billboards\)[\s\S]*?cand\.push\(/.exec(source)?.[0];
|
||||
assert.ok(loop, `${name}: the model-eligibility candidate loop is present`);
|
||||
assert.match(loop, /keepDistSq/, `${name}: matched the model-eligibility loop`);
|
||||
assert.match(loop, /if \(isTr3b\(icao\)\) continue;/,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { readLayerSource } from '../testSupport/readLayerSource.mjs';
|
||||
// src/data/trackedModelRegime.test.mjs
|
||||
//
|
||||
// Zoom-driven 2D↔3D for the TRACKED contact (owner directive 2026-08-19).
|
||||
@@ -931,15 +932,15 @@ for (const fixture of LAYERS) {
|
||||
test('both layers gate the tracked-model load and record its failures', async () => {
|
||||
const { readFile } = await import('node:fs/promises');
|
||||
for (const name of ['flights.js', 'militaryFlights.js']) {
|
||||
const source = await readFile(new URL(`./${name}`, import.meta.url), 'utf8');
|
||||
assert.match(source, /!_trackedModel && !_trackedModelLoading && _trackedModelLoadAllowed\(\)/,
|
||||
const source = readLayerSource(new URL(`./${name}`, import.meta.url));
|
||||
assert.match(source, /!(?:flightState\.)?_trackedModel && !(?:flightState\.)?_trackedModelLoading && (?:parts\.\w+\.)?_trackedModelLoadAllowed\(\)/,
|
||||
`${name}: the driver asks permission before starting another tracked-model load`);
|
||||
assert.match(source, /_noteTrackedModelLoadFailure\(trackedSpec\.url, err\)/,
|
||||
assert.match(source, /(?:parts\.\w+\.)?_noteTrackedModelLoadFailure\(trackedSpec\.url, err\)/,
|
||||
`${name}: a rejected load is recorded against this selection, not silently retried`);
|
||||
// The reset must be reachable from the real teardown, not only a test seam.
|
||||
assert.match(source, /_releaseTrackedModel\(\);\n _resetTrackedSelectionState\(\);/,
|
||||
assert.match(source, /(?:parts\.\w+\.)?_releaseTrackedModel\(\);\n (?:parts\.\w+\.)?_resetTrackedSelectionState\(\);/,
|
||||
`${name}: deselect clears the per-selection latches in the production path`);
|
||||
assert.match(source, /_trackedIcao = icao24;\n _resetTrackedSelectionState\(\);/,
|
||||
assert.match(source, /(?:flightState\.)?_trackedIcao = icao24;\n (?:parts\.\w+\.)?_resetTrackedSelectionState\(\);/,
|
||||
`${name}: selecting a contact starts from a clean per-selection state`);
|
||||
}
|
||||
});
|
||||
@@ -947,16 +948,16 @@ test('both layers gate the tracked-model load and record its failures', async ()
|
||||
test('the tracked regime never consults the fleet models3d toggle', async () => {
|
||||
const { readFile } = await import('node:fs/promises');
|
||||
for (const name of ['flights.js', 'militaryFlights.js']) {
|
||||
const source = await readFile(new URL(`./${name}`, import.meta.url), 'utf8');
|
||||
const regime = /function _trackedModelRegimeActive\(\) \{[\s\S]*?\n\}/.exec(source)?.[0];
|
||||
const source = readLayerSource(new URL(`./${name}`, import.meta.url));
|
||||
const regime = /function (?:parts\.\w+\.)?_trackedModelRegimeActive\(\) \{[\s\S]*?\n\}/.exec(source)?.[0];
|
||||
assert.ok(regime, `${name}: _trackedModelRegimeActive is defined`);
|
||||
assert.doesNotMatch(regime, /_models3dEnabled|_modelRegimeActive\(\)/,
|
||||
assert.doesNotMatch(regime, /(?:flightState\.)?_models3dEnabled|(?:parts\.\w+\.)?_modelRegimeActive\(\)/,
|
||||
`${name}: the tracked contact's handoff is default-on, not gated on the fleet toggle`);
|
||||
assert.match(regime, /trackedModelZoomActive\(/,
|
||||
`${name}: the tracked contact uses the shared hysteretic zoom policy`);
|
||||
// The FLEET must still obey the toggle — the budget decision stays the operator's.
|
||||
const fleet = /function _modelRegimeActive\(\) \{[\s\S]*?\n\}/.exec(source)?.[0];
|
||||
assert.match(fleet, /if \(!_models3dEnabled\) return false;/,
|
||||
const fleet = /function (?:parts\.\w+\.)?_modelRegimeActive\(\) \{[\s\S]*?\n\}/.exec(source)?.[0];
|
||||
assert.match(fleet, /if \(!(?:flightState\.)?_models3dEnabled\) return false;/,
|
||||
`${name}: the fleet regime still obeys the DISPLAY-rail 3D toggle`);
|
||||
}
|
||||
});
|
||||
@@ -1,3 +1,4 @@
|
||||
import { readLayerSource } from '../testSupport/readLayerSource.mjs';
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
@@ -244,13 +245,13 @@ test('tracking layers write gevLabelModel and expose only their cached display p
|
||||
'militaryFlights.js',
|
||||
'satellites.js',
|
||||
'militaryInstallations.js',
|
||||
].map(async (name) => [name, await readFile(new URL(`./${name}`, import.meta.url), 'utf8')]));
|
||||
].map(async (name) => [name, readLayerSource(new URL(`./${name}`, import.meta.url))]));
|
||||
const sources = Object.fromEntries(files);
|
||||
for (const [name, source] of files) {
|
||||
assert.ok(source.includes('.gevLabelModel ='), `${name} writes the explicit model directly`);
|
||||
assert.ok(source.includes('.gevDisplayPosition ='), `${name} exposes a display-position cache`);
|
||||
}
|
||||
assert.ok(sources['flights.js'].includes('gevDisplayPosition = _trackedDisplayCached'));
|
||||
assert.match(sources['flights.js'], /gevDisplayPosition = parts\.motion\._trackedDisplayCached/);
|
||||
assert.ok(sources['militaryFlights.js'].includes('gevDisplayPosition = _trackedDisplayCached'));
|
||||
assert.ok(sources['satellites.js'].includes('gevDisplayPosition = _trackedDisplayCached'));
|
||||
assert.equal(sources['flights.js'].includes('_trackedEntity.label.text'), false);
|
||||
@@ -260,11 +261,11 @@ test('tracking layers write gevLabelModel and expose only their cached display p
|
||||
|
||||
test('civilian and military trail heads use the lower-centre model anchor and weak-texture tint', async () => {
|
||||
const files = await Promise.all(['flights.js', 'militaryFlights.js'].map(async (name) => (
|
||||
[name, await readFile(new URL(`./${name}`, import.meta.url), 'utf8')]
|
||||
[name, readLayerSource(new URL(`./${name}`, import.meta.url))]
|
||||
)));
|
||||
for (const [name, source] of files) {
|
||||
assert.ok(
|
||||
source.includes('const head = _trackedTrailCached() || _trackedDisplayPosition(_trackedIcao);'),
|
||||
(/const head = (?:parts\.motion\.)?_trackedTrailCached\(\) \|\| (?:parts\.motion\.)?_trackedDisplayPosition\((?:flightState\.)?_trackedIcao\);/).test(source),
|
||||
`${name} trail head uses the dedicated lower-centre model anchor`,
|
||||
);
|
||||
assert.ok(source.includes('const MODEL_COLOR_BLEND_AMOUNT = 0.94;'),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { readLayerSource } from '../testSupport/readLayerSource.mjs';
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
@@ -110,16 +111,16 @@ test('slow clean sprite clicks select, while long presses and orbit nudges canno
|
||||
|
||||
test('civilian and military click handlers apply duration only at the deselect branch', () => {
|
||||
const sources = [
|
||||
readFileSync(new URL('./flights.js', import.meta.url), 'utf8'),
|
||||
readFileSync(new URL('./militaryFlights.js', import.meta.url), 'utf8'),
|
||||
readLayerSource(new URL('./flights.js', import.meta.url)),
|
||||
readLayerSource(new URL('./militaryFlights.js', import.meta.url)),
|
||||
];
|
||||
for (const source of sources) {
|
||||
assert.match(source, /isTrackingSelectionGesture\(gesture\)[\s\S]+scene\.pick/);
|
||||
assert.match(source, /isTrackingClickGesture\(gesture\)[\s\S]+_clearTracking\([^)]*\{ origin: 'user' \}\)/);
|
||||
assert.match(source, /isTrackingClickGesture\(gesture\)[\s\S]+(?:parts\.\w+\.)?_clearTracking\([^)]*\{ origin: 'user' \}\)/);
|
||||
}
|
||||
assert.doesNotMatch(
|
||||
sources[0],
|
||||
/_trackedEntity = _viewer\.entities\.add\(\{\s*id:/,
|
||||
/(?:flightState\.)?_trackedEntity = (?:flightState\.)?_viewer\.entities\.add\(\{\s*id:/,
|
||||
'civilian tracked entities must retain Cesium-generated GUIDs',
|
||||
);
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user