i18n: fix the repeat-review findings

- Status pieces translate in one place (src/ui/statusText.js): a Local
  ADS-B error with a single piece now translates, and the analyst card
  splits empty-layer notes into pieces (Transit, Local ADS-B).
- Translate the ALPR retry chip text, the ECCC error on the Air quality
  card, "Upstream response too large" and the "entry {n}" feed label.
- The unmarked-text check also sees error/loadingLabel/statusMessage/
  status assignments, `status:` properties and showToast?.( /
  this._showToast( calls; the scene import preview marks its pack
  statuses, data and model-facing text carry i18n-ignore with a reason.
- Tests check the real code: the HUD locality formatter moves to
  src/hudLocalityFormat.js, the unsaved-keys test pins the teardown.
- One copy each: city names come from src/cityPois.js, the GNSS HTTP
  template and wind "field unavailable" texts; dead fallbacks removed.
- Leftovers of the reverted vessel-label change and the reformatting of
  detectionHost.test.mjs / keySetup.test.mjs are back to main.

Catalogs: es/ru 2617 messages each, complete.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
German KhokhlovandClaude Opus 5.5 committed 2026-10-16 19:28:59 +04:00
1 parent a2463ca2d2
commit 3157888780
60 files changed
+1577 -1606

No files matched your search

+4
View File
@@ -249,6 +249,7 @@ export function createAisWatchdog(options = {}) {
if (!env.hasKey) {
const actions = terminateOwned('key-absent');
status = 'missing-key';
// i18n-ignore: server detail; the chip shows a translated reason (vessels/queries.js)
error = 'AISSTREAM_API_KEY is not set';
reconnectAttempt = 0;
keyFingerprint = null;
@@ -257,6 +258,7 @@ export function createAisWatchdog(options = {}) {
if (env.hasTransport === false) {
const actions = terminateOwned('no-transport');
status = 'unsupported';
// i18n-ignore: server detail; the chip shows a translated reason (vessels/queries.js)
error = 'Node WebSocket transport is unavailable';
return actions;
}
@@ -329,6 +331,7 @@ export function createAisWatchdog(options = {}) {
if (!silenceWatchArmed) return [];
const silentFor = monoNow - silenceSinceMono;
if (silentFor >= recycleAfterMs) {
// i18n-ignore: server detail; the chip shows a translated reason (vessels/queries.js)
error = `AISStream delivered no data for ${Math.round(silentFor / 1000)}s`;
const actions = terminateOwned('silent');
scheduleRetry('transport');
@@ -401,6 +404,7 @@ export function createAisWatchdog(options = {}) {
function onClose(eventGeneration) {
if (!ownsGeneration(eventGeneration)) return [];
release();
// i18n-ignore: server detail; the chip shows a translated reason (vessels/queries.js)
if (!error) error = 'AISStream websocket closed';
scheduleRetry('transport');
return [];
+154 -431
View File
@@ -27,25 +27,17 @@ import { DETECTION_THEME_MAP } from '../overlays/worldOverlayTokens.js';
import { composeLabel, resolveTier } from './detectionDraw.js';
test('detection diagnostics count rendered fading rows instead of absent selected identities', () => {
assert.equal(
countFadingRenderEntries([
{ selected: true },
{ selected: false },
{ selected: true },
{ selected: false },
]),
2,
);
assert.equal(
countFadingRenderEntries([{ selected: true }, { selected: true }]),
0,
);
assert.equal(countFadingRenderEntries([
{ selected: true },
{ selected: false },
{ selected: true },
{ selected: false },
]), 2);
assert.equal(countFadingRenderEntries([{ selected: true }, { selected: true }]), 0);
});
class MockEvent {
constructor() {
this.listeners = new Set();
}
constructor() { this.listeners = new Set(); }
addEventListener(listener) {
this.listeners.add(listener);
@@ -77,127 +69,62 @@ function mockContext(target, trace) {
return {
calls,
font: '',
get filter() {
return filter;
},
set filter(value) {
filter = value;
record('filter', value);
},
get filter() { return filter; },
set filter(value) { filter = value; record('filter', value); },
fillStyle: '',
get strokeStyle() {
return strokeStyle;
},
set strokeStyle(value) {
strokeStyle = value;
record('strokeStyle', value);
},
get strokeStyle() { return strokeStyle; },
set strokeStyle(value) { strokeStyle = value; record('strokeStyle', value); },
globalAlpha: 1,
get globalCompositeOperation() {
return globalCompositeOperation;
},
set globalCompositeOperation(value) {
globalCompositeOperation = value;
record('globalCompositeOperation', value);
},
get globalCompositeOperation() { return globalCompositeOperation; },
set globalCompositeOperation(value) { globalCompositeOperation = value; record('globalCompositeOperation', value); },
lineWidth: 1,
measureText(text) {
return { width: String(text).length * 6 };
},
setTransform(...args) {
record('setTransform', ...args);
},
clearRect(...args) {
record('clearRect', ...args);
},
save() {
record('save');
},
restore() {
record('restore');
},
translate(...args) {
record('translate', ...args);
},
scale(...args) {
record('scale', ...args);
},
beginPath() {
record('beginPath');
},
rect(...args) {
record('rect', ...args);
},
clip(...args) {
record('clip', ...args);
},
moveTo(...args) {
record('moveTo', ...args);
},
lineTo(...args) {
record('lineTo', ...args);
},
arc(...args) {
record('arc', ...args);
},
arcTo(...args) {
record('arcTo', ...args);
},
closePath() {
record('closePath');
},
measureText(text) { return { width: String(text).length * 6 }; },
setTransform(...args) { record('setTransform', ...args); },
clearRect(...args) { record('clearRect', ...args); },
save() { record('save'); },
restore() { record('restore'); },
translate(...args) { record('translate', ...args); },
scale(...args) { record('scale', ...args); },
beginPath() { record('beginPath'); },
rect(...args) { record('rect', ...args); },
clip(...args) { record('clip', ...args); },
moveTo(...args) { record('moveTo', ...args); },
lineTo(...args) { record('lineTo', ...args); },
arc(...args) { record('arc', ...args); },
arcTo(...args) { record('arcTo', ...args); },
closePath() { record('closePath'); },
// The style is recorded AT fill time, not on assignment, so a pin can prove
// which plate token actually reached the canvas rather than which one was
// set at some point during the frame. globalAlpha rides along for the same
// reason: the backdrop feather is an alpha, not a colour.
fill(path) {
record('fill', path, this.fillStyle, this.globalAlpha);
},
stroke(path) {
record('stroke', path, this.strokeStyle, this.lineWidth);
},
fillRect(...args) {
record('fillRect', ...args);
},
fillText(...args) {
record('fillText', ...args);
},
drawImage(...args) {
record('drawImage', ...args);
},
fill(path) { record('fill', path, this.fillStyle, this.globalAlpha); },
stroke(path) { record('stroke', path, this.strokeStyle, this.lineWidth); },
fillRect(...args) { record('fillRect', ...args); },
fillText(...args) { record('fillText', ...args); },
drawImage(...args) { record('drawImage', ...args); },
};
}
// `search` seeds window.location.search. The detection mode banner is developer
// telemetry gated behind ?detectDebug=1, so any test that uses the banner as its
// "did this frame repaint" probe must opt in explicitly.
function installEnvironment({
width = 800,
height = 600,
dpr = 2,
search = '',
} = {}) {
function installEnvironment({ width = 800, height = 600, dpr = 2, search = '' } = {}) {
const byId = new Map();
const paintTrace = [];
const ctx = mockContext('shared', paintTrace);
const detectionCtx = mockContext('detection', paintTrace);
const originalPerformance = Object.getOwnPropertyDescriptor(
globalThis,
'performance',
);
const originalPerformance = Object.getOwnPropertyDescriptor(globalThis, 'performance');
const originalDateNow = Date.now;
const originalPath2D = globalThis.Path2D;
let currentTime = 1_000;
let performanceStep = 0;
Object.defineProperty(globalThis, 'performance', {
configurable: true,
value: {
now: () => {
const value = currentTime;
currentTime += performanceStep;
return value;
},
},
value: { now: () => {
const value = currentTime;
currentTime += performanceStep;
return value;
} },
});
Date.now = () => currentTime;
globalThis.Path2D = MockPath2D;
@@ -240,9 +167,7 @@ function installEnvironment({
register(this);
}
getBoundingClientRect() {
return this._rect;
}
getBoundingClientRect() { return this._rect; }
getContext() {
if (this.tagName !== 'CANVAS') return null;
return this.id === 'world-overlay-detection-surface' ? detectionCtx : ctx;
@@ -255,17 +180,13 @@ function installEnvironment({
remove() {
if (this.parentElement) {
this.parentElement.children = this.parentElement.children.filter(
(child) => child !== this,
);
this.parentElement.children = this.parentElement.children.filter((child) => child !== this);
}
unregister(this);
this.parentElement = null;
}
get nextSibling() {
return null;
}
get nextSibling() { return null; }
}
function register(element) {
@@ -279,26 +200,14 @@ function installEnvironment({
}
const body = new MockElement('body');
body.classList = {
contains() {
return false;
},
};
body.classList = { contains() { return false; } };
const document = {
body,
createElement(tagName) {
return new MockElement(tagName);
},
getElementById(id) {
return byId.get(id) || null;
},
querySelector(selector) {
return byId.get(selector.slice(1)) || null;
},
createElement(tagName) { return new MockElement(tagName); },
getElementById(id) { return byId.get(id) || null; },
querySelector(selector) { return byId.get(selector.slice(1)) || null; },
querySelectorAll(selector) {
const element = selector.startsWith('#')
? byId.get(selector.slice(1))
: null;
const element = selector.startsWith('#') ? byId.get(selector.slice(1)) : null;
return element ? [element] : [];
},
};
@@ -307,18 +216,10 @@ function installEnvironment({
location: { search },
addEventListener() {},
removeEventListener() {},
getComputedStyle() {
return { display: 'block', visibility: 'visible', opacity: '1' };
},
};
globalThis.ResizeObserver = class {
observe() {}
disconnect() {}
};
globalThis.MutationObserver = class {
observe() {}
disconnect() {}
getComputedStyle() { return { display: 'block', visibility: 'visible', opacity: '1' }; },
};
globalThis.ResizeObserver = class { observe() {} disconnect() {} };
globalThis.MutationObserver = class { observe() {} disconnect() {} };
globalThis.document = document;
globalThis.window = window;
@@ -340,9 +241,7 @@ function installEnvironment({
positionWC: new Cesium.Cartesian3(0, 0, 10_000_000),
positionCartographic: { height: 1_000_000 },
viewMatrix: Cesium.Matrix4.clone(Cesium.Matrix4.IDENTITY),
frustum: {
projectionMatrix: Cesium.Matrix4.clone(Cesium.Matrix4.IDENTITY),
},
frustum: { projectionMatrix: Cesium.Matrix4.clone(Cesium.Matrix4.IDENTITY) },
moveEnd: new MockEvent(),
},
scene: { postRender, requestRender() {} },
@@ -355,12 +254,8 @@ function installEnvironment({
ctx,
detectionCtx,
paintTrace,
advance(ms) {
currentTime += ms;
},
setPerformanceStep(ms) {
performanceStep = ms;
},
advance(ms) { currentTime += ms; },
setPerformanceStep(ms) { performanceStep = ms; },
cleanup() {
destroyDetection();
destroyWorldOverlay();
@@ -371,8 +266,7 @@ function installEnvironment({
delete globalThis.window;
delete globalThis.ResizeObserver;
delete globalThis.MutationObserver;
if (originalPerformance)
Object.defineProperty(globalThis, 'performance', originalPerformance);
if (originalPerformance) Object.defineProperty(globalThis, 'performance', originalPerformance);
else delete globalThis.performance;
},
};
@@ -401,16 +295,14 @@ function militaryLayer() {
return {
id: 'military',
getDetectableObjects() {
return [
{
position: new Cesium.Cartesian3(0, 0, 6_356_752),
sourceId: 'military-pin',
id: 'MIL-PIN',
metric: 'FL450',
type: 'AIR',
tier: 'military',
},
];
return [{
position: new Cesium.Cartesian3(0, 0, 6_356_752),
sourceId: 'military-pin',
id: 'MIL-PIN',
metric: 'FL450',
type: 'AIR',
tier: 'military',
}];
},
};
}
@@ -466,9 +358,7 @@ test('detection lifecycle re-hosts unchanged painters behind the sole host liste
assert.equal(env.postRender.listeners.size, 1);
assert.equal(env.document.getElementById('detection-overlay'), null);
assert.ok(env.document.getElementById('world-overlay-canvas'));
const surface = env.document.getElementById(
'world-overlay-detection-surface',
);
const surface = env.document.getElementById('world-overlay-detection-surface');
const root = env.document.getElementById('world-overlay-root');
const mainCanvas = env.document.getElementById('world-overlay-canvas');
assert.ok(surface);
@@ -491,36 +381,19 @@ test('detection lifecycle re-hosts unchanged painters behind the sole host liste
assert.equal(first.profile, 'DENSE');
assert.ok(Array.isArray(first.calloutRects));
if (first.calloutRects.length) {
const x = first.calloutRects[0].x;
first.calloutRects[0].x = NaN;
assert.equal(
getDetectionDiagnostics().calloutRects[0].x,
x,
'QA owns a copy, never a live plate',
);
const x=first.calloutRects[0].x;
first.calloutRects[0].x=NaN;
assert.equal(getDetectionDiagnostics().calloutRects[0].x,x,'QA owns a copy, never a live plate');
}
assert.equal(first.observationCount, 2);
assert.equal(first.didSolve, true);
assert.ok(first.solveRevision > 0);
assert.ok(first.collectiveLabelBudget > 0);
assert.ok(
first.bracketOpacityCounts.full + first.bracketOpacityCounts.partial > 0,
);
assert.ok(
env.detectionCtx.calls.some(
([name, text]) =>
name === 'fillText' && String(text).startsWith('DENSE VIS:'),
),
);
assert.ok(
env.detectionCtx.calls.some(
([name, path]) => name === 'stroke' && path instanceof MockPath2D,
),
);
assert.ok(
env.detectionCtx.calls.some(([name]) => name === 'fillRect'),
'scanlines and banner still paint',
);
assert.ok(first.bracketOpacityCounts.full + first.bracketOpacityCounts.partial > 0);
assert.ok(env.detectionCtx.calls.some(([name, text]) => name === 'fillText'
&& String(text).startsWith('DENSE VIS:')));
assert.ok(env.detectionCtx.calls.some(([name, path]) => name === 'stroke' && path instanceof MockPath2D));
assert.ok(env.detectionCtx.calls.some(([name]) => name === 'fillRect'), 'scanlines and banner still paint');
assert.equal(env.detectionCtx.globalCompositeOperation, 'source-over');
assert.equal(env.detectionCtx.filter, 'none');
assert.equal(surface.style.display, 'block');
@@ -536,16 +409,8 @@ test('detection lifecycle re-hosts unchanged painters behind the sole host liste
// screen-blended sensor surface: `screen` can only lighten, so a callout's
// dark backing plate is a no-op over sunlit ground and the text dissolves
// into it. Brackets, banner and scanlines stay on the sensor surface.
assert.ok(
env.ctx.calls.some(
([name, text]) => name === 'fillText' && text === 'TEST0',
),
);
assert.ok(
!env.detectionCtx.calls.some(
([name, text]) => name === 'fillText' && text === 'TEST0',
),
);
assert.ok(env.ctx.calls.some(([name, text]) => name === 'fillText' && text === 'TEST0'));
assert.ok(!env.detectionCtx.calls.some(([name, text]) => name === 'fillText' && text === 'TEST0'));
env.advance(1);
env.postRender.raise();
assert.ok(getDetectionDiagnostics().solveRevision > first.solveRevision);
@@ -555,10 +420,7 @@ test('detection lifecycle re-hosts unchanged painters behind the sole host liste
assert.equal(getMode(), 'SPARSE');
assert.equal(getDetectionDiagnostics().profile, 'SPARSE');
assert.equal(getDetectionDiagnostics().allocationStrategy, 'WEIGHTED');
assert.ok(
env.detectionCtx.calls.some(([name]) => name === 'arc'),
'sparse focus ring remains available',
);
assert.ok(env.detectionCtx.calls.some(([name]) => name === 'arc'), 'sparse focus ring remains available');
setMode('BALANCED');
env.postRender.raise();
@@ -567,12 +429,9 @@ test('detection lifecycle re-hosts unchanged painters behind the sole host liste
env.postRender.raise();
assert.equal(getDetectionDiagnostics().profile, 'DENSE');
const bannerCount = () =>
env.detectionCtx.calls.filter(
([name, text]) =>
name === 'fillText' &&
/^(SPARSE|BALANCED|DENSE) VIS:/.test(String(text)),
).length;
const bannerCount = () => env.detectionCtx.calls.filter(([name, text]) => (
name === 'fillText' && /^(SPARSE|BALANCED|DENSE) VIS:/.test(String(text))
)).length;
const beforeSuspend = bannerCount();
suspendDetection('intercity');
assert.equal(isDetectionSuspended(), true);
@@ -589,12 +448,9 @@ test('detection lifecycle re-hosts unchanged painters behind the sole host liste
// These are the exact engine calls made by military style presets after
// their production UI gate chooses CRT/NVG/FLIR defaults.
const expectedThemes = {
retro:
'contrast(1.08) saturate(1.04) drop-shadow(0 0 3px rgba(255, 176, 56, 0.45))',
surveillance:
'contrast(1.12) saturate(1.12) drop-shadow(0 0 3px rgba(120, 255, 120, 0.42))',
thermal:
'contrast(1.1) saturate(1.08) drop-shadow(0 0 3px rgba(255, 224, 170, 0.42))',
retro: 'contrast(1.08) saturate(1.04) drop-shadow(0 0 3px rgba(255, 176, 56, 0.45))',
surveillance: 'contrast(1.12) saturate(1.12) drop-shadow(0 0 3px rgba(120, 255, 120, 0.42))',
thermal: 'contrast(1.1) saturate(1.08) drop-shadow(0 0 3px rgba(255, 224, 170, 0.42))',
};
for (const style of ['retro', 'surveillance', 'thermal']) {
setMode('OFF');
@@ -620,28 +476,17 @@ test('detection lifecycle re-hosts unchanged painters behind the sole host liste
assert.equal(getMode(), 'OFF');
assert.equal(surface.style.display, 'none');
assert.equal(env.postRender.listeners.size, 1);
assert.ok(
modes.includes('SPARSE') &&
modes.includes('BALANCED') &&
modes.includes('DENSE'),
);
assert.ok(modes.includes('SPARSE') && modes.includes('BALANCED') && modes.includes('DENSE'));
destroyDetection();
assert.equal(
env.postRender.listeners.size,
1,
'detection never owns the listener',
);
assert.equal(env.postRender.listeners.size, 1, 'detection never owns the listener');
setMode('DENSE');
env.postRender.raise();
assert.equal(env.document.getElementById('detection-overlay'), null);
destroyWorldOverlay();
assert.equal(env.postRender.listeners.size, 0);
assert.equal(env.document.getElementById('world-overlay-canvas'), null);
assert.equal(
env.document.getElementById('world-overlay-detection-surface'),
null,
);
assert.equal(env.document.getElementById('world-overlay-detection-surface'), null);
} finally {
env.cleanup();
}
@@ -654,22 +499,16 @@ test('callouts stop painting the moment the last detectable object goes away', (
// clear the replay buffer, or the final callsigns stay stranded on the
// shared canvas after the last data layer is switched off.
const env = installEnvironment();
let objects = [
{
position: new Cesium.Cartesian3(0, 0, 6_356_752),
sourceId: 'lonely-1',
id: 'LASTONE',
metric: 'FL120',
type: 'AIR',
},
];
let objects = [{
position: new Cesium.Cartesian3(0, 0, 6_356_752),
sourceId: 'lonely-1',
id: 'LASTONE',
metric: 'FL120',
type: 'AIR',
}];
try {
initWorldOverlay(env.viewer);
initDetection(
env.viewer,
[{ id: 'flights', getDetectableObjects: () => objects }],
() => {},
);
initDetection(env.viewer, [{ id: 'flights', getDetectableObjects: () => objects }], () => {});
setMode('DENSE');
env.advance(250);
env.postRender.raise();
@@ -678,9 +517,7 @@ test('callouts stop painting the moment the last detectable object goes away', (
env.advance(250);
env.postRender.raise();
assert.ok(
env.ctx.calls.some(
([name, text]) => name === 'fillText' && text === 'LASTONE',
),
env.ctx.calls.some(([name, text]) => name === 'fillText' && text === 'LASTONE'),
'the callout paints on the shared canvas while the contact exists',
);
@@ -691,9 +528,7 @@ test('callouts stop painting the moment the last detectable object goes away', (
env.advance(250);
env.postRender.raise();
assert.ok(
!env.ctx.calls.some(
([name, text]) => name === 'fillText' && text === 'LASTONE',
),
!env.ctx.calls.some(([name, text]) => name === 'fillText' && text === 'LASTONE'),
'an empty field must drop the replay buffer, not strand the last callsign',
);
} finally {
@@ -760,24 +595,12 @@ test('space-tier callouts take the heavier plate while air contacts keep the lig
theme.calloutPlateSpace,
'the fixture is only meaningful while the two tiers differ',
);
const painted = (text) =>
env.ctx.calls.some(
([name, value]) => name === 'fillText' && value === text,
);
assert.ok(
painted('AIRONE') && painted('SATONE'),
'both tiers reached the frame under test',
);
const painted = (text) => env.ctx.calls.some(([name, value]) => name === 'fillText' && value === text);
assert.ok(painted('AIRONE') && painted('SATONE'), 'both tiers reached the frame under test');
const fills = sharedFillStyles(env);
assert.ok(
fills.includes(theme.calloutPlate),
'the air contact keeps the light plate',
);
assert.ok(
fills.includes(theme.calloutPlateSpace),
'the space contact takes the heavier plate',
);
assert.ok(fills.includes(theme.calloutPlate), 'the air contact keeps the light plate');
assert.ok(fills.includes(theme.calloutPlateSpace), 'the space contact takes the heavier plate');
} finally {
env.cleanup();
}
@@ -794,16 +617,11 @@ test('surveillance military tier reaches the dedicated render target as shipped
env.postRender.raise();
assert.ok(
env.detectionCtx.calls.some(
([name, value]) => name === 'strokeStyle' && value === '#ff5a47',
),
env.detectionCtx.calls.some(([name, value]) => name === 'strokeStyle' && value === '#ff5a47'),
'the production projection/tier/batched-bracket paint path emits surveillance military red',
);
assert.ok(
env.detectionCtx.calls.some(
([name, path]) => name === 'stroke' && path instanceof MockPath2D,
),
);
assert.ok(env.detectionCtx.calls.some(([name, path]) => name === 'stroke'
&& path instanceof MockPath2D));
} finally {
env.cleanup();
}
@@ -815,71 +633,44 @@ test('pathological detection paint holds alternate frames without freezing share
try {
initWorldOverlay(env.viewer);
initDetection(env.viewer, [detectableLayer()], () => {});
setOverlayEntries('valve-card', [
{
id: 'ambient-card',
position: new Cesium.Cartesian3(0, 0, 0),
variant: 'label',
title: 'AMBIENT-CONTINUES',
selected: true,
protected: true,
horizonCull: false,
edgeFade: 'none',
},
]);
setOverlayEntries('valve-card', [{
id: 'ambient-card',
position: new Cesium.Cartesian3(0, 0, 0),
variant: 'label',
title: 'AMBIENT-CONTINUES',
selected: true,
protected: true,
horizonCull: false,
edgeFade: 'none',
}]);
setMode('DENSE');
env.advance(250);
env.setPerformanceStep(30);
env.postRender.raise();
env.postRender.raise();
const detectionClears = env.detectionCtx.calls.filter(
([name]) => name === 'clearRect',
).length;
const detectionBanners = env.detectionCtx.calls.filter(
([name, text]) =>
name === 'fillText' && String(text).startsWith('DENSE VIS:'),
).length;
const sharedClears = env.ctx.calls.filter(
([name]) => name === 'clearRect',
).length;
const sharedCards = env.ctx.calls.filter(
([name, text]) => name === 'fillText' && text === 'AMBIENT-CONTINUES',
).length;
const detectionClears = env.detectionCtx.calls.filter(([name]) => name === 'clearRect').length;
const detectionBanners = env.detectionCtx.calls.filter(([name, text]) => name === 'fillText'
&& String(text).startsWith('DENSE VIS:')).length;
const sharedClears = env.ctx.calls.filter(([name]) => name === 'clearRect').length;
const sharedCards = env.ctx.calls.filter(([name, text]) => name === 'fillText'
&& text === 'AMBIENT-CONTINUES').length;
env.postRender.raise();
assert.equal(
env.detectionCtx.calls.filter(([name]) => name === 'clearRect').length,
detectionClears,
'the host preserves detection pixels on the held odd frame',
);
assert.equal(
env.detectionCtx.calls.filter(
([name, text]) =>
name === 'fillText' && String(text).startsWith('DENSE VIS:'),
).length,
detectionBanners,
);
assert.equal(
env.ctx.calls.filter(([name]) => name === 'clearRect').length,
sharedClears + 1,
'the shared surface still clears',
);
assert.equal(
env.ctx.calls.filter(
([name, text]) => name === 'fillText' && text === 'AMBIENT-CONTINUES',
).length,
sharedCards + 1,
'the shared lane still repaints',
);
assert.equal(env.detectionCtx.calls.filter(([name]) => name === 'clearRect').length, detectionClears,
'the host preserves detection pixels on the held odd frame');
assert.equal(env.detectionCtx.calls.filter(([name, text]) => name === 'fillText'
&& String(text).startsWith('DENSE VIS:')).length, detectionBanners);
assert.equal(env.ctx.calls.filter(([name]) => name === 'clearRect').length, sharedClears + 1,
'the shared surface still clears');
assert.equal(env.ctx.calls.filter(([name, text]) => name === 'fillText'
&& text === 'AMBIENT-CONTINUES').length, sharedCards + 1,
'the shared lane still repaints');
assert.equal(getDetectionDiagnostics().throttleSkipCount, 1);
env.postRender.raise();
assert.equal(
env.detectionCtx.calls.filter(([name]) => name === 'clearRect').length,
detectionClears + 1,
'the next even frame repaints detection',
);
assert.equal(env.detectionCtx.calls.filter(([name]) => name === 'clearRect').length,
detectionClears + 1, 'the next even frame repaints detection');
assert.equal(getDetectionDiagnostics().throttleSkipCount, 1);
} finally {
env.cleanup();
@@ -887,14 +678,9 @@ test('pathological detection paint holds alternate frames without freezing share
});
test('detection cannot resurrect a private canvas, listener, matrix, resize, clear, or UI inventory', () => {
const source = readFileSync(
new URL('./detection.js', import.meta.url),
'utf8',
);
const uiSource =
readShellSource() +
'\n' +
readFileSync(new URL('../ui/visualPresets.js', import.meta.url), 'utf8');
const source = readFileSync(new URL('./detection.js', import.meta.url), 'utf8');
const uiSource = readShellSource()
+ '\n' + readFileSync(new URL('../ui/visualPresets.js', import.meta.url), 'utf8');
assert.doesNotMatch(source, /createElement\(\s*['"]canvas['"]\s*\)/);
assert.doesNotMatch(source, /postRender\.addEventListener/);
assert.doesNotMatch(source, /['"]detection-overlay['"]/);
@@ -904,20 +690,11 @@ test('detection cannot resurrect a private canvas, listener, matrix, resize, cle
assert.doesNotMatch(source, /CALLOUT_OCCLUSION_SELECTORS/);
assert.doesNotMatch(source, /_ctx\.(?:filter|globalCompositeOperation)\s*=/);
assert.match(source, /_hostSurface\.style\.mixBlendMode = _theme\.blend;/);
assert.match(
source,
/_hostSurface\.style\.filter = `\$\{_theme\.filter\} drop-shadow\(0 0 \$\{GLOW_PX\}px \$\{_theme\.glow\}\)`;/,
);
assert.match(source, /_hostSurface\.style\.filter = `\$\{_theme\.filter\} drop-shadow\(0 0 \$\{GLOW_PX\}px \$\{_theme\.glow\}\)`;/);
assert.match(source, /const LABEL_SOLVE_INTERVAL_MS = 125;/);
assert.match(source, /const _labelArbiter = new LabelArbiter\(\);/);
assert.match(
source,
/const clipW = vp3 \* px \+ vp7 \* py \+ vp11 \* pz \+ vp15;/,
);
assert.match(
source,
/registerWorldOverlayPaintLane\('detection', _paintDetectionLane/,
);
assert.match(source, /const clipW = vp3 \* px \+ vp7 \* py \+ vp11 \* pz \+ vp15;/);
assert.match(source, /registerWorldOverlayPaintLane\('detection', _paintDetectionLane/);
assert.match(source, /target: 'detection'/);
assert.match(source, /shouldPaint: _shouldPaintDetectionLane/);
// The three military styles used to carry three copies of these numbers.
@@ -934,10 +711,7 @@ test('detection cannot resurrect a private canvas, listener, matrix, resize, cle
3,
'CRT, NVG, and FLIR retain their Dense auto-enable defaults',
);
assert.match(
uiSource,
/preset\.detection && !this\._detectionUserOverridden/,
);
assert.match(uiSource, /preset\.detection && !this\._detectionUserOverridden/);
});
// ── Developer telemetry gate (2026-08-20 QA hunt) ───────────────────────────
@@ -951,22 +725,15 @@ test('detectionDebugRequested parses the query-string gate and nothing else', ()
assert.equal(detectionDebugRequested(''), false);
assert.equal(detectionDebugRequested('?detectDebug=0'), false);
assert.equal(detectionDebugRequested('?detectDebug'), false);
assert.equal(
detectionDebugRequested('?detectdebug=1'),
false,
'the flag is case-sensitive',
);
assert.equal(detectionDebugRequested('?detectdebug=1'), false, 'the flag is case-sensitive');
assert.equal(detectionDebugRequested(undefined), false);
assert.equal(detectionDebugRequested(null), false);
});
test('the mode banner is absent by default and present behind the flag', () => {
const bannerPaints = (env) =>
env.detectionCtx.calls.filter(
([name, text]) =>
name === 'fillText' &&
/^(SPARSE|BALANCED|DENSE) VIS:/.test(String(text)),
).length;
const bannerPaints = (env) => env.detectionCtx.calls.filter(([name, text]) => (
name === 'fillText' && /^(SPARSE|BALANCED|DENSE) VIS:/.test(String(text))
)).length;
const painted = (search) => {
const env = installEnvironment({ search });
@@ -978,9 +745,7 @@ test('the mode banner is absent by default and present behind the flag', () => {
env.postRender.raise();
// The overlay is alive either way — brackets still stroke.
assert.ok(
env.detectionCtx.calls.some(
([name, path]) => name === 'stroke' && path instanceof MockPath2D,
),
env.detectionCtx.calls.some(([name, path]) => name === 'stroke' && path instanceof MockPath2D),
'detection still paints its contacts regardless of the debug gate',
);
return bannerPaints(env);
@@ -991,15 +756,8 @@ test('the mode banner is absent by default and present behind the flag', () => {
}
};
assert.equal(
painted(''),
0,
'users must never see the engine telemetry banner',
);
assert.ok(
painted('?detectDebug=1') > 0,
'the flag brings the telemetry back',
);
assert.equal(painted(''), 0, 'users must never see the engine telemetry banner');
assert.ok(painted('?detectDebug=1') > 0, 'the flag brings the telemetry back');
});
test('detection telemetry stays reachable programmatically with the banner hidden', () => {
@@ -1036,11 +794,7 @@ test('civilian and military AIR brackets cover front, left, and right at Sparse
type: 'AIR',
}));
initWorldOverlay(env.viewer);
initDetection(
env.viewer,
[{ id: layerId, getDetectableObjects: () => objects }],
() => {},
);
initDetection(env.viewer, [{ id: layerId, getDetectableObjects: () => objects }], () => {});
setDetectionTuning({ densityPct: 25 });
setMode('SPARSE');
settleFrame(env);
@@ -1053,10 +807,8 @@ test('civilian and military AIR brackets cover front, left, and right at Sparse
assert.equal(diagnostics.visibleCount, 3);
assert.equal(diagnostics.densityPct, 25);
assert.equal(diagnostics.profile, 'SPARSE');
assert.ok(
diagnostics.selectedCount <= diagnostics.collectiveLabelBudget,
'Sparse keeps its documented budget instead of silently becoming Dense',
);
assert.ok(diagnostics.selectedCount <= diagnostics.collectiveLabelBudget,
'Sparse keeps its documented budget instead of silently becoming Dense');
} finally {
destroyDetection();
destroyWorldOverlay();
@@ -1081,17 +833,11 @@ function backdropLayer() {
return [
{
position: new Cesium.Cartesian3(-0.4, 0.2, 6_356_752),
sourceId: 'ground-1',
id: 'GROUNDED',
metric: 'FL100',
type: 'AIR',
sourceId: 'ground-1', id: 'GROUNDED', metric: 'FL100', type: 'AIR',
},
{
position: new Cesium.Cartesian3(0.4, -0.2, 20_000_000),
sourceId: 'sky-1',
id: 'SKYBACK',
metric: 'FL400',
type: 'AIR',
sourceId: 'sky-1', id: 'SKYBACK', metric: 'FL400', type: 'AIR',
},
];
},
@@ -1113,14 +859,8 @@ test('the backdrop feather reaches the canvas as a lighter plate against sky', (
env.ctx.calls.length = 0;
settleFrame(env);
const painted = (text) =>
env.ctx.calls.some(
([name, value]) => name === 'fillText' && value === text,
);
assert.ok(
painted('GROUNDED') && painted('SKYBACK'),
'both backdrops reached the frame under test',
);
const painted = (text) => env.ctx.calls.some(([name, value]) => name === 'fillText' && value === text);
assert.ok(painted('GROUNDED') && painted('SKYBACK'), 'both backdrops reached the frame under test');
const plate = DETECTION_THEME_MAP._default.calloutPlate;
const plateAlphas = env.ctx.calls
@@ -1131,10 +871,7 @@ test('the backdrop feather reaches the canvas as a lighter plate against sky', (
const heaviest = Math.max(...plateAlphas);
const lightest = Math.min(...plateAlphas);
assert.ok(heaviest > 0, 'the grounded contact still gets a plate');
assert.ok(
lightest > 0,
'the sky contact keeps a whisper rather than vanishing',
);
assert.ok(lightest > 0, 'the sky contact keeps a whisper rather than vanishing');
// Reverting the feature makes both plates equal, which fails here first.
assert.ok(
lightest < heaviest * 0.5,
@@ -1200,23 +937,9 @@ test('a transit vehicle is a contact: box, route, mode and operator on the share
painted.some((text) => String(text).includes('34 KM/H')),
'and so does what the vehicle is doing',
);
assert.ok(
env.ctx.calls.some(
([name, , color, width]) =>
name === 'stroke' && color === '#5EF08A' && width === 1.25,
),
);
assert.ok(
env.ctx.calls.some(
([name, , color, width]) =>
name === 'stroke' && color === '#05080C' && width === 3.25,
),
);
assert.ok(
!env.detectionCtx.calls.some(
([name, , color]) => name === 'stroke' && color === '#5EF08A',
),
);
assert.ok(env.ctx.calls.some(([name, , color, width]) => name === 'stroke' && color === '#5EF08A' && width === 1.25));
assert.ok(env.ctx.calls.some(([name, , color, width]) => name === 'stroke' && color === '#05080C' && width === 3.25));
assert.ok(!env.detectionCtx.calls.some(([name, , color]) => name === 'stroke' && color === '#5EF08A'));
// The operator travels on the object for the two-tier card form, which is
// where `klass` is read; the host's track label does not paint it.
assert.equal(composeLabel(objects[0]).secondary, 'MBTA · BUS 34 KM/H');