diff --git a/scripts/qa-floorhold-mutations.mjs b/scripts/qa-floorhold-mutations.mjs index cfc97fee7..0e2ac9d62 100644 --- a/scripts/qa-floorhold-mutations.mjs +++ b/scripts/qa-floorhold-mutations.mjs @@ -94,7 +94,7 @@ const MUTATIONS = [ { defect: 'the held floor is stretched without bound (no drift limit)', edits: [ - { file: FLIGHTS, from: ' <= HELD_FLOOR_MAX_DRIFT_KM)) {', to: ' <= Infinity)) {' }, + { file: FLIGHTS, from: '<= HELD_FLOOR_MAX_DRIFT_KM', to: '<= Infinity' }, ], }, { @@ -102,8 +102,8 @@ const MUTATIONS = [ edits: [ { file: FLIGHTS, - from: ' if (next.easedM == null && wasHeld && Number.isFinite(stoodOnM)', - to: ' if (false && next.easedM == null && wasHeld && Number.isFinite(stoodOnM)', + from: 'next.easedM == null && wasHeld && Number.isFinite(stoodOnM)', + to: 'false && next.easedM == null && wasHeld && Number.isFinite(stoodOnM)', }, ], }, @@ -122,8 +122,8 @@ const MUTATIONS = [ edits: [ { file: FLIGHTS, - from: ' if (next.easedM == null && wasHeld && Number.isFinite(stoodOnM)', - to: ' if (next.easedM == null && Number.isFinite(stoodOnM)', + from: 'next.easedM == null && wasHeld && Number.isFinite(stoodOnM)', + to: 'next.easedM == null && Number.isFinite(stoodOnM)', }, ], }, @@ -159,8 +159,8 @@ const MUTATIONS = [ edits: [ { file: FLIGHTS, - from: ' if (next.easedM == null && wasHeld && Number.isFinite(stoodOnM)\n && Number.isFinite(effective) && effective < stoodOnM) {', - to: ' if (next.easedM == null && Number.isFinite(floor) && wasHeld && Number.isFinite(stoodOnM)\n && Number.isFinite(effective) && effective < stoodOnM) {', + from: 'next.easedM == null && wasHeld && Number.isFinite(stoodOnM)', + to: 'next.easedM == null && Number.isFinite(floor) && wasHeld && Number.isFinite(stoodOnM)', }, ], }, @@ -191,8 +191,8 @@ const MUTATIONS = [ edits: [ { file: FLIGHTS, - from: ' const closed = Math.min(FLOOR_EASE_MAX_STEP, 1 - Math.exp(-dtMs / FLOOR_EASE_TAU_MS));', - to: ' const closed = 1 - Math.exp(-dtMs / FLOOR_EASE_TAU_MS);', + from: 'FLOOR_EASE_MAX_STEP, 1 - Math.exp(-dtMs / FLOOR_EASE_TAU_MS),', + to: 'Infinity, 1 - Math.exp(-dtMs / FLOOR_EASE_TAU_MS),', }, ], }, @@ -213,8 +213,8 @@ const MUTATIONS = [ edits: [ { file: FLIGHTS, - from: ' return state.retiredMs != null && nowMs - state.retiredMs > FLOOR_SEED_GRACE_MS;', - to: ' return false;', + from: 'state.retiredMs != null && nowMs - state.retiredMs > FLOOR_SEED_GRACE_MS', + to: 'false', }, ], }, diff --git a/src/data/cockpitDetectionSubjects.test.mjs b/src/data/cockpitDetectionSubjects.test.mjs index d189d772e..dfe6baee9 100644 --- a/src/data/cockpitDetectionSubjects.test.mjs +++ b/src/data/cockpitDetectionSubjects.test.mjs @@ -109,11 +109,11 @@ test('Cockpit lifecycle publishes one normalized aircraft identity to both detec ['commercial', FLIGHTS_SOURCE], ['military', MILITARY_SOURCE], ]) { - const consumer = /function (?:parts\.\w+\.)?_applyCockpitState\(detail = \{\}\) \{[\s\S]*?\n\}/ + const consumer = /function\s*(?:parts\.\w+\.)?_applyCockpitState\(\s*detail\s*=\s*\{\},?\s*\)\s*\{[\s\S]*?\n {0,2}\}/ .exec(source)?.[0]; assert.ok(consumer, `${name} Cockpit consumer is defined`); assert.match(consumer, /detail\?\.subjectId/); - assert.match(consumer, /\.trim\(\)\.toLowerCase\(\)/); + assert.match(consumer, /\.trim\(\s*,?\s*\)\s*\.toLowerCase\(\s*,?\s*\)/); assert.doesNotMatch(consumer, /layerId/, `${name} must also suppress a duplicate subject originating in the sibling AIR feed`); } diff --git a/src/data/cockpitModels.test.mjs b/src/data/cockpitModels.test.mjs index 77cfb50b2..36f8b24d3 100644 --- a/src/data/cockpitModels.test.mjs +++ b/src/data/cockpitModels.test.mjs @@ -38,9 +38,9 @@ for (const layer of LAYERS) { }); test(`${layer.name}: Cockpit 3D obeys the shared Display toggle`, () => { - const regime = /function (?:parts\.\w+\.)?_modelRegimeActive\(\) \{[\s\S]*?\n\}/.exec(source)?.[0]; + const regime = /^([ \t]*)function _modelRegimeActive\b[\s\S]*?\n\1\}/m.exec(source)?.[0]; assert.ok(regime, '_modelRegimeActive is defined'); - assert.match(regime, /if \(!(?:flightState\.)?_models3dEnabled\) return false;/, + assert.match(regime, /if\s*\(\s*!(?:flightState\.)?_models3dEnabled,?\s*\)\s*return\s*false;/, 'OFF must keep Cockpit AIR contacts in 2D'); assert.doesNotMatch(regime, /!(?:flightState\.)?_models3dEnabled\s*&&\s*!(?:flightState\.)?_cockpitContactMode/, 'Cockpit must not bypass the owner-visible Display toggle'); @@ -52,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 (?:parts\.\w+\.)?_trackedModelRegimeActive\(\) \{[\s\S]*?\n\}/.exec(source)?.[0]; + const regime = /^([ \t]*)function _trackedModelRegimeActive\b[\s\S]*?\n\1\}/m.exec(source)?.[0]; assert.ok(regime, '_trackedModelRegimeActive is defined'); - assert.match(regime, /if \(!(?:flightState\.)?_trackedIcao \|\| (?:flightState\.)?_cockpitContactMode \|\|[\s\S]*?return false;/, + assert.match(regime, /if\s*\(\s*!(?:flightState\.)?_trackedIcao\s*\|\|\s*(?:flightState\.)?_cockpitContactMode\s*\|\|[\s\S]*?return\s*false;/, '_trackedModelRegimeActive excludes cockpit'); - const tracked = /function (?:parts\.\w+\.)?_updateTrackedModel\(\)[\s\S]*?\n if \(!active\)/.exec(source)?.[0]; + const tracked = /^([ \t]*)function _updateTrackedModel\b[\s\S]*?\n\1\}/m.exec(source)?.[0]; assert.ok(tracked, '_updateTrackedModel is defined'); - assert.match(tracked, /(?:parts\.\w+\.)?_trackedModelRegimeActive\(\)/, + assert.match(tracked, /(?:parts\.\w+\.)?_trackedModelRegimeActive\(\s*,?\s*\)/, 'the tracked-model driver uses the cockpit-aware predicate'); }); @@ -69,15 +69,15 @@ 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 (?: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/); + const add = /^([ \t]*)function _modelAddDistM\b[\s\S]*?\n\1\}/m.exec(source)?.[0]; + const keep = /^([ \t]*)function _modelKeepDistM\b[\s\S]*?\n\1\}/m.exec(source)?.[0]; + assert.match(add, /(?:flightState\.)?_models3dMode\s*===\s*'all'\s*\?\s*MODEL_ALL_ADD_M\s*:\s*MODEL_PROX_ADD_M/); + assert.match(keep, /(?:flightState\.)?_models3dMode\s*===\s*'all'\s*\?\s*MODEL_ALL_KEEP_M\s*:\s*MODEL_PROX_KEEP_M/); assert.doesNotMatch(add, /COCKPIT_MODEL_ADD_M/); assert.doesNotMatch(keep, /COCKPIT_MODEL_KEEP_M/); - const cap = /function (?:parts\.\w+\.)?_modelCap\(\) \{[\s\S]*?\n\}/.exec(source)?.[0]; - assert.match(cap, /Math\.min\(COCKPIT_MODEL_MAX/, + const cap = /^([ \t]*)function _modelCap\b[\s\S]*?\n\1\}/m.exec(source)?.[0]; + assert.match(cap, /Math\.min\(\s*COCKPIT_MODEL_MAX/, 'Cockpit keeps its 60-model performance ceiling'); }); @@ -89,19 +89,19 @@ for (const layer of LAYERS) { // `_iconKind` is identity for every unconverted contact (see // tr3bRegistry.test.mjs) — it only swaps the glyph for a contact the // operator explicitly converted into a TR-3B. - assert.match(source, /bb\.image = aircraftIcon\(_iconKind\(icao24, meta\?\.klass\)(, bb\._gevIconLarge \? TRACKED_ICON_PX : undefined)?\)/, + assert.match(source, /bb\.image\s*=\s*aircraftIcon\(\s*_iconKind\(\s*icao24,\s*meta\?\.klass,?\s*\)(,\s*bb\._gevIconLarge\s*\?\s*TRACKED_ICON_PX\s*:\s*undefined)?,?\s*\)/, 'near contacts and model fallbacks retain the class-derived aircraft silhouette'); - assert.match(source, /bb\.rotation = 0;/, + assert.match(source, /bb\.rotation\s*=\s*0;/, 'far dots are reset to a rotation-free presentation'); - assert.match(source, /\(!(?:flightState\.)?_cockpitContactMode \|\| isCockpitNear\) && \(doRotations \|\| revealed\)/, + assert.match(source, /\(\s*!(?:flightState\.)?_cockpitContactMode\s*\|\|\s*isCockpitNear,?\s*\)\s*&&\s*\(\s*doRotations\s*\|\|\s*revealed,?\s*\)/, 'near 2D silhouettes continue to receive projected course'); - assert.match(source, /if \(bb\.show\) bb\.show = false; \/\/ hand off ONLY once the model renders/, + assert.match(source, /if\s*\(\s*bb\.show,?\s*\)\s*bb\.show\s*=\s*false;\s*\/\/\s*hand\s*off\s*ONLY\s*once\s*the\s*model\s*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 (?: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\);/); + const setMode = /^([ \t]*)function _setCockpitContactMode\b[\s\S]*?\n\1\}/m.exec(source)?.[0]; + assert.match(setMode, /else\s*(?:flightState\.)?_cockpitNearContacts\s*=\s*new\s*Set\(\s*,?\s*\);/); + assert.match(setMode, /for\s*\(\s*const\s*\[icao24,\s*bb\]\s*of\s*(?:flightState\.)?_billboards,?\s*\)\s*(?:parts\.\w+\.)?_applyFleetBillboardPresentation\(\s*icao24,\s*bb,?\s*\);/); }); } diff --git a/src/data/detectionRenderDemand.test.mjs b/src/data/detectionRenderDemand.test.mjs index 3b44603b9..56a1c7dcf 100644 --- a/src/data/detectionRenderDemand.test.mjs +++ b/src/data/detectionRenderDemand.test.mjs @@ -429,7 +429,7 @@ test('the render-governor gate covers the parked case, with teeth on the painter test('aircraft brackets stay prompt because the aircraft layers hold the render loop', async () => { for (const file of ['./flights.js', './militaryFlights.js']) { const source = readLayerSource(new URL(file, import.meta.url)); - const enable = /\n enable\([\s\S]*?\n \},/.exec(source)?.[0]; + const enable = /\n([ \t]*)enable\([\s\S]*?\n\1\},/.exec(source)?.[0]; assert.ok(enable, `${file}: enable() is still identifiable`); assert.match( enable, diff --git a/src/data/militaryAwareness.test.mjs b/src/data/militaryAwareness.test.mjs index 6694fcc94..120a8dd74 100644 --- a/src/data/militaryAwareness.test.mjs +++ b/src/data/militaryAwareness.test.mjs @@ -1354,11 +1354,11 @@ test('hasContact declines while a layer is disabled, whatever its maps still hol // alone would report a preserved subject as FRESH from hidden stale data. for (const [name, source, guard] of [ ['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;/], + /hasContact\(\s*icao24,?\s*\)\s*\{\s*\n\s*if\s*\(\s*!(?:flightState\.)?_billboardCollection\s*\|\|\s*!(?:flightState\.)?_billboardCollection\.show\s*\|\|\s*(?:flightState\.)?_billboards\.size\s*===\s*0,?\s*\)\s*return\s*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;/], + /hasContact\(\s*icao24,?\s*\)\s*\{\s*\n\s*if\s*\(\s*!(?:flightState\.)?_billboardCollection\s*\|\|\s*!(?:flightState\.)?_billboardCollection\.show\s*\|\|\s*(?:flightState\.)?_billboards\.size\s*===\s*0,?\s*\)\s*return\s*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;/], + /hasContact\(\s*mmsi,?\s*\)\s*\{\s*\n\s*if\s*\(\s*!state\.enabled\s*\|\|\s*!state\.vesselMap\s*\|\|\s*state\.vesselMap\.size\s*===\s*0,?\s*\)\s*return\s*null;/], ]) { assert.match(source, guard, `${name}.hasContact must decline while the layer is disabled`); } @@ -1535,7 +1535,7 @@ test('production eviction sites actually tag their clears', () => { for (const [name, source] of [['flights', flightsSource], ['militaryFlights', militarySource]]) { assert.match( source, - /if \(icao24 === (?:flightState\.)?_trackedIcao\) \{\s*\n\s*(?:parts\.\w+\.)?_clearTracking\(false, \{ evicted: true \}\);/, + /if\s*\(\s*icao24\s*===\s*(?:flightState\.)?_trackedIcao,?\s*\)\s*\{\s*\n\s*(?:parts\.\w+\.)?_clearTracking\(\s*false,\s*\{\s*evicted:\s*true\s*\},?\s*\);/, `${name} must mark its aged-out cull as an eviction`, ); assert.match( @@ -1589,9 +1589,9 @@ test('cockpit blocks only non-aircraft Context camera flights', () => { }); test('vessel entry and selection framing both use the 3 km focus radius', () => { - assert.match(militaryAwarenessSource, /const VESSEL_FOCUS_RADIUS_M = 3000;/); + assert.match(militaryAwarenessSource, /const\s*VESSEL_FOCUS_RADIUS_M\s*=\s*3000;/); const focusRadiusUses = militaryAwarenessSource.match( - /new Cesium\.BoundingSphere\(vessel\.position, VESSEL_FOCUS_RADIUS_M\)/g, + /new\s*Cesium\.BoundingSphere\(\s*vessel\.position,\s*VESSEL_FOCUS_RADIUS_M,?\s*\)/g, ) || []; assert.equal(focusRadiusUses.length, 2); }); diff --git a/src/data/tr3bRegistry.test.mjs b/src/data/tr3bRegistry.test.mjs index 3166b0216..484768337 100644 --- a/src/data/tr3bRegistry.test.mjs +++ b/src/data/tr3bRegistry.test.mjs @@ -238,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 \(!(?:flightState\.)?_trackedIcao \|\| (?:flightState\.)?_cockpitContactMode \|\| isTr3b\((?:flightState\.)?_trackedIcao\)\) \{/, + assert.match(source, /if\s*\(\s*!(?:flightState\.)?_trackedIcao\s*\|\|\s*(?:flightState\.)?_cockpitContactMode\s*\|\|\s*isTr3b\(\s*(?:flightState\.)?_trackedIcao,?\s*\),?\s*\)\s*\{/, `${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 !== (?:flightState\.)?_trackedIcao\) bb\.show = true;|if \(modelled && id !== (?:flightState\.)?_trackedIcao\) modelled\.show = true;/, + assert.match(source, /if\s*\(\s*bb\s*&&\s*id\s*!==\s*(?:flightState\.)?_trackedIcao,?\s*\)\s*bb\.show\s*=\s*true;|if\s*\(\s*modelled\s*&&\s*id\s*!==\s*(?:flightState\.)?_trackedIcao,?\s*\)\s*modelled\.show\s*=\s*true;/, `${name}: converting restores the billboard the model handoff had hidden`); // 3. Every aircraftIcon() CALL SITE routes through the kind resolver, so no @@ -254,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*(?:parts\.rendering\.)?_iconKind\(/, + assert.match(call, /aircraftIcon\(\s*\s*(?:parts\.rendering\.)?_iconKind\(\s*/, `${name}: ${call.replace(/\s+/g, ' ')} must resolve its sprite kind through _iconKind`); } @@ -410,7 +410,7 @@ test('a converted contact never consumes a 3D model CAP SLOT', async () => { 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 (?:flightState\.)?_billboards\)[\s\S]*?cand\.push\(/.exec(source)?.[0]; + const loop = /const\s*cand\s*=\s*\[\];\s*\n\s*for\s*\(\s*const\s*\[icao,\s*bb\]\s*of\s*(?:flightState\.)?_billboards,?\s*\)[\s\S]*?cand\.push\(\s*/.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;/, diff --git a/src/data/trackedModelRegime.test.mjs b/src/data/trackedModelRegime.test.mjs index 9789271f0..1b02df1d5 100644 --- a/src/data/trackedModelRegime.test.mjs +++ b/src/data/trackedModelRegime.test.mjs @@ -933,14 +933,14 @@ 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 = readLayerSource(new URL(`./${name}`, import.meta.url)); - assert.match(source, /!(?:flightState\.)?_trackedModel && !(?:flightState\.)?_trackedModelLoading && (?:parts\.\w+\.)?_trackedModelLoadAllowed\(\)/, + assert.match(source, /!(?:flightState\.)?_trackedModel\s*&&\s*!(?:flightState\.)?_trackedModelLoading\s*&&\s*(?:parts\.\w+\.)?_trackedModelLoadAllowed\(\s*,?\s*\)/, `${name}: the driver asks permission before starting another tracked-model load`); - assert.match(source, /(?:parts\.\w+\.)?_noteTrackedModelLoadFailure\(trackedSpec\.url, err\)/, + assert.match(source, /(?:parts\.\w+\.)?_noteTrackedModelLoadFailure\(\s*trackedSpec\.url,\s*err,?\s*\)/, `${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, /(?:parts\.\w+\.)?_releaseTrackedModel\(\);\n (?:parts\.\w+\.)?_resetTrackedSelectionState\(\);/, + assert.match(source, /(?:parts\.\w+\.)?_releaseTrackedModel\(\s*,?\s*\);\n\s*(?:parts\.\w+\.)?_resetTrackedSelectionState\(\s*,?\s*\);/, `${name}: deselect clears the per-selection latches in the production path`); - assert.match(source, /(?:flightState\.)?_trackedIcao = icao24;\n (?:parts\.\w+\.)?_resetTrackedSelectionState\(\);/, + assert.match(source, /(?:flightState\.)?_trackedIcao\s*=\s*icao24;\n\s*(?:parts\.\w+\.)?_resetTrackedSelectionState\(\s*,?\s*\);/, `${name}: selecting a contact starts from a clean per-selection state`); } }); @@ -949,15 +949,15 @@ 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 = readLayerSource(new URL(`./${name}`, import.meta.url)); - const regime = /function (?:parts\.\w+\.)?_trackedModelRegimeActive\(\) \{[\s\S]*?\n\}/.exec(source)?.[0]; + const regime = /^([ \t]*)function _trackedModelRegimeActive\b[\s\S]*?\n\1\}/m.exec(source)?.[0]; assert.ok(regime, `${name}: _trackedModelRegimeActive is defined`); - assert.doesNotMatch(regime, /(?:flightState\.)?_models3dEnabled|(?:parts\.\w+\.)?_modelRegimeActive\(\)/, + assert.doesNotMatch(regime, /(?:flightState\.)?_models3dEnabled|(?:parts\.\w+\.)?_modelRegimeActive\(\s*,?\s*\)/, `${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 (?:parts\.\w+\.)?_modelRegimeActive\(\) \{[\s\S]*?\n\}/.exec(source)?.[0]; - assert.match(fleet, /if \(!(?:flightState\.)?_models3dEnabled\) return false;/, + const fleet = /^([ \t]*)function _modelRegimeActive\b[\s\S]*?\n\1\}/m.exec(source)?.[0]; + assert.match(fleet, /if\s*\(\s*!(?:flightState\.)?_models3dEnabled,?\s*\)\s*return\s*false;/, `${name}: the fleet regime still obeys the DISPLAY-rail 3D toggle`); } }); diff --git a/src/data/trackedReadout.test.mjs b/src/data/trackedReadout.test.mjs index a7c1f6df2..d83b9df56 100644 --- a/src/data/trackedReadout.test.mjs +++ b/src/data/trackedReadout.test.mjs @@ -251,7 +251,7 @@ test('tracking layers write gevLabelModel and expose only their cached display p assert.ok(source.includes('.gevLabelModel ='), `${name} writes the explicit model directly`); assert.ok(source.includes('.gevDisplayPosition ='), `${name} exposes a display-position cache`); } - assert.match(sources['flights.js'], /gevDisplayPosition = parts\.motion\._trackedDisplayCached/); + assert.match(sources['flights.js'], /gevDisplayPosition\s*=\s*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); @@ -265,7 +265,7 @@ test('civilian and military trail heads use the lower-centre model anchor and we ))); for (const [name, source] of files) { assert.ok( - (/const head = (?:parts\.motion\.)?_trackedTrailCached\(\) \|\| (?:parts\.motion\.)?_trackedDisplayPosition\((?:flightState\.)?_trackedIcao\);/).test(source), + (/const\s*head\s*=\s*(?:parts\.motion\.)?_trackedTrailCached\(\s*,?\s*\)\s*\|\|\s*(?:parts\.motion\.)?_trackedDisplayPosition\(\s*(?:flightState\.)?_trackedIcao,?\s*\);/).test(source), `${name} trail head uses the dedicated lower-centre model anchor`, ); assert.ok(source.includes('const MODEL_COLOR_BLEND_AMOUNT = 0.94;'),