mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
refactor: isolate Context controls and layer restoration
This commit is contained in:
1 parent
7f70b97536
commit
fc369cc65a
26 files changed
+1471
-1271
No files matched your search
@@ -1,11 +1,15 @@
|
||||
import { _handleContextLayerChange } from './ui/contextLayerChanges.js';
|
||||
import { connectContextManager } from './ui/contextSubscriptions.js';
|
||||
import { _restoreContextSession, _restoreContextSessionAfterLayerSettles } from './ui/contextSession.js';
|
||||
import { _selectContextMode, _clearLayersOutsideContextMode } from './ui/contextTransactions.js';
|
||||
import { _initGlobalContextPanel } from './ui/contextBindings.js';
|
||||
import { setContextMode as contextModeAction } from './ui/contextActions.js';
|
||||
import { ContextControls } from './ui/contextControls.js';
|
||||
import { readFileSync as readRadioSource } from 'node:fs';
|
||||
const radioBindings = readRadioSource(new URL('./ui/radioBindings.js', import.meta.url), 'utf8');
|
||||
const radioPresentation = readRadioSource(new URL('./ui/radioPresentation.js', import.meta.url), 'utf8');
|
||||
const radioControlsSource = readRadioSource(new URL('./ui/radioControls.js', import.meta.url), 'utf8');
|
||||
// Source-contract pins for StyleManager's Context-session handler ordering.
|
||||
// ui.js cannot be imported headlessly (it touches the DOM at module scope), so
|
||||
// these read the shipped source — the idiom established by cockpitMarkup /
|
||||
// cameraHandoff tests. Each pin guards a bug that shipped or nearly shipped:
|
||||
// Source-contract pins read the actual Context owners and root disposal wiring. Each pin guards a bug that shipped or nearly shipped:
|
||||
// - session bookkeeping ran AFTER the exit early-return, so the compensating
|
||||
// userAdded.delete never ran on the left-panel chip exit and restoration
|
||||
// resurrected the mission layer the user just disabled;
|
||||
@@ -21,10 +25,7 @@ import { fileURLToPath } from 'node:url';
|
||||
|
||||
const src = readFileSync(fileURLToPath(new URL('./ui.js', import.meta.url)), 'utf8');
|
||||
|
||||
const handlerStart = src.indexOf('_handleContextLayerChange(change) {');
|
||||
assert.ok(handlerStart > 0, 'handler found');
|
||||
const handlerEnd = src.indexOf('_syncContextModeButtons() {', handlerStart);
|
||||
const handler = src.slice(handlerStart, handlerEnd);
|
||||
const handler = _handleContextLayerChange.toString();
|
||||
|
||||
test('context handler: session bookkeeping runs before the exit early-return', () => {
|
||||
const record = handler.indexOf('recordContextSessionUserChange(');
|
||||
@@ -56,9 +57,7 @@ test('cancelled Space Missions entry resolves ownership before settled bookkeepi
|
||||
});
|
||||
|
||||
test('direct Context entry captures on the synchronous request boundary', () => {
|
||||
const attachStart = src.indexOf('attachDataManager(dataManager) {');
|
||||
const attachEnd = src.indexOf('_syncContextModeButtons()', attachStart);
|
||||
const attach = src.slice(attachStart, attachEnd);
|
||||
const attach = connectContextManager.toString();
|
||||
assert.match(
|
||||
attach,
|
||||
/subscribeVisibilityRequests\(\(change\) => \{[\s\S]*?shouldCaptureContextSession\(change\)/,
|
||||
@@ -70,9 +69,7 @@ test('direct Context entry captures on the synchronous request boundary', () =>
|
||||
});
|
||||
|
||||
test('Clear All defers a newer explicit mission guard until its batch settles', () => {
|
||||
const attachStart = src.indexOf('attachDataManager(dataManager) {');
|
||||
const attachEnd = src.indexOf('if (typeof this._dataManager?.subscribeBeforeDestroy', attachStart);
|
||||
const attach = src.slice(attachStart, attachEnd);
|
||||
const attach = connectContextManager.toString();
|
||||
assert.match(attach, /shouldDeferContextEntryDuringClear\(\{/);
|
||||
assert.match(attach, /_contextModeDeferredEntryIntent = \{/);
|
||||
assert.match(attach, /await this\._clearSelectedLayersManagerPromise/);
|
||||
@@ -80,10 +77,7 @@ test('Clear All defers a newer explicit mission guard until its batch settles',
|
||||
});
|
||||
|
||||
test('context restore replays explicit companion intent after the stale restore queue drains', () => {
|
||||
const restore = src.slice(
|
||||
src.indexOf('async _restoreContextSession('),
|
||||
src.indexOf('async _selectContextMode('),
|
||||
);
|
||||
const restore = _restoreContextSession.toString();
|
||||
const restoreAwait = restore.indexOf('await this._dataManager.restoreEnabledLayerIds(');
|
||||
const replay = restore.indexOf('await settleContextIntentReplay(');
|
||||
assert.ok(restoreAwait > 0, 'restore queue is awaited');
|
||||
@@ -92,10 +86,7 @@ test('context restore replays explicit companion intent after the stale restore
|
||||
});
|
||||
|
||||
test('context restore settles the Contacts coordinator before dependency fanout', () => {
|
||||
const restore = src.slice(
|
||||
src.indexOf('async _restoreContextSession('),
|
||||
src.indexOf('async _selectContextMode('),
|
||||
);
|
||||
const restore = _restoreContextSession.toString();
|
||||
const settle = restore.indexOf("const contactsCoordinatorId = 'military-awareness'");
|
||||
const coordinatorOff = restore.indexOf('const coordinatorSettled = await this._dataManager.setEnabled(', settle);
|
||||
const fanout = restore.indexOf('await this._dataManager.restoreEnabledLayerIds(', settle);
|
||||
@@ -106,10 +97,7 @@ test('context restore settles the Contacts coordinator before dependency fanout'
|
||||
});
|
||||
|
||||
test('context restore preserves its exact pending target after a failed transition', () => {
|
||||
const restore = src.slice(
|
||||
src.indexOf('async _restoreContextSession('),
|
||||
src.indexOf('async _selectContextMode('),
|
||||
);
|
||||
const restore = _restoreContextSession.toString();
|
||||
assert.match(restore, /const replayError = await settleContextIntentReplay\(\{/);
|
||||
assert.match(restore, /if \(restoreError && !this\._contextSessionSnapshot\)/);
|
||||
assert.match(restore, /enabledLayerIds: new Set\(restoreState\.enabledLayerIds\)/);
|
||||
@@ -130,7 +118,7 @@ test('context handler: either failed direct Context-shell start rolls the sessio
|
||||
assert.match(failedBranch, /const failureMessage =/);
|
||||
assert.match(
|
||||
failedBranch,
|
||||
/await this\._restoreContextSessionAfterLayerSettles\([\s\S]*?this\._showToast\(failureMessage\);\s*return true;/,
|
||||
/await this\._restoreContextSessionAfterLayerSettles\([\s\S]*?this\.showToast\(failureMessage\);\s*return true;/,
|
||||
);
|
||||
assert.match(failedBranch, /\},\s*failureMessage,\s*\)\);/);
|
||||
assert.match(failedBranch, /_trackContextLayerReaction\(/);
|
||||
@@ -139,10 +127,7 @@ test('context handler: either failed direct Context-shell start rolls the sessio
|
||||
/else if \(!this\._userFacingContextNotificationTokens\.has\(change\.notificationToken\)\)/,
|
||||
);
|
||||
|
||||
const deferredRestore = src.slice(
|
||||
src.indexOf('async _restoreContextSessionAfterLayerSettles('),
|
||||
src.indexOf('async _selectContextMode('),
|
||||
);
|
||||
const deferredRestore = _restoreContextSessionAfterLayerSettles.toString();
|
||||
assert.match(deferredRestore, /await this\._dataManager\?\.waitForLayerSettled\?\.\(layerId\)/);
|
||||
assert.match(deferredRestore, /return this\._restoreContextSession\(\{ notificationToken \}\)/);
|
||||
assert.doesNotMatch(failedBranch, /excludeLayerIds/);
|
||||
@@ -157,14 +142,11 @@ test('wrapped visibility blocks leave the accessible toast to the wrapper token
|
||||
blockedBranch,
|
||||
/!this\._userFacingContextNotificationTokens\.has\(change\.notificationToken\)/,
|
||||
);
|
||||
assert.match(blockedBranch, /this\._showToast\(/);
|
||||
assert.match(blockedBranch, /this\.showToast\(/);
|
||||
});
|
||||
|
||||
test('every user-facing Context exit route settles through the failure surface', () => {
|
||||
const initPanel = src.slice(
|
||||
src.indexOf('_initGlobalContextPanel() {'),
|
||||
src.indexOf('_captureContextSessionSnapshot(', src.indexOf('_initGlobalContextPanel() {')),
|
||||
);
|
||||
const initPanel = _initGlobalContextPanel.toString();
|
||||
assert.equal((initPanel.match(/void this\._runUserFacingContextAction/g) || []).length, 3);
|
||||
assert.doesNotMatch(initPanel, /falseIsFailure:\s*false/);
|
||||
assert.doesNotMatch(initPanel, /void this\._selectContextMode/);
|
||||
@@ -198,10 +180,7 @@ test('only the expanded Radio Enable gesture requests the contained post-enable
|
||||
});
|
||||
|
||||
test('right-rail context entry is transactional: activation result gates the mode', () => {
|
||||
const select = src.slice(
|
||||
src.indexOf('async _selectContextMode('),
|
||||
src.indexOf('async _deactivateContextForLayerChange('),
|
||||
);
|
||||
const select = _selectContextMode.toString();
|
||||
const activation = select.indexOf('activationIntent = this._dataManager._setEnabledWithIntent(');
|
||||
assert.ok(activation > 0, 'activation result captured');
|
||||
const failureBlock = select.slice(activation);
|
||||
@@ -220,10 +199,7 @@ test('right-rail context entry is transactional: activation result gates the mod
|
||||
});
|
||||
|
||||
test('Context entry awaits isolation and direct shell routes isolate in the visibility guard', () => {
|
||||
const select = src.slice(
|
||||
src.indexOf('async _selectContextMode('),
|
||||
src.indexOf('async _deactivateContextForLayerChange('),
|
||||
);
|
||||
const select = _selectContextMode.toString();
|
||||
assert.match(select, /await this\._clearLayersOutsideContextMode\(mode, \{ notificationToken, signal \}\)/);
|
||||
assert.match(select, /await this\._restoreContextSession\(\{ notificationToken, signal \}\)/);
|
||||
assert.doesNotMatch(select, /void this\._clearLayersOutsideContextMode\(mode\)/);
|
||||
@@ -255,12 +231,10 @@ test('Context entry awaits isolation and direct shell routes isolate in the visi
|
||||
// invalidates in-flight Context transactions so teardown cannot be raced into
|
||||
// publishing a mode.
|
||||
const dispose = src.slice(src.indexOf(' async dispose() {'), src.indexOf('this._stampNavigation();', src.indexOf(' async dispose() {')));
|
||||
assert.match(dispose, /this\._contextModeGeneration \+= 1;/);
|
||||
assert.match(dispose, /this\._contextControls\.stop\(\)/);
|
||||
assert.match(ContextControls.prototype.stop.toString(), /this\._contextModeGeneration\+\+/);
|
||||
|
||||
const guard = src.slice(
|
||||
src.indexOf('this._dataManagerVisibilityGuardUnsubscribe = this._dataManager.addVisibilityGuard'),
|
||||
src.indexOf("if (typeof this._dataManager?.subscribeBeforeDestroy === 'function')"),
|
||||
);
|
||||
const guard = connectContextManager.toString();
|
||||
assert.match(guard, /\['military-awareness', 'rocket-launches'\]\.includes\(change\.layerId\)/);
|
||||
assert.match(guard, /const notificationToken = change\.notificationToken \|\| Symbol\('direct-context-shell-entry'\)/);
|
||||
assert.match(guard, /this\._userFacingContextNotificationTokens\.add\(notificationToken\)/);
|
||||
@@ -277,10 +251,7 @@ test('a lost cross-mode switch says Context is off, and the state agrees', () =>
|
||||
// a bare "did not complete" while the operator's Context was silently gone.
|
||||
// Text and state are derived from the same verdict so they cannot disagree,
|
||||
// and the failed layer ids survive (Manjunath's honesty requirement).
|
||||
const setter = src.slice(
|
||||
src.indexOf(' async setContextMode(mode, {'),
|
||||
src.indexOf(' getCockpitState() {'),
|
||||
);
|
||||
const setter = contextModeAction.toString();
|
||||
assert.match(setter, /const priorMode = this\._contextMode;/, 'the report knows what was lost');
|
||||
assert.match(
|
||||
setter,
|
||||
@@ -301,14 +272,10 @@ test('a lost cross-mode switch says Context is off, and the state agrees', () =>
|
||||
});
|
||||
|
||||
test('Context cancellation reaches isolation and restore lifecycle mutations', () => {
|
||||
const clearStart = src.indexOf('async _clearLayersOutsideContextMode(');
|
||||
const clear = src.slice(clearStart, src.indexOf('_handleContextLayerChange(', clearStart));
|
||||
const clear = _clearLayersOutsideContextMode.toString();
|
||||
assert.match(clear, /setEnabled\(layerId, false, \{[\s\S]*?signal/);
|
||||
|
||||
const restore = src.slice(
|
||||
src.indexOf('async _restoreContextSession('),
|
||||
src.indexOf('async _restoreContextSessionAfterLayerSettles('),
|
||||
);
|
||||
const restore = _restoreContextSession.toString();
|
||||
assert.match(restore, /restoreEnabledLayerIds\([\s\S]*?signal/);
|
||||
assert.match(restore, /setEnabled: \(layerId, enabled, options = \{\}\)[\s\S]*?signal/);
|
||||
assert.match(restore, /error\.failedLayerIds = \[contactsCoordinatorId\]/);
|
||||
@@ -319,10 +286,7 @@ test('Context cancellation reaches isolation and restore lifecycle mutations', (
|
||||
});
|
||||
|
||||
test('Context facade preserves success when cancellation arrives after commit', () => {
|
||||
const setContextMode = src.slice(
|
||||
src.indexOf('async setContextMode('),
|
||||
src.indexOf('getCockpitState()', src.indexOf('async setContextMode(')),
|
||||
);
|
||||
const setContextMode = contextModeAction.toString();
|
||||
assert.match(
|
||||
setContextMode,
|
||||
/transitioned === null \|\| \(!requestIsCurrent\(\) && transitioned !== true\)/,
|
||||
@@ -334,10 +298,7 @@ test('Context facade preserves success when cancellation arrives after commit',
|
||||
});
|
||||
|
||||
test('Context production rollback paths merge primary and restore failed-layer identities', () => {
|
||||
const select = src.slice(
|
||||
src.indexOf('async _selectContextMode('),
|
||||
src.indexOf('async _deactivateContextForLayerChange('),
|
||||
);
|
||||
const select = _selectContextMode.toString();
|
||||
assert.equal(
|
||||
(select.match(/mergeContextTransitionErrors\(transitionError, restoreError\)/g) || []).length,
|
||||
2,
|
||||
@@ -347,10 +308,7 @@ test('Context production rollback paths merge primary and restore failed-layer i
|
||||
});
|
||||
|
||||
test('stale Context cancellation preserves rollback failed-layer identities', () => {
|
||||
const setContextMode = src.slice(
|
||||
src.indexOf('async setContextMode('),
|
||||
src.indexOf('getCockpitState()', src.indexOf('async setContextMode(')),
|
||||
);
|
||||
const setContextMode = contextModeAction.toString();
|
||||
assert.match(
|
||||
setContextMode,
|
||||
/if \(!requestIsCurrent\(\)\) \{[\s\S]*?\.\.\.cancellationResult\(\),[\s\S]*?failedLayerIds: \[\.\.\.error\.failedLayerIds\]/,
|
||||
|
||||
Reference in new issue
Block a user