Undo the reformatting of four camera-slice tests

The camera-port commits ran prettier over four test files that were
never prettier-formatted. Restore their earlier text and keep only the
camera-port edits.
This commit is contained in:
Sameh Khamis committed 2026-11-06 09:55:05 -08:00
1 parent bc69e8a4ee
commit 68855b2089
4 files changed
+804 -2266

No files matched your search

+146 -320
View File
@@ -1,13 +1,7 @@
import { LayerBindings } from './ui/layerBindings.js'; import { LayerBindings } from './ui/layerBindings.js';
import { import { readShellSource, shellMethod } from './testSupport/readShellSource.mjs';
readShellSource,
shellMethod,
} from './testSupport/readShellSource.mjs';
import { readLayerSource } from './testSupport/readLayerSource.mjs'; import { readLayerSource } from './testSupport/readLayerSource.mjs';
import { import { enter as cockpitEnter, navigateContext } from './ui/cockpitTrackingController.js';
enter as cockpitEnter,
navigateContext,
} from './ui/cockpitTrackingController.js';
import { CockpitViewController } from './ui/cockpitController.js'; import { CockpitViewController } from './ui/cockpitController.js';
import assert from 'node:assert/strict'; import assert from 'node:assert/strict';
import fs from 'node:fs'; import fs from 'node:fs';
@@ -17,24 +11,11 @@ import { fileURLToPath } from 'node:url';
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const ui = readShellSource(); const ui = readShellSource();
const firms = readLayerSource( const firms = readLayerSource(path.join(ROOT, 'src', 'data', 'firmsHeatmap.js'));
path.join(ROOT, 'src', 'data', 'firmsHeatmap.js'), const vessels = readLayerSource(path.join(ROOT, 'src', 'data', 'aisLiveVessels.js'));
); const voice = fs.readFileSync(path.join(ROOT, 'src', 'voice', 'gevActions.js'), 'utf8');
const vessels = readLayerSource( const cameraVerbs = fs.readFileSync(path.join(ROOT, 'src', 'cameraVerbs.js'), 'utf8');
path.join(ROOT, 'src', 'data', 'aisLiveVessels.js'), const cockpitTracking = fs.readFileSync(path.join(ROOT, 'src', 'cockpitTracking.js'), 'utf8');
);
const voice = fs.readFileSync(
path.join(ROOT, 'src', 'voice', 'gevActions.js'),
'utf8',
);
const cameraVerbs = fs.readFileSync(
path.join(ROOT, 'src', 'cameraVerbs.js'),
'utf8',
);
const cockpitTracking = fs.readFileSync(
path.join(ROOT, 'src', 'cockpitTracking.js'),
'utf8',
);
function body(source, pattern, label) { function body(source, pattern, label) {
const name = pattern.source.match(/^(\w+)/)?.[1]; const name = pattern.source.match(/^(\w+)/)?.[1];
@@ -50,14 +31,8 @@ function body(source, pattern, label) {
function ordered(source, needles, label) { function ordered(source, needles, label) {
let previous = -1; let previous = -1;
for (const needle of needles) { for (const needle of needles) {
const match = const match = needle instanceof RegExp ? needle.exec(source.slice(previous + 1)) : null;
needle instanceof RegExp ? needle.exec(source.slice(previous + 1)) : null; const index = needle instanceof RegExp ? (match ? previous + 1 + match.index : -1) : source.indexOf(needle, previous + 1);
const index =
needle instanceof RegExp
? match
? previous + 1 + match.index
: -1
: source.indexOf(needle, previous + 1);
assert.ok(index >= 0, `${label}: missing ${needle}`); assert.ok(index >= 0, `${label}: missing ${needle}`);
assert.ok(index > previous, `${label}: ${needle} is out of order`); assert.ok(index > previous, `${label}: ${needle} is out of order`);
previous = index; previous = index;
@@ -66,16 +41,12 @@ function ordered(source, needles, label) {
test('Cockpit takeover invalidates deferred work before camera cancellation', () => { test('Cockpit takeover invalidates deferred work before camera cancellation', () => {
const enter = cockpitEnter.toString(); const enter = cockpitEnter.toString();
ordered( ordered(enter, [
enter, 'if (!info || !entity?.position) return false;',
[ 'this.onCameraTakeover?.();',
'if (!info || !entity?.position) return false;', 'cameraOf(this.viewer).cancelFlight();',
'this.onCameraTakeover?.();', 'this.viewer.trackedEntity = undefined;',
'cameraOf(this.viewer).cancelFlight();', ], 'Cockpit takeover');
'this.viewer.trackedEntity = undefined;',
],
'Cockpit takeover',
);
assert.match( assert.match(
ui, ui,
/onCameraTakeover: \(\) =>\s*this\._stampNavigation\(\{\s*cancelPendingSelection: false,?\s*\}\),/, /onCameraTakeover: \(\) =>\s*this\._stampNavigation\(\{\s*cancelPendingSelection: false,?\s*\}\),/,
@@ -109,23 +80,11 @@ test('navigation clears dormant tracker IDs without aborting unrelated layer res
); );
assert.doesNotMatch(stamp, /cancelPendingRestores\(\)/); assert.doesNotMatch(stamp, /cancelPendingRestores\(\)/);
assert.match(stamp, /flightsLayer\.cancelPendingTrackingRestore\?\.\(\)/); assert.match(stamp, /flightsLayer\.cancelPendingTrackingRestore\?\.\(\)/);
assert.match( assert.match(stamp, /militaryFlightsLayer\.cancelPendingTrackingRestore\?\.\(\)/);
stamp,
/militaryFlightsLayer\.cancelPendingTrackingRestore\?\.\(\)/,
);
assert.match(stamp, /satellitesLayer\.cancelPendingTrackingRestore\?\.\(\)/); assert.match(stamp, /satellitesLayer\.cancelPendingTrackingRestore\?\.\(\)/);
assert.match( assert.match(stamp, /if \(\s*!passivelyClearedShareSelection\s*&&\s*!flightsLayer\.getTrackedInfo\?\.\(\)\s*\)[\s\S]*?selectedFlightsTrackingId: null/);
stamp, assert.match(stamp, /if \(\s*!passivelyClearedShareSelection\s*&&\s*!militaryFlightsLayer\.getTrackedInfo\?\.\(\)\s*\)[\s\S]*?selectedMilitaryTrackingId: null/);
/if \(\s*!passivelyClearedShareSelection\s*&&\s*!flightsLayer\.getTrackedInfo\?\.\(\)\s*\)[\s\S]*?selectedFlightsTrackingId: null/, assert.match(stamp, /if \(\s*!passivelyClearedShareSelection\s*&&\s*!satellitesLayer\.getTrackedInfo\?\.\(\)\s*\)[\s\S]*?selectedSatTrackingId: null/);
);
assert.match(
stamp,
/if \(\s*!passivelyClearedShareSelection\s*&&\s*!militaryFlightsLayer\.getTrackedInfo\?\.\(\)\s*\)[\s\S]*?selectedMilitaryTrackingId: null/,
);
assert.match(
stamp,
/if \(\s*!passivelyClearedShareSelection\s*&&\s*!satellitesLayer\.getTrackedInfo\?\.\(\)\s*\)[\s\S]*?selectedSatTrackingId: null/,
);
}); });
test('voice Cockpit entry reaches the camera only through stamping seams', () => { test('voice Cockpit entry reaches the camera only through stamping seams', () => {
@@ -145,14 +104,10 @@ test('voice Cockpit entry reaches the camera only through stamping seams', () =>
/export function enterCockpitWithTracking\(\{[\s\S]*?\n\}\) \{([\s\S]*?)\n\}\n/, /export function enterCockpitWithTracking\(\{[\s\S]*?\n\}\) \{([\s\S]*?)\n\}\n/,
'Cockpit entry transaction', 'Cockpit entry transaction',
); );
ordered( ordered(transaction, [
transaction, /if \(\s*!selectedLayer\.trackById\?\.\(selectedTarget\.id, \{\s*origin: selectionOrigin,?\s*\}\)\s*\) \{/,
[ 'if (!entryError) entered = Boolean(cockpitView.enter());',
/if \(\s*!selectedLayer\.trackById\?\.\(selectedTarget\.id, \{\s*origin: selectionOrigin,?\s*\}\)\s*\) \{/, ], 'Cockpit entry transaction');
'if (!entryError) entered = Boolean(cockpitView.enter());',
],
'Cockpit entry transaction',
);
// No direct camera control: every mutation goes through a layer tracker or // No direct camera control: every mutation goes through a layer tracker or
// the cockpit controller, both of which stamp. // the cockpit controller, both of which stamp.
assert.doesNotMatch(transaction, /\b(?:viewer\.)?camera\s*(?:\.|\[|=)/); assert.doesNotMatch(transaction, /\b(?:viewer\.)?camera\s*(?:\.|\[|=)/);
@@ -191,41 +146,27 @@ test('voice Cockpit next/previous shares the manual Context navigation path', ()
/this\._listen\(this\.contextNext, 'click', \(\) =>\s*this\.navigateContext\(1, \{ origin: 'user' \}\),?\s*\);/, /this\._listen\(this\.contextNext, 'click', \(\) =>\s*this\.navigateContext\(1, \{ origin: 'user' \}\),?\s*\);/,
); );
const funnel = navigateContext.toString(); const funnel = navigateContext.toString();
assert.match( assert.match(funnel, /const navigationOptions = wasActive\s*\? \{ \.\.\.options, aircraftOnly: true \}\s*: options;/);
funnel, ordered(funnel, [
/const navigationOptions = wasActive\s*\? \{ \.\.\.options, aircraftOnly: true \}\s*: options;/, "const method = direction < 0 ? 'navigatePrevious' : 'navigateNext';",
); 'const navigationOptions = wasActive',
ordered( 'militaryAwarenessLayer?.[method]?.(navigationOptions)',
funnel, 'this._adoptTrackedEntity(performance.now());',
[ ], 'Cockpit Context navigation funnel');
"const method = direction < 0 ? 'navigatePrevious' : 'navigateNext';",
'const navigationOptions = wasActive',
'militaryAwarenessLayer?.[method]?.(navigationOptions)',
'this._adoptTrackedEntity(performance.now());',
],
'Cockpit Context navigation funnel',
);
const navigate = body( const navigate = body(
ui, ui,
/if \(normalized === 'next' \|\| normalized === 'previous'\) \{([\s\S]*?)\n \}/, /if \(normalized === 'next' \|\| normalized === 'previous'\) \{([\s\S]*?)\n \}/,
'controlCockpit navigation branch', 'controlCockpit navigation branch',
); );
ordered( ordered(navigate, [
navigate, 'this.cockpitView.navigateContext(',
['this.cockpitView.navigateContext(', "normalized === 'next' ? 1 : -1,"], "normalized === 'next' ? 1 : -1,",
'controlCockpit navigation branch', ], 'controlCockpit navigation branch');
);
// No private camera route around the awareness layer. // No private camera route around the awareness layer.
assert.doesNotMatch( assert.doesNotMatch(navigate, /flyTo|camera|trackById|_runExplicitNavigation/);
navigate,
/flyTo|camera|trackById|_runExplicitNavigation/,
);
// An exhausted cohort is an honest failure, not a silent success. // An exhausted cohort is an honest failure, not a silent success.
assert.match(navigate, /ok: changed,/); assert.match(navigate, /ok: changed,/);
assert.match( assert.match(navigate, /error: changed \? null : 'No further context target was available',/);
navigate,
/error: changed \? null : 'No further context target was available',/,
);
}); });
test('accepted navigation releases through PR15-aware ownership before flight', () => { test('accepted navigation releases through PR15-aware ownership before flight', () => {
@@ -234,69 +175,37 @@ test('accepted navigation releases through PR15-aware ownership before flight',
/_runExplicitNavigation\(noun, navigate, releaseOptions = undefined\) \{([\s\S]*?)\n \}/, /_runExplicitNavigation\(noun, navigate, releaseOptions = undefined\) \{([\s\S]*?)\n \}/,
'explicit navigation', 'explicit navigation',
); );
ordered( ordered(run, [
run, 'cockpitActive: this.isCockpitActive()',
[ 'stamp: () => this._stampNavigation()',
'cockpitActive: this.isCockpitActive()', 'release: () => this._releaseFollowCamera(releaseOptions)',
'stamp: () => this._stampNavigation()', 'navigate,',
'release: () => this._releaseFollowCamera(releaseOptions)', ], 'explicit navigation');
'navigate,',
],
'explicit navigation',
);
const release = body( const release = body(
ui, ui,
/_releaseFollowCamera\(\{[\s\S]*?\} = \{\}\) \{([\s\S]*?)\n \}/, /_releaseFollowCamera\(\{[\s\S]*?\} = \{\}\) \{([\s\S]*?)\n \}/,
'follow release', 'follow release',
); );
ordered( ordered(release, [
release, 'origin: trackingOrigin',
[ 'satellitesLayer.stopTracking?.({ origin: trackingOrigin })',
'origin: trackingOrigin', 'rocketLaunchesLayer.releaseCameraOwnership?.()',
'satellitesLayer.stopTracking?.({ origin: trackingOrigin })', 'this.viewer.trackedEntity = undefined;',
'rocketLaunchesLayer.releaseCameraOwnership?.()', "interruptCameraMotion('explicit-navigation')",
'this.viewer.trackedEntity = undefined;', 'this.viewer.camera.cancelFlight();',
"interruptCameraMotion('explicit-navigation')", 'this.viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);',
'this.viewer.camera.cancelFlight();', ], 'follow release');
'this.viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);', assert.match(release, /flightsLayer\.stopTracking\?\.\(\{ origin: trackingOrigin \}\)/);
], assert.match(release, /militaryFlightsLayer\.stopTracking\?\.\(\{ origin: trackingOrigin \}\)/);
'follow release',
);
assert.match(
release,
/flightsLayer\.stopTracking\?\.\(\{ origin: trackingOrigin \}\)/,
);
assert.match(
release,
/militaryFlightsLayer\.stopTracking\?\.\(\{ origin: trackingOrigin \}\)/,
);
}); });
test('validated voice camera destinations share the UI navigation authority facade', () => { test('validated voice camera destinations share the UI navigation authority facade', () => {
assert.match( assert.match(ui, /runImmediateNavigation\(noun, navigate, releaseOptions = undefined\) \{\s*return this\._runExplicitNavigation\(noun, navigate, releaseOptions\);/);
ui, assert.match(voice, /runManagedVoiceNavigation\(\s*styleManager,\s*'camera',\s*'move_camera',\s*navigate,\s*releaseOptions/);
/runImmediateNavigation\(noun, navigate, releaseOptions = undefined\) \{\s*return this\._runExplicitNavigation\(noun, navigate, releaseOptions\);/, assert.match(voice, /runManagedVoiceNavigation\(\s*styleManager,\s*'route',\s*'fly_route',\s*navigate/);
); assert.match(voice, /runManagedVoiceNavigation\(\s*styleManager,\s*'fire',\s*'track_entity'/);
assert.match( assert.match(voice, /runManagedVoiceNavigation\(\s*styleManager,\s*family\.kind,\s*'track_entity'/);
voice, assert.match(voice, /runManagedVoiceNavigation\(\s*styleManager,\s*'frame',\s*'frame_overhead'/);
/runManagedVoiceNavigation\(\s*styleManager,\s*'camera',\s*'move_camera',\s*navigate,\s*releaseOptions/,
);
assert.match(
voice,
/runManagedVoiceNavigation\(\s*styleManager,\s*'route',\s*'fly_route',\s*navigate/,
);
assert.match(
voice,
/runManagedVoiceNavigation\(\s*styleManager,\s*'fire',\s*'track_entity'/,
);
assert.match(
voice,
/runManagedVoiceNavigation\(\s*styleManager,\s*family\.kind,\s*'track_entity'/,
);
assert.match(
voice,
/runManagedVoiceNavigation\(\s*styleManager,\s*'frame',\s*'frame_overhead'/,
);
const trackedVoice = voice.slice( const trackedVoice = voice.slice(
voice.indexOf('async function trackEntity'), voice.indexOf('async function trackEntity'),
voice.indexOf('async function frameOverhead'), voice.indexOf('async function frameOverhead'),
@@ -313,80 +222,47 @@ test('validated voice camera destinations share the UI navigation authority faca
/export function moveCamera\(args = \{\}, runNavigation = null\) \{([\s\S]*?)\n\}/, /export function moveCamera\(args = \{\}, runNavigation = null\) \{([\s\S]*?)\n\}/,
'move camera', 'move camera',
); );
ordered( ordered(move, [
move, "if (!['orbit', 'pan', 'tilt', 'rotate', 'rotate_globe'].includes(motion))",
[ 'const start = () => {',
"if (!['orbit', 'pan', 'tilt', 'rotate', 'rotate_globe'].includes(motion))", /const preserveCameraFlight =\s*motion === 'orbit'/,
'const start = () => {', 'runNavigation(start, { preserveCameraFlight })',
/const preserveCameraFlight =\s*motion === 'orbit'/, ], 'move validation before handoff');
'runNavigation(start, { preserveCameraFlight })',
],
'move validation before handoff',
);
const route = body( const route = body(
cameraVerbs, cameraVerbs,
/export function flyRoute\(\s*annoList,\s*args = \{\},\s*floorFn = null,\s*runNavigation = null,\s*warmFn = null,?\s*\) \{([\s\S]*?)\n\}/, /export function flyRoute\(\s*annoList,\s*args = \{\},\s*floorFn = null,\s*runNavigation = null,\s*warmFn = null,?\s*\) \{([\s\S]*?)\n\}/,
'fly route', 'fly route',
); );
ordered( ordered(route, [
route, 'if (!routes.length)',
[ 'const pts = route.path.map',
'if (!routes.length)', 'const start = () => {',
'const pts = route.path.map', /return typeof runNavigation === 'function'\s*\? runNavigation\(start\)\s*: start\(\);/,
'const start = () => {', ], 'route validation before handoff');
/return typeof runNavigation === 'function'\s*\? runNavigation\(start\)\s*: start\(\);/,
],
'route validation before handoff',
);
// The corridor warm is injected the same way the floor READ is — the dolly // The corridor warm is injected the same way the floor READ is — the dolly
// never reaches into the data layer itself, and the voice dispatch is the one // never reaches into the data layer itself, and the voice dispatch is the one
// place that binds both. // place that binds both.
assert.match( assert.match(voice, /\(lat, lon\) => floorServices\.cachedGroundFloor\(lat, lon\),[\s\S]{0,200}?\(cells\) => floorServices\.warmGroundFloor\(cells\),/);
voice,
/\(lat, lon\) => floorServices\.cachedGroundFloor\(lat, lon\),[\s\S]{0,200}?\(cells\) => floorServices\.warmGroundFloor\(cells\),/,
);
}); });
test('deferred search releases only after its final authority check', () => { test('deferred search releases only after its final authority check', () => {
const search = fs.readFileSync( const search = fs.readFileSync(path.join(ROOT, 'src', 'ui', 'locationSearch.js'), 'utf8');
path.join(ROOT, 'src', 'ui', 'locationSearch.js'), ordered(search, [
'utf8', 'const authority = this.begin();',
); 'this.onStart?.(authority);',
ordered( 'await this.search(query',
search, 'beforeFly: () => current() && this.beforeFly(authority)',
[ 'if (!current() || controller.signal.aborted) return;',
'const authority = this.begin();', 'destination?.cancelled',
'this.onStart?.(authority);', 'finally',
'await this.search(query', 'this.onSettled?.(authority)',
'beforeFly: () => current() && this.beforeFly(authority)', ], 'deferred search component');
'if (!current() || controller.signal.aborted) return;', assert.match(ui, /begin: \(\) => this\._beginDeferredNavigation\('location'\)/);
'destination?.cancelled', assert.match(ui, /beforeFly: \(generation\) => this\._reassertNavigationHandoff\(generation\)/);
'finally', assert.match(ui, /isCurrent: \(generation\) =>\s*!this\._disposed && generation === this\._navigationGeneration/);
'this.onSettled?.(authority)', assert.match(ui, /change\.type === 'settled'\)\s*this\._settleLocationSearchUi\(change\.generation, \{\s*keepQuery: state\.status === 'missing' \|\| state\.status === 'failed',?\s*\}\)/);
], assert.doesNotMatch(search.slice(0, search.indexOf('await this.search')), /_releaseFollowCamera/);
'deferred search component',
);
assert.match(
ui,
/begin: \(\) => this\._beginDeferredNavigation\('location'\)/,
);
assert.match(
ui,
/beforeFly: \(generation\) => this\._reassertNavigationHandoff\(generation\)/,
);
assert.match(
ui,
/isCurrent: \(generation\) =>\s*!this\._disposed && generation === this\._navigationGeneration/,
);
assert.match(
ui,
/change\.type === 'settled'\)\s*this\._settleLocationSearchUi\(change\.generation, \{\s*keepQuery: state\.status === 'missing' \|\| state\.status === 'failed',?\s*\}\)/,
);
assert.doesNotMatch(
search.slice(0, search.indexOf('await this.search')),
/_releaseFollowCamera/,
);
}); });
test('a direct globe gesture retires delayed camera and selection restore only', () => { test('a direct globe gesture retires delayed camera and selection restore only', () => {
@@ -411,115 +287,77 @@ test('a direct globe gesture retires delayed camera and selection restore only',
/_stampNavigation\(\{ cancelPendingSelection = true[^)]*\} = \{\}\) \{([\s\S]*?)\n \}/, /_stampNavigation\(\{ cancelPendingSelection = true[^)]*\} = \{\}\) \{([\s\S]*?)\n \}/,
'navigation stamp', 'navigation stamp',
); );
assert.match( assert.match(stamp, /if \(cancelPendingSelection\) \{[\s\S]*?cancelPendingTrackingRestore/);
stamp,
/if \(cancelPendingSelection\) \{[\s\S]*?cancelPendingTrackingRestore/,
);
assert.doesNotMatch(stamp, /cancelPendingRestores\(\)/); assert.doesNotMatch(stamp, /cancelPendingRestores\(\)/);
}); });
test('newer navigation, reset, Cockpit, and teardown share one generation', () => { test('newer navigation, reset, Cockpit, and teardown share one generation', () => {
assert.equal((ui.match(/_navigationGeneration \+= 1/g) || []).length, 1); assert.equal((ui.match(/_navigationGeneration \+= 1/g) || []).length, 1);
const reset = body(ui, /resetToGlobeView\(\) \{([\s\S]*?)\n \}/, 'reset'); const reset = body(ui, /resetToGlobeView\(\) \{([\s\S]*?)\n \}/, 'reset');
ordered( ordered(reset, [
reset, 'if (this._globeResetPromise) return this._globeResetPromise;',
[ 'this._stampNavigation();',
'if (this._globeResetPromise) return this._globeResetPromise;', "interruptCameraMotion('reset-globe')",
'this._stampNavigation();', ], 'reset supersession');
"interruptCameraMotion('reset-globe')",
],
'reset supersession',
);
const dispose = body(ui, /async dispose\(\) \{([\s\S]*?)\n \}/, 'dispose'); const dispose = body(ui, /async dispose\(\) \{([\s\S]*?)\n \}/, 'dispose');
ordered( ordered(dispose, [
dispose, 'this._disposed = true;',
[ 'this._layerBindings.stop();',
'this._disposed = true;', 'this._navigation.destroy();',
'this._layerBindings.stop();', 'await this._contextControls.restoreForDisposal();',
'this._navigation.destroy();', ], 'dispose invalidation');
'await this._contextControls.restoreForDisposal();',
],
'dispose invalidation',
);
assert.match(shellMethod('destroy').toString(), /this\._stampNavigation\(\)/); assert.match(shellMethod('destroy').toString(), /this\._stampNavigation\(\)/);
}); });
test('teardown synchronously closes immediate camera entry points', () => { test('teardown synchronously closes immediate camera entry points', () => {
const dispose = body(ui, /async dispose\(\) \{([\s\S]*?)\n \}/, 'dispose'); const dispose = body(ui, /async dispose\(\) \{([\s\S]*?)\n \}/, 'dispose');
ordered( ordered(dispose, [
dispose, 'this._disposed = true;',
[ 'this._layerBindings.stop();',
'this._disposed = true;', 'await this._contextControls.restoreForDisposal();',
'this._layerBindings.stop();', ], 'synchronous teardown barrier');
'await this._contextControls.restoreForDisposal();', ordered(LayerBindings.prototype.stop.toString(), [
], 'this._disposed = true;',
'synchronous teardown barrier', 'this._removeCctvRequestFocusListener?.();',
); 'this._removeWorldRequestFocusListener?.();',
ordered( 'this._navigationOwnerChangedRemover?.();',
LayerBindings.prototype.stop.toString(), ], 'camera bindings close synchronously');
[
'this._disposed = true;',
'this._removeCctvRequestFocusListener?.();',
'this._removeWorldRequestFocusListener?.();',
'this._navigationOwnerChangedRemover?.();',
],
'camera bindings close synchronously',
);
const navigation = body( const navigation = body(
ui, ui,
/_runExplicitNavigation\(noun, navigate, releaseOptions = undefined\) \{([\s\S]*?)\n \}/, /_runExplicitNavigation\(noun, navigate, releaseOptions = undefined\) \{([\s\S]*?)\n \}/,
'explicit navigation', 'explicit navigation',
); );
ordered( ordered(navigation, [
navigation, 'disposed: this._disposed',
[ 'release: () => this._releaseFollowCamera(releaseOptions)',
'disposed: this._disposed', 'navigate,',
'release: () => this._releaseFollowCamera(releaseOptions)', ], 'disposed navigation guard');
'navigate,',
],
'disposed navigation guard',
);
const cctvFocus = body( const cctvFocus = body(
ui, ui,
/_runExplicitCctvFocus\(activate, focus\) \{([\s\S]*?)\n \}/, /_runExplicitCctvFocus\(activate, focus\) \{([\s\S]*?)\n \}/,
'explicit CCTV focus', 'explicit CCTV focus',
); );
ordered( ordered(cctvFocus, [
cctvFocus, 'if (this._disposed) return false;',
['if (this._disposed) return false;', 'const cameraId = activate();'], 'const cameraId = activate();',
'disposed CCTV activation guard', ], 'disposed CCTV activation guard');
);
}); });
test('teardown refuses deferred location work before geocoding begins', () => { test('teardown refuses deferred location work before geocoding begins', () => {
const deferred = body( const deferred = body(ui, /_beginDeferredNavigation\(noun = 'location', \{ cancelPendingSelection = true \} = \{\}\) \{([\s\S]*?)\n \}/, 'deferred navigation');
ui,
/_beginDeferredNavigation\(noun = 'location', \{ cancelPendingSelection = true \} = \{\}\) \{([\s\S]*?)\n \}/,
'deferred navigation',
);
assert.match(deferred, /disposed: this\._disposed/); assert.match(deferred, /disposed: this\._disposed/);
const search = fs.readFileSync( const search = fs.readFileSync(path.join(ROOT, 'src', 'ui', 'locationSearch.js'), 'utf8');
path.join(ROOT, 'src', 'ui', 'locationSearch.js'), ordered(search, [
'utf8', 'if (!query || this.destroyed) return;',
); 'const authority = this.begin();',
ordered( 'if (authority === false)',
search, 'this.input?.blur();',
[ 'this.onStart?.(authority);',
'if (!query || this.destroyed) return;', 'await this.search(query',
'const authority = this.begin();', ], 'disposed search refusal');
'if (authority === false)', assert.match(search, /if \(authority === false\) \{[\s\S]*?return;[\s\S]*?\}\s*this\.controller/);
'this.input?.blur();',
'this.onStart?.(authority);',
'await this.search(query',
],
'disposed search refusal',
);
assert.match(
search,
/if \(authority === false\) \{[\s\S]*?return;[\s\S]*?\}\s*this\.controller/,
);
}); });
test('refused canned destinations commit no location or POI state', () => { test('refused canned destinations commit no location or POI state', () => {
@@ -528,15 +366,11 @@ test('refused canned destinations commit no location or POI state', () => {
['poi', /_onPoiClick\(cityId, poiIndex\) \{([\s\S]*?)\n \}/], ['poi', /_onPoiClick\(cityId, poiIndex\) \{([\s\S]*?)\n \}/],
]) { ]) {
const handler = body(ui, pattern, name); const handler = body(ui, pattern, name);
ordered( ordered(handler, [
handler, 'this._flyWithTransition(',
[ 'if (result === false) return;',
'this._flyWithTransition(', 'this._setActiveLocation(cityId);',
'if (result === false) return;', ], name);
'this._setActiveLocation(cityId);',
],
name,
);
} }
}); });
@@ -558,15 +392,11 @@ test('vessel and fire layers announce valid clicks and never fly cameras', () =>
/inputFor\(viewer\)\.onClick\(\(event\) => \{([\s\S]*?)\n \}\);/, /inputFor\(viewer\)\.onClick\(\(event\) => \{([\s\S]*?)\n \}\);/,
'vessel click', 'vessel click',
); );
ordered( ordered(vesselClick, [
vesselClick, "isOwnedByOtherLayer('ais-live-vessels', pickedId)",
[ '_vesselOverlayHost.hitTest?.(',
"isOwnedByOtherLayer('ais-live-vessels', pickedId)", 'selectAndFocusVessel(record)',
'_vesselOverlayHost.hitTest?.(', ], 'vessel sibling ownership');
'selectAndFocusVessel(record)',
],
'vessel sibling ownership',
);
const vesselFocus = body( const vesselFocus = body(
vessels, vessels,
/function selectAndFocusVessel\(record\) \{([\s\S]*?)\n \}/, /function selectAndFocusVessel\(record\) \{([\s\S]*?)\n \}/,
@@ -578,13 +408,9 @@ test('vessel and fire layers announce valid clicks and never fly cameras', () =>
/input\.onClick\(\(event\) => \{([\s\S]*?)\n \}\);/, /input\.onClick\(\(event\) => \{([\s\S]*?)\n \}\);/,
'fire click', 'fire click',
); );
ordered( ordered(fireClick, [
fireClick, 'isOwnedByOtherLayer(id, pickedId)',
[ 'overlayHost.hitTest?.(',
'isOwnedByOtherLayer(id, pickedId)', 'selectAndFocusFire(carded)',
'overlayHost.hitTest?.(', ], 'fire sibling ownership');
'selectAndFocusFire(carded)',
],
'fire sibling ownership',
);
}); });
File diff suppressed because it is too large. Load diff
+464 -1166
View File
File diff suppressed because it is too large. Load diff
+30 -123
View File
@@ -22,28 +22,16 @@ function stubCamera() {
return { return {
calls, calls,
heading: Cesium.Math.toRadians(45), heading: Cesium.Math.toRadians(45),
cancelFlight() { cancelFlight() { calls.cancelFlight += 1; },
calls.cancelFlight += 1; flyToBoundingSphere(sphere, options) { calls.flights.push({ sphere, options }); },
},
flyToBoundingSphere(sphere, options) {
calls.flights.push({ sphere, options });
},
}; };
} }
test('a focus request carries the clicked target to any registered listener', () => { test('a focus request carries the clicked target to any registered listener', () => {
const target = new EventTarget(); const target = new EventTarget();
const seen = []; const seen = [];
const dispose = registerWorldFocusRequestListener(target, (event) => const dispose = registerWorldFocusRequestListener(target, (event) => seen.push(event.detail));
seen.push(event.detail), assert.equal(requestWorldFocus({ kind: 'vessel', position: POSITION, id: '123' }, target), true);
);
assert.equal(
requestWorldFocus(
{ kind: 'vessel', position: POSITION, id: '123' },
target,
),
true,
);
assert.equal(seen.length, 1); assert.equal(seen.length, 1);
assert.equal(seen[0].kind, 'vessel'); assert.equal(seen[0].kind, 'vessel');
assert.equal(seen[0].id, '123'); assert.equal(seen[0].id, '123');
@@ -57,9 +45,7 @@ test('a focus request carries the clicked target to any registered listener', ()
test('requests without a kind or a position are dropped, never dispatched', () => { test('requests without a kind or a position are dropped, never dispatched', () => {
const target = new EventTarget(); const target = new EventTarget();
let count = 0; let count = 0;
target.addEventListener(WORLD_FOCUS_REQUEST_EVENT, () => { target.addEventListener(WORLD_FOCUS_REQUEST_EVENT, () => { count += 1; });
count += 1;
});
assert.equal(requestWorldFocus({ position: POSITION }, target), false); assert.equal(requestWorldFocus({ position: POSITION }, target), false);
assert.equal(requestWorldFocus({ kind: 'vessel' }, target), false); assert.equal(requestWorldFocus({ kind: 'vessel' }, target), false);
assert.equal(requestWorldFocus(null, target), false); assert.equal(requestWorldFocus(null, target), false);
@@ -89,95 +75,51 @@ test('a refusing policy (cockpit owns the camera) never reaches the flight', ()
const result = routeWorldFocusRequest( const result = routeWorldFocusRequest(
{ detail: { kind: 'vessel', id: '123', position: POSITION } }, { detail: { kind: 'vessel', id: '123', position: POSITION } },
() => false, () => false,
() => { () => { flights += 1; },
flights += 1;
},
); );
assert.equal(result, false); assert.equal(result, false);
assert.equal(flights, 0); assert.equal(flights, 0);
}); });
test('malformed requests are inert', () => { test('malformed requests are inert', () => {
assert.equal( assert.equal(routeWorldFocusRequest(null, () => 'x', () => 'y'), false);
routeWorldFocusRequest( assert.equal(routeWorldFocusRequest({ detail: { kind: 'vessel' } }, () => 'x', () => 'y'), false);
null,
() => 'x',
() => 'y',
),
false,
);
assert.equal(
routeWorldFocusRequest(
{ detail: { kind: 'vessel' } },
() => 'x',
() => 'y',
),
false,
);
}); });
// A request that cannot fly must never cost the user their tracking: the UI // A request that cannot fly must never cost the user their tracking: the UI
// policy releases the follow camera, so validation happens BEFORE it runs. // policy releases the follow camera, so validation happens BEFORE it runs.
test('an unflyable request never reaches the release policy', () => { test('an unflyable request never reaches the release policy', () => {
const unflyable = [ const unflyable = [
{ kind: 'plane', position: POSITION }, // no framing for this kind { kind: 'plane', position: POSITION }, // no framing for this kind
{ kind: 'vessel', position: { x: NaN, y: 0, z: 0 } }, // malformed position { kind: 'vessel', position: { x: NaN, y: 0, z: 0 } }, // malformed position
{ kind: 'vessel', position: { x: 0, y: 0 } }, // truthy but incomplete { kind: 'vessel', position: { x: 0, y: 0 } }, // truthy but incomplete
{ kind: 'vessel', id: '123', position: { x: 0, y: 0, z: 0 } }, // ECEF origin { kind: 'vessel', id: '123', position: { x: 0, y: 0, z: 0 } }, // ECEF origin
{ kind: 'fire', id: 'fire-1', position: { x: 1, y: 1, z: 1 } }, // finite but inside Earth { kind: 'fire', id: 'fire-1', position: { x: 1, y: 1, z: 1 } }, // finite but inside Earth
{ kind: 'vessel', position: 'somewhere' }, { kind: 'vessel', position: 'somewhere' },
{ kind: 'vessel', position: POSITION }, // missing owner id { kind: 'vessel', position: POSITION }, // missing owner id
{ position: POSITION }, { position: POSITION },
]; ];
for (const detail of unflyable) { for (const detail of unflyable) {
assert.equal( assert.equal(isValidWorldFocusTarget(detail), false, JSON.stringify(detail));
isValidWorldFocusTarget(detail),
false,
JSON.stringify(detail),
);
let policyRuns = 0; let policyRuns = 0;
const result = routeWorldFocusRequest( const result = routeWorldFocusRequest(
{ detail }, { detail },
() => { () => { policyRuns += 1; return 'released'; },
policyRuns += 1;
return 'released';
},
() => 'flew', () => 'flew',
); );
assert.equal(result, false, JSON.stringify(detail)); assert.equal(result, false, JSON.stringify(detail));
assert.equal( assert.equal(policyRuns, 0, `the policy must not run for ${JSON.stringify(detail)}`);
policyRuns,
0,
`the policy must not run for ${JSON.stringify(detail)}`,
);
// Nor may such a request be dispatched in the first place. // Nor may such a request be dispatched in the first place.
assert.equal(requestWorldFocus(detail, new EventTarget()), false); assert.equal(requestWorldFocus(detail, new EventTarget()), false);
} }
assert.equal( assert.equal(isValidWorldFocusTarget({ kind: 'vessel', id: '123', position: POSITION }), true);
isValidWorldFocusTarget({ kind: 'vessel', id: '123', position: POSITION }), assert.equal(isValidWorldFocusTarget({ kind: 'fire', id: 'fire-1', position: POSITION }), true);
true,
);
assert.equal(
isValidWorldFocusTarget({ kind: 'fire', id: 'fire-1', position: POSITION }),
true,
);
}); });
test('the transfer flight supersedes any flight in progress and keeps the operator heading', () => { test('the transfer flight supersedes any flight in progress and keeps the operator heading', () => {
const camera = stubCamera(); const camera = stubCamera();
assert.equal( assert.equal(flyToWorldTarget(bindFakeCesiumCamera({ camera }), { kind: 'vessel', id: '123', position: POSITION }), true);
flyToWorldTarget(bindFakeCesiumCamera({ camera }), { assert.equal(camera.calls.cancelFlight, 1, 'a prior flight must be cancelled, not queued');
kind: 'vessel',
id: '123',
position: POSITION,
}),
true,
);
assert.equal(
camera.calls.cancelFlight,
1,
'a prior flight must be cancelled, not queued',
);
assert.equal(camera.calls.flights.length, 1); assert.equal(camera.calls.flights.length, 1);
const { sphere, options } = camera.calls.flights[0]; const { sphere, options } = camera.calls.flights[0];
assert.equal(sphere.radius, WORLD_FOCUS_FRAMING.vessel.radiusM); assert.equal(sphere.radius, WORLD_FOCUS_FRAMING.vessel.radiusM);
@@ -190,20 +132,12 @@ test('the transfer flight supersedes any flight in progress and keeps the operat
test('fires frame wider than vessels — a fire is read by its surroundings', () => { test('fires frame wider than vessels — a fire is read by its surroundings', () => {
const camera = stubCamera(); const camera = stubCamera();
flyToWorldTarget(bindFakeCesiumCamera({ camera }), { flyToWorldTarget(bindFakeCesiumCamera({ camera }), { kind: 'fire', id: 'fire-1', position: POSITION });
kind: 'fire',
id: 'fire-1',
position: POSITION,
});
const { sphere, options } = camera.calls.flights[0]; const { sphere, options } = camera.calls.flights[0];
assert.equal(sphere.radius, WORLD_FOCUS_FRAMING.fire.radiusM); assert.equal(sphere.radius, WORLD_FOCUS_FRAMING.fire.radiusM);
assert.equal(options.offset.range, WORLD_FOCUS_FRAMING.fire.rangeM); assert.equal(options.offset.range, WORLD_FOCUS_FRAMING.fire.rangeM);
assert.ok( assert.ok(WORLD_FOCUS_FRAMING.fire.rangeM > WORLD_FOCUS_FRAMING.vessel.rangeM);
WORLD_FOCUS_FRAMING.fire.rangeM > WORLD_FOCUS_FRAMING.vessel.rangeM, assert.ok(WORLD_FOCUS_FRAMING.fire.radiusM > WORLD_FOCUS_FRAMING.vessel.radiusM);
);
assert.ok(
WORLD_FOCUS_FRAMING.fire.radiusM > WORLD_FOCUS_FRAMING.vessel.radiusM,
);
}); });
test('every framing is a real oblique standoff, not a nadir or an inside-out sphere', () => { test('every framing is a real oblique standoff, not a nadir or an inside-out sphere', () => {
@@ -212,52 +146,25 @@ test('every framing is a real oblique standoff, not a nadir or an inside-out sph
for (const kind of kinds) { for (const kind of kinds) {
const framing = WORLD_FOCUS_FRAMING[kind]; const framing = WORLD_FOCUS_FRAMING[kind];
// Looking DOWN at the target, but obliquely — a nadir drop reads as a map. // Looking DOWN at the target, but obliquely — a nadir drop reads as a map.
assert.ok( assert.ok(framing.pitchDeg < 0, `${kind}: pitch must look down, got ${framing.pitchDeg}`);
framing.pitchDeg < 0, assert.ok(framing.pitchDeg > -80, `${kind}: pitch must stay oblique, got ${framing.pitchDeg}`);
`${kind}: pitch must look down, got ${framing.pitchDeg}`,
);
assert.ok(
framing.pitchDeg > -80,
`${kind}: pitch must stay oblique, got ${framing.pitchDeg}`,
);
// Standing off outside the framed sphere, at a human-readable distance. // Standing off outside the framed sphere, at a human-readable distance.
assert.ok(framing.radiusM > 0, `${kind}: radius must be positive`); assert.ok(framing.radiusM > 0, `${kind}: radius must be positive`);
assert.ok( assert.ok(
framing.rangeM > framing.radiusM, framing.rangeM > framing.radiusM,
`${kind}: range ${framing.rangeM} must stand off outside radius ${framing.radiusM}`, `${kind}: range ${framing.rangeM} must stand off outside radius ${framing.radiusM}`,
); );
assert.ok( assert.ok(framing.rangeM <= 10000, `${kind}: range must stay close-in, got ${framing.rangeM}`);
framing.rangeM <= 10000,
`${kind}: range must stay close-in, got ${framing.rangeM}`,
);
} }
// Exact shipped values — a silent retune must show up as a failing test. // Exact shipped values — a silent retune must show up as a failing test.
assert.deepEqual( assert.deepEqual({ ...WORLD_FOCUS_FRAMING.vessel }, { radiusM: 150, rangeM: 1200, pitchDeg: -30 });
{ ...WORLD_FOCUS_FRAMING.vessel }, assert.deepEqual({ ...WORLD_FOCUS_FRAMING.fire }, { radiusM: 400, rangeM: 3000, pitchDeg: -35 });
{ radiusM: 150, rangeM: 1200, pitchDeg: -30 },
);
assert.deepEqual(
{ ...WORLD_FOCUS_FRAMING.fire },
{ radiusM: 400, rangeM: 3000, pitchDeg: -35 },
);
}); });
test('unknown kinds and missing viewers issue no flight', () => { test('unknown kinds and missing viewers issue no flight', () => {
const camera = stubCamera(); const camera = stubCamera();
assert.equal( assert.equal(flyToWorldTarget(bindFakeCesiumCamera({ camera }), { kind: 'plane', position: POSITION }), false);
flyToWorldTarget(bindFakeCesiumCamera({ camera }), { assert.equal(flyToWorldTarget(bindFakeCesiumCamera({ camera }), { kind: 'vessel' }), false);
kind: 'plane', assert.equal(flyToWorldTarget(null, { kind: 'vessel', position: POSITION }), false);
position: POSITION,
}),
false,
);
assert.equal(
flyToWorldTarget(bindFakeCesiumCamera({ camera }), { kind: 'vessel' }),
false,
);
assert.equal(
flyToWorldTarget(null, { kind: 'vessel', position: POSITION }),
false,
);
assert.equal(camera.calls.flights.length, 0); assert.equal(camera.calls.flights.length, 0);
}); });