#!/usr/bin/env node /** Focused rendered proof for adaptive Cockpit Display/Radio layout. */ import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import puppeteer from 'puppeteer'; const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); const shotsDir = path.join(repoRoot, 'qa-shots', 'cockpit-utility'); const appUrl = process.env.QA_BASE_URL || 'http://localhost:4173'; const headful = process.argv.includes('--headful'); fs.mkdirSync(shotsDir, { recursive: true }); const chromeCandidates = [ process.env.PUPPETEER_EXECUTABLE_PATH, (() => { try { return puppeteer.executablePath(); } catch { return null; } })(), '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', ].filter(Boolean); const executablePath = chromeCandidates.find((candidate) => fs.existsSync(candidate)); const browser = await puppeteer.launch({ headless: headful ? false : 'new', ...(executablePath ? { executablePath } : {}), args: ['--use-angle=metal', '--enable-gpu', '--no-sandbox'], }); const page = await browser.newPage(); const failures = []; const consoleErrors = []; const localHttpErrors = []; page.on('console', (message) => { if (message.type() === 'error' && !/Failed to load resource.*404/i.test(message.text())) { const source = message.location()?.url; consoleErrors.push(source ? `${message.text()} [${source}]` : message.text()); } }); page.on('pageerror', (error) => consoleErrors.push(error.message)); page.on('response', (response) => { const url = new URL(response.url()); const expectedOptionalTrackMiss = response.status() === 404 && url.pathname === '/api/opensky-track'; if ( url.origin === new URL(appUrl).origin && response.status() >= 400 && !expectedOptionalTrackMiss ) { localHttpErrors.push(`${response.status()} ${url.pathname}`); } }); const check = (name, passed, detail) => { console.log(` [${passed ? 'PASS' : 'FAIL'}] ${name}${detail ? ` — ${detail}` : ''}`); if (!passed) failures.push(name); }; try { await page.setViewport({ width: 1440, height: 900, deviceScaleFactor: 1 }); await page.setRequestInterception(true); page.on('request', (request) => { const url = new URL(request.url()); if (url.origin === new URL(appUrl).origin && url.pathname === '/api/ais-live') { request.respond({ status: 200, contentType: 'application/json', body: JSON.stringify({ rows: [], source: 'AISStream QA', status: 'open', error: null, refreshing: false, newestPositionAt: null, lastMessageAt: null, }), }); return; } if (url.origin === new URL(appUrl).origin && url.pathname === '/api/adsblol/mil') { request.respond({ status: 200, contentType: 'application/json', body: JSON.stringify({ msg: 'No error', now: Date.now(), ac: [] }), }); return; } if (url.origin === new URL(appUrl).origin && url.pathname === '/api/opensky-track') { request.respond({ status: 200, contentType: 'application/json', body: JSON.stringify({ path: [] }), }); return; } if (url.origin === new URL(appUrl).origin && url.pathname === '/api/military-installations') { request.respond({ status: 200, contentType: 'application/json', body: JSON.stringify({ elements: [], saturated: false, elementCap: 1_500, retrievedAt: new Date().toISOString(), status: 'ready', }), }); return; } if (url.origin === new URL(appUrl).origin && url.pathname === '/api/openai/hud-summary') { request.respond({ status: 200, contentType: 'application/json', body: JSON.stringify({ summary: 'Cockpit utility QA' }), }); return; } request.continue(); }); await page.goto(appUrl, { waitUntil: 'domcontentloaded', timeout: 60_000 }); await page.waitForFunction(() => window.__godsEyeView?.styleManager, { timeout: 60_000 }); await page.waitForFunction( () => document.getElementById('loading-screen')?.classList.contains('hidden'), { timeout: 60_000 }, ); await page.waitForFunction(() => ( typeof window.__gevQaRegisterLayer === 'function' && typeof window.__gevQaUnregisterLayer === 'function' )); await page.evaluate(() => { const manager = window.__godsEyeView.styleManager; const hud = document.getElementById('cockpit-hud'); const signal = document.getElementById('cockpit-signal-stream'); window.__qaCockpitUtilityPrior = { cockpit: document.body.classList.contains('cockpit-mode'), active: manager.cockpitView.active, hudHidden: hud.hidden, signalHidden: signal.hidden, hudVisible: manager.hud.visible, hudVariant: manager.hud.getVariant(), utilityTop: hud.style.getPropertyValue('--cockpit-utility-top'), }; }); const contactMissionHandoff = await page.evaluate(async () => { const { styleManager, dataManager } = window.__godsEyeView; const originalShowToast = styleManager._showToast; const toasts = []; styleManager._showToast = (message) => { toasts.push(String(message)); }; try { if (styleManager._contextMode) await styleManager._selectContextMode(null); const contactsResult = await styleManager._selectContextMode('flights'); const missionResult = await styleManager._selectContextMode('space-missions'); const switched = { contactsResult, missionResult, mode: styleManager._contextMode, missionsEnabled: dataManager.isEnabled('rocket-launches'), toasts: [...toasts], }; const exitResult = await styleManager._selectContextMode(null); return { ...switched, exitResult, modeAfterExit: styleManager._contextMode, missionsOffAfterExit: !dataManager.isEffectivelyEnabled('rocket-launches'), }; } finally { styleManager._showToast = originalShowToast; } }); check( 'Contacts hands off to Space Missions on the first request without a failure toast', contactMissionHandoff.contactsResult === true && contactMissionHandoff.missionResult === true && contactMissionHandoff.mode === 'space-missions' && contactMissionHandoff.missionsEnabled && contactMissionHandoff.toasts?.length === 0 && contactMissionHandoff.exitResult === true && contactMissionHandoff.modeAfterExit === null && contactMissionHandoff.missionsOffAfterExit, JSON.stringify(contactMissionHandoff), ); const cancelledMissionEntry = await page.evaluate(async () => { const styleManager = window.__godsEyeView.styleManager; const dataManager = window.__godsEyeView.dataManager; const rocketEntry = dataManager.layers.get('rocket-launches'); if (!rocketEntry || dataManager.isEffectivelyEnabled('rocket-launches')) { return { exercised: false, reason: 'Space Missions was not in a clean OFF state' }; } const siblingId = 'qa-cockpit-cancel-sibling'; const siblingModule = { id: siblingId, name: 'QA cancellation sibling', icon: 'science', source: 'QA', updateInterval: -1, async init() { return true; }, async enable() { return true; }, async update() { return true; }, async disable() { return true; }, async destroy() {}, getStats() { return { count: 1, status: 'live' }; }, }; window.__gevQaRegisterLayer(dataManager, siblingModule); await dataManager.setEnabled(siblingId, true, { origin: 'programmatic' }); const originalInitialized = rocketEntry.initialized; const originalLifecycle = rocketEntry.lifecycleState; const originalMethods = { init: rocketEntry.module.init, enable: rocketEntry.module.enable, update: rocketEntry.module.update, disable: rocketEntry.module.disable, }; const originalShowToast = styleManager._showToast; const toasts = []; let releaseEnable; let markEnableStarted; const enableStarted = new Promise((resolve) => { markEnableStarted = resolve; }); const enableGate = new Promise((resolve) => { releaseEnable = resolve; }); rocketEntry.initialized = true; rocketEntry.module.enable = async () => { markEnableStarted(); await enableGate; return true; }; rocketEntry.module.update = async () => true; rocketEntry.module.disable = async () => true; styleManager._showToast = (message) => { toasts.push(String(message)); }; let transitionResult = null; let timedOut = false; try { const controller = new AbortController(); const transition = dataManager.setEnabled('rocket-launches', true, { origin: 'user', signal: controller.signal, }); await enableStarted; controller.abort(new DOMException('QA caller cancellation', 'AbortError')); releaseEnable(); transitionResult = await transition; const deadline = performance.now() + 5_000; while (performance.now() < deadline) { if ( styleManager._contextModeEntering === null && styleManager._contextSessionSnapshot === null && dataManager.isEnabled(siblingId) && !dataManager.isEffectivelyEnabled('rocket-launches') ) break; await new Promise((resolve) => setTimeout(resolve, 20)); } timedOut = !( styleManager._contextModeEntering === null && styleManager._contextSessionSnapshot === null && dataManager.isEnabled(siblingId) && !dataManager.isEffectivelyEnabled('rocket-launches') ); return { exercised: true, transitionResult, timedOut, entering: styleManager._contextModeEntering, snapshotRetained: Boolean(styleManager._contextSessionSnapshot), siblingRestored: dataManager.isEnabled(siblingId), missionEffective: dataManager.isEffectivelyEnabled('rocket-launches'), toasts, }; } finally { styleManager._showToast = originalShowToast; rocketEntry.module.init = originalMethods.init; rocketEntry.module.enable = originalMethods.enable; rocketEntry.module.update = originalMethods.update; rocketEntry.module.disable = originalMethods.disable; rocketEntry.initialized = originalInitialized; rocketEntry.lifecycleState = originalLifecycle; await dataManager.setEnabled(siblingId, false, { origin: 'programmatic' }); await window.__gevQaUnregisterLayer(dataManager, siblingId); } }); check( 'cancelled direct Space Missions entry restores its exact isolated sibling state', cancelledMissionEntry.exercised && cancelledMissionEntry.transitionResult === false && !cancelledMissionEntry.timedOut && cancelledMissionEntry.entering === null && !cancelledMissionEntry.snapshotRetained && cancelledMissionEntry.siblingRestored && !cancelledMissionEntry.missionEffective, JSON.stringify(cancelledMissionEntry), ); check( 'successful Space Missions cancellation rollback stays silent', cancelledMissionEntry.exercised && cancelledMissionEntry.toasts?.length === 0, JSON.stringify(cancelledMissionEntry.toasts || []), ); const replacementMissionEntry = await page.evaluate(async () => { const styleManager = window.__godsEyeView.styleManager; const dataManager = window.__godsEyeView.dataManager; const rocketEntry = dataManager.layers.get('rocket-launches'); if (!rocketEntry || dataManager.isEffectivelyEnabled('rocket-launches')) { return { exercised: false, reason: 'Space Missions was not in a clean OFF state' }; } const siblingId = 'qa-cockpit-replacement-sibling'; window.__gevQaRegisterLayer(dataManager, { id: siblingId, name: 'QA replacement sibling', icon: 'science', source: 'QA', updateInterval: -1, async init() { return true; }, async enable() { return true; }, async update() { return true; }, async disable() { return true; }, async destroy() {}, getStats() { return { count: 1, status: 'live' }; }, }); await dataManager.setEnabled(siblingId, true, { origin: 'programmatic' }); const original = { siblingInitialized: dataManager.layers.get(siblingId)?.initialized, initialized: rocketEntry.initialized, lifecycleState: rocketEntry.lifecycleState, init: rocketEntry.module.init, enable: rocketEntry.module.enable, update: rocketEntry.module.update, disable: rocketEntry.module.disable, showToast: styleManager._showToast, }; let firstUpdate = true; let releaseUpdate; let markUpdateStarted; const updateStarted = new Promise((resolve) => { markUpdateStarted = resolve; }); const updateGate = new Promise((resolve) => { releaseUpdate = resolve; }); const toasts = []; rocketEntry.initialized = true; rocketEntry.module.enable = async () => true; rocketEntry.module.update = async () => { if (!firstUpdate) return true; firstUpdate = false; markUpdateStarted(); await updateGate; return true; }; rocketEntry.module.disable = async () => true; styleManager._showToast = (message) => { toasts.push(String(message)); }; try { const entry = styleManager._selectContextMode('space-missions'); await updateStarted; const replacement = dataManager.setEnabled('rocket-launches', true, { origin: 'programmatic' }); releaseUpdate(); const [entryResult, replacementResult] = await Promise.all([entry, replacement]); const committed = { entryResult, replacementResult, mode: styleManager._contextMode, entering: styleManager._contextModeEntering, snapshotRetained: Boolean(styleManager._contextSessionSnapshot), siblingIsolated: !dataManager.isEffectivelyEnabled(siblingId), missionEnabled: dataManager.isEnabled('rocket-launches'), missionEffective: dataManager.isEffectivelyEnabled('rocket-launches'), toasts: [...toasts], }; const exitResult = await styleManager._selectContextMode(null); return { exercised: true, ...committed, exitResult, siblingRestored: dataManager.isEnabled(siblingId), missionRestoredOff: !dataManager.isEffectivelyEnabled('rocket-launches'), }; } finally { styleManager._showToast = original.showToast; rocketEntry.module.init = original.init; rocketEntry.module.enable = original.enable; rocketEntry.module.update = original.update; rocketEntry.module.disable = original.disable; rocketEntry.initialized = original.initialized; rocketEntry.lifecycleState = original.lifecycleState; await dataManager.setEnabled(siblingId, false, { origin: 'programmatic' }); await window.__gevQaUnregisterLayer(dataManager, siblingId); } }); check( 'right-rail Space Missions adopts a newer authoritative ON without stale restoration', replacementMissionEntry.exercised && replacementMissionEntry.entryResult === true && replacementMissionEntry.replacementResult === true && replacementMissionEntry.mode === 'space-missions' && replacementMissionEntry.entering === null && replacementMissionEntry.snapshotRetained && replacementMissionEntry.siblingIsolated && replacementMissionEntry.missionEnabled && replacementMissionEntry.missionEffective && replacementMissionEntry.toasts?.length === 0 && replacementMissionEntry.exitResult === true && replacementMissionEntry.siblingRestored && replacementMissionEntry.missionRestoredOff, JSON.stringify(replacementMissionEntry), ); const supersededMissionEntry = await page.evaluate(async () => { const styleManager = window.__godsEyeView.styleManager; const dataManager = window.__godsEyeView.dataManager; const rocketEntry = dataManager.layers.get('rocket-launches'); if (!rocketEntry || dataManager.isEffectivelyEnabled('rocket-launches')) { return { exercised: false, reason: 'Space Missions was not in a clean OFF state' }; } const siblingId = 'qa-cockpit-superseded-sibling'; window.__gevQaRegisterLayer(dataManager, { id: siblingId, name: 'QA superseded sibling', icon: 'science', source: 'QA', updateInterval: -1, async init() { return true; }, async enable() { return true; }, async update() { return true; }, async disable() { return true; }, async destroy() {}, getStats() { return { count: 1, status: 'live' }; }, }); await dataManager.setEnabled(siblingId, true, { origin: 'programmatic' }); const original = { initialized: rocketEntry.initialized, lifecycleState: rocketEntry.lifecycleState, init: rocketEntry.module.init, enable: rocketEntry.module.enable, update: rocketEntry.module.update, disable: rocketEntry.module.disable, showToast: styleManager._showToast, }; let releaseUpdate; let markUpdateStarted; const updateStarted = new Promise((resolve) => { markUpdateStarted = resolve; }); const updateGate = new Promise((resolve) => { releaseUpdate = resolve; }); const toasts = []; rocketEntry.initialized = true; rocketEntry.module.enable = async () => true; rocketEntry.module.update = async () => { markUpdateStarted(); await updateGate; return true; }; rocketEntry.module.disable = async () => true; styleManager._showToast = (message) => { toasts.push(String(message)); }; try { const entry = styleManager._runUserFacingContextAction( (notificationToken) => styleManager._selectContextMode( 'space-missions', { notificationToken }, ), 'Space Missions could not complete the requested transition; try again', ); await updateStarted; const supersedingOff = dataManager.setEnabled('rocket-launches', false, { origin: 'programmatic', }); releaseUpdate(); const [entryResult, offResult] = await Promise.all([entry, supersedingOff]); return { exercised: true, entryResult, offResult, mode: styleManager._contextMode, entering: styleManager._contextModeEntering, snapshotRetained: Boolean(styleManager._contextSessionSnapshot), siblingRestored: dataManager.isEnabled(siblingId), missionEffective: dataManager.isEffectivelyEnabled('rocket-launches'), toasts, }; } finally { styleManager._showToast = original.showToast; rocketEntry.module.init = original.init; rocketEntry.module.enable = original.enable; rocketEntry.module.update = original.update; rocketEntry.module.disable = original.disable; rocketEntry.initialized = original.initialized; rocketEntry.lifecycleState = original.lifecycleState; await dataManager.setEnabled(siblingId, false, { origin: 'programmatic' }); await window.__gevQaUnregisterLayer(dataManager, siblingId); } }); check( 'right-rail Space Missions superseded by OFF restores exactly without a failure toast', supersededMissionEntry.exercised && supersededMissionEntry.entryResult === null && supersededMissionEntry.mode === null && supersededMissionEntry.entering === null && !supersededMissionEntry.snapshotRetained && supersededMissionEntry.siblingRestored && !supersededMissionEntry.missionEffective && supersededMissionEntry.toasts?.length === 0, JSON.stringify(supersededMissionEntry), ); const voiceMissionEntry = await page.evaluate(async () => { const { dataManager, styleManager } = window.__godsEyeView; const siblingId = '__qa_voice_context_sibling__'; const rocketEntry = dataManager.layers.get('rocket-launches'); window.__gevQaRegisterLayer(dataManager, { id: siblingId, name: 'QA voice Context sibling', icon: 'science', source: 'QA', updateInterval: -1, async init() { return true; }, async enable() { return true; }, async update() { return true; }, async disable() { return true; }, async destroy() {}, getStats() { return { count: 1, status: 'live' }; }, }); const original = { initialized: rocketEntry.initialized, lifecycleState: rocketEntry.lifecycleState, init: rocketEntry.module.init, enable: rocketEntry.module.enable, update: rocketEntry.module.update, disable: rocketEntry.module.disable, }; const siblingLayerEntry = dataManager.layers.get(siblingId); siblingLayerEntry.initialized = true; await dataManager.setEnabled(siblingId, true, { origin: 'programmatic' }); rocketEntry.initialized = true; rocketEntry.module.init = async () => true; rocketEntry.module.enable = async () => true; rocketEntry.module.update = async () => true; rocketEntry.module.disable = async () => true; try { const voiceOn = await dataManager.setEnabled('rocket-launches', true, { origin: 'voice' }); await new Promise((resolve) => setTimeout(resolve, 80)); const voiceState = { voiceOn, mode: styleManager._contextMode, entering: styleManager._contextModeEntering, snapshotRetained: Boolean(styleManager._contextSessionSnapshot), siblingIsolated: !dataManager.isEffectivelyEnabled(siblingId), }; const snapshotBeforeOff = [...(styleManager._contextSessionSnapshot?.enabledLayerIds || [])]; const voiceOff = await dataManager.setEnabled('rocket-launches', false, { origin: 'voice' }); const reactionCountAfterOff = styleManager._contextLayerReactionPromises.size; await styleManager._waitForContextLayerSettlement(); const restoredSiblingEntry = dataManager.layers.get(siblingId); const voiceExit = { voiceOff, snapshotBeforeOff, reactionCountAfterOff, mode: styleManager._contextMode, entering: styleManager._contextModeEntering, snapshotRetained: Boolean(styleManager._contextSessionSnapshot), siblingRestored: dataManager.isEffectivelyEnabled(siblingId), siblingEnabled: restoredSiblingEntry?.enabled, siblingLifecycle: restoredSiblingEntry?.lifecycleState, restoreActive: Boolean(styleManager._contextRestoreState), }; await dataManager.setEnabled('rocket-launches', true, { origin: 'programmatic' }); await new Promise((resolve) => setTimeout(resolve, 40)); const internalState = { mode: styleManager._contextMode, entering: styleManager._contextModeEntering, snapshotRetained: Boolean(styleManager._contextSessionSnapshot), missionEnabled: dataManager.isEffectivelyEnabled('rocket-launches'), }; await dataManager.setEnabled('rocket-launches', false, { origin: 'programmatic' }); return { exercised: true, voiceState, voiceExit, internalState }; } finally { rocketEntry.module.init = original.init; rocketEntry.module.enable = original.enable; rocketEntry.module.update = original.update; rocketEntry.module.disable = original.disable; rocketEntry.initialized = original.initialized; rocketEntry.lifecycleState = original.lifecycleState; await dataManager.setEnabled(siblingId, false, { origin: 'programmatic' }); siblingLayerEntry.initialized = original.siblingInitialized; await window.__gevQaUnregisterLayer(dataManager, siblingId); } }); check( 'voice Space Missions uses the same Context snapshot and exact-restore transaction as UI entry', voiceMissionEntry.exercised && voiceMissionEntry.voiceState?.voiceOn && voiceMissionEntry.voiceState.mode === 'space-missions' && voiceMissionEntry.voiceState.entering === null && voiceMissionEntry.voiceState.snapshotRetained && voiceMissionEntry.voiceState.siblingIsolated && voiceMissionEntry.voiceExit?.voiceOff && voiceMissionEntry.voiceExit.mode === null && voiceMissionEntry.voiceExit.entering === null && !voiceMissionEntry.voiceExit.snapshotRetained && voiceMissionEntry.voiceExit.siblingRestored, JSON.stringify(voiceMissionEntry), ); check( 'internal programmatic Space Missions activation does not create a user Context session', voiceMissionEntry.internalState?.missionEnabled && voiceMissionEntry.internalState.mode === null && voiceMissionEntry.internalState.entering === null && !voiceMissionEntry.internalState.snapshotRetained, JSON.stringify(voiceMissionEntry), ); await page.evaluate(() => window.__godsEyeView.dataManager.setEnabled( 'flights', true, { origin: 'user' }, )); await page.waitForFunction(() => { const layer = window.__godsEyeView?.dataManager?.layers?.get('flights')?.module; return (layer?.getAllPositions?.(500) || []).some( (candidate) => Number(candidate.altitudeM) > 1_000, ); }, { timeout: 60_000 }); const tracked = await page.evaluate(() => { const layer = window.__godsEyeView.dataManager.layers.get('flights')?.module; const candidates = layer?.getAllPositions?.(500) || []; const airborne = candidates.find((candidate) => Number(candidate.altitudeM) > 1_000); return { id: airborne?.id || null, tracked: Boolean(airborne && layer.trackById?.(airborne.id)), }; }); check('real airborne flight is tracked before Contacts activation', tracked.tracked, JSON.stringify(tracked)); await page.waitForFunction( () => Boolean(window.__godsEyeView.viewer.trackedEntity?.position), { timeout: 10_000 }, ); const preselectedContactAdoption = await page.evaluate(async () => { const { styleManager, dataManager, viewer } = window.__godsEyeView; const flights = dataManager.layers.get('flights')?.module; await dataManager.setEnabled('military', true, { origin: 'programmatic' }); const before = flights?.getTrackedInfo?.() || null; const trackedEntityBefore = viewer.trackedEntity; const blockerId = '__qa_slow_contacts_sibling__'; const gateTimeoutMs = 5_000; // The transition settles behind real dependency enables (network-bound), so its // guard matches the harness's other network waits — a hang stop, not a budget. const settleTimeoutMs = 60_000; let releaseDisable = () => {}; let reportDisableStarted = () => {}; const disableGate = new Promise((resolve) => { releaseDisable = resolve; }); const disableStarted = new Promise((resolve) => { reportDisableStarted = resolve; }); // Every await in this probe is bounded: the gated sibling teardown is the // behaviour under test, so a no-show has to fail the check with evidence // rather than hang the whole harness on an unresolved promise. const settleWithin = (promise, ms) => Promise.race([ promise.then( (value) => ({ settled: true, value }), (error) => ({ settled: true, value: `error: ${String(error?.message || error)}` }), ), new Promise((resolve) => { setTimeout(() => resolve({ settled: false, value: null }), ms); }), ]); window.__gevQaRegisterLayer(dataManager, { id: blockerId, name: 'QA slow Contacts sibling', icon: 'science', source: 'QA', updateInterval: -1, async init() { return true; }, async enable() { return true; }, async update() { return true; }, async disable() { reportDisableStarted(); await disableGate; return true; }, async destroy() {}, getStats() { return { count: 1, status: 'live' }; }, }); let deferCleanup = false; try { const blockerEntry = dataManager.layers.get(blockerId); blockerEntry.initialized = true; await dataManager.setEnabled(blockerId, true, { origin: 'programmatic' }); const transition = styleManager._selectContextMode('flights'); const disableStart = await settleWithin(disableStarted, gateTimeoutMs); if (!disableStart.settled) { releaseDisable(); const abandoned = await settleWithin(transition, settleTimeoutMs); return { disableObserved: false, beforeId: before?.icao24 || null, timeoutReason: `QA blocker disable() never started within ${gateTimeoutMs}ms — ` + 'the Contacts transition never tore its sibling down, so the pending-window ' + 'probe could not be exercised', transitionSettled: abandoned.settled, transitionResult: abandoned.value, }; } styleManager.cockpitView.syncEntry(); const entry = document.getElementById('cockpit-entry'); const pending = { changing: styleManager._contextModeChanging, entryHidden: Boolean(entry?.hidden), enterResult: styleManager.cockpitView.enter(), trackerPreserved: viewer.trackedEntity === trackedEntityBefore, }; releaseDisable(); const settleStartedAt = performance.now(); const settledTransition = await settleWithin(transition, settleTimeoutMs); const settleMs = Math.round(performance.now() - settleStartedAt); styleManager.cockpitView.syncEntry(); const awareness = dataManager.layers.get('military-awareness')?.module; const snapshot = awareness?.getContextSnapshot?.() || null; const trackedInfo = flights?.getTrackedInfo?.() || null; deferCleanup = true; return { disableObserved: true, beforeId: before?.icao24 || null, pending, transitionSettled: settledTransition.settled, transitionResult: settledTransition.value, settleMs, subject: snapshot?.subject ? { layerId: snapshot.subject.layerId, id: snapshot.subject.id, } : null, navigation: snapshot?.navigation || null, afterId: trackedInfo?.icao24 || null, viewerTrackedId: viewer.trackedEntity?.gevTrackedId || null, contextVisible: !document.getElementById('military-awareness-panel')?.hidden, entryAvailableAfterSettlement: Boolean(entry && !entry.hidden), blockerStillRegistered: dataManager.layers.has(blockerId), blockerEffectivelyOff: !dataManager.isEffectivelyEnabled(blockerId), }; } finally { // Never leave the injected layer (or a gated disable) behind — a failed // probe must not poison the checks that run after it. releaseDisable(); if (!deferCleanup && dataManager.layers.has(blockerId)) { if (styleManager._contextSessionSnapshot) await styleManager._selectContextMode(null); await window.__gevQaUnregisterLayer(dataManager, blockerId); styleManager.cockpitView.syncEntry(); } } }); check( 'Contacts blocks early Cockpit entry, then adopts the already tracked flight after settlement', preselectedContactAdoption.disableObserved && preselectedContactAdoption.transitionSettled && preselectedContactAdoption.beforeId && preselectedContactAdoption.pending?.changing && preselectedContactAdoption.pending.entryHidden && preselectedContactAdoption.pending.enterResult === false && preselectedContactAdoption.pending.trackerPreserved && preselectedContactAdoption.transitionResult === true && preselectedContactAdoption.subject?.layerId === 'flights' && String(preselectedContactAdoption.subject.id).toLowerCase() === String(preselectedContactAdoption.beforeId).toLowerCase() && String(preselectedContactAdoption.afterId).toLowerCase() === String(preselectedContactAdoption.beforeId).toLowerCase() && String(preselectedContactAdoption.viewerTrackedId).toLowerCase() === `flights:${String(preselectedContactAdoption.beforeId).toLowerCase()}` && preselectedContactAdoption.navigation?.canPrevious === false && typeof preselectedContactAdoption.navigation?.canNext === 'boolean' && preselectedContactAdoption.contextVisible && preselectedContactAdoption.entryAvailableAfterSettlement && preselectedContactAdoption.blockerStillRegistered && preselectedContactAdoption.blockerEffectivelyOff, JSON.stringify(preselectedContactAdoption), ); // The slow thing in the field is the FETCH, so that is what this holds — the // REAL militaryInstallations module runs throughout and reports its own // getStats(). An earlier cut stubbed `enable` and `getStats` instead. Both // were wrong, and provably so: // * `enable()` is SYNCHRONOUS in production (the module's own comment says // "DataLayerManager invokes update() immediately after enable(), which // owns the first fetch"), so gating it blocked the Contacts activation // that brings the PANEL up. The scenario then sampled markup an earlier // scenario had left behind, which is why it read a stale `0`. // * The panel does not observe a `getStats` stub in this scenario at all — // verified by making the stub report an ANSWERED source mid-window and // watching every assertion stay green. A check written against a stub the // panel cannot see has no teeth, which is the same defect this scenario // was created to fix. // Holding the network reproduces the field exactly and the panel tracks it, // which is what gives these assertions teeth. const deferredInstallationReadiness = await page.evaluate(async () => { const { styleManager, dataManager } = window.__godsEyeView; const entry = dataManager.layers.get('military-installations'); if (!entry?.module) return { exercised: false, reason: 'military-installations missing' }; const settleWithin = (promise, ms) => Promise.race([ promise.then( (value) => ({ settled: true, value }), (error) => ({ settled: true, value: `error: ${String(error?.message || error)}` }), ), new Promise((resolve) => { setTimeout(() => resolve({ settled: false, value: null }), ms); }), ]); const row = () => [...document.querySelectorAll('#military-awareness-panel .military-awareness-row')] .find((candidate) => candidate.querySelector('strong')?.textContent?.trim() === 'Mapped installations'); const installationCount = () => row()?.querySelector('b')?.textContent?.trim() || null; /** The REASON text, which is what tracks availability: the cohort engine * answers 'feed unavailable' / 'feed stale' when it refuses to count. */ const installationReason = () => row()?.querySelector('small')?.textContent?.trim() || null; const realFetch = window.fetch; let released = false; let requestSeen = false; let transition = null; try { await styleManager._selectContextMode(null); await dataManager.setEnabled('military-installations', false, { origin: 'programmatic' }); // Hold the first Overpass request open, honouring the module's own // AbortSignal so its camera-settle abort/refetch behaves as it does live. window.fetch = (input, init) => { const raw = typeof input === 'string' || input instanceof URL ? String(input) : input?.url; let url = null; try { url = new URL(raw, window.location.href); } catch { return realFetch(input, init); } if (url.pathname !== '/api/military-installations') return realFetch(input, init); requestSeen = true; const signal = init?.signal; return new Promise((resolve, reject) => { let done = false; const fail = () => { if (done) return; done = true; const error = new Error('aborted'); error.name = 'AbortError'; reject(error); }; if (signal) { if (signal.aborted) return fail(); signal.addEventListener('abort', fail, { once: true }); } const tick = () => { if (done) return; if (released) { done = true; resolve(new Response( JSON.stringify({ elements: [], retrievedAt: new Date().toISOString() }), { status: 200, headers: { 'Content-Type': 'application/json' } }, )); return; } setTimeout(tick, 100); }; tick(); }); }; transition = styleManager._selectContextMode('flights'); // The activation promise stays PENDING while the first fetch is out, and // the Contacts panel comes up behind it — that is what a deferred // dependency is for. Verified live on :4272: the panel renders and reads // a non-numeric count for the whole of a 17 s first fetch. const started = await settleWithin((async () => { for (let i = 0; i < 100 && !(requestSeen && row()); i++) { await new Promise((resolve) => setTimeout(resolve, 100)); } return requestSeen && Boolean(row()); })(), 12_000); styleManager.cockpitView.syncEntry(); const pendingLifecycle = dataManager.getLayerLifecycleState('military-installations'); const pendingCount = installationCount(); const pendingReason = installationReason(); // THE WINDOW: first request outstanding, panel live. Sampled more than // once — the field report was a panel sitting on a fabricated 0 for ~13 s, // so a single lucky read is not evidence. const fetchingCounts = []; const fetchingReasons = []; for (let i = 0; i < 6; i++) { fetchingCounts.push(installationCount()); fetchingReasons.push(installationReason()); await new Promise((resolve) => setTimeout(resolve, 250)); } released = true; const contacts = await settleWithin(transition, 20_000); styleManager.cockpitView.syncEntry(); // Measured AFTER activation settles, not during it. The sibling pin above // ("Contacts blocks early Cockpit entry, then adopts the already tracked // flight after settlement") establishes that Contacts HIDES the entry // while the transition is changing — that is the designed contract, and // asserting the opposite (as this scenario used to) could never pass. // What matters is that a slow dependency does not lock it away for good. const cockpitAvailableAfterActivation = !document.getElementById('cockpit-entry')?.hidden; const installed = await settleWithin((async () => { while (dataManager.getLayerLifecycleState('military-installations')?.lifecycleState !== 'enabled') { await new Promise((resolve) => setTimeout(resolve, 50)); } await new Promise((resolve) => setTimeout(resolve, 200)); return true; })(), 20_000); const answered = await settleWithin((async () => { for (let i = 0; i < 60 && !/^\d+$/.test(String(installationCount())); i++) { await new Promise((resolve) => setTimeout(resolve, 150)); } return true; })(), 12_000); return { exercised: true, started, contacts, pendingLifecycle, pendingCount, pendingReason, cockpitAvailableAfterActivation, installed, settledLifecycle: dataManager.getLayerLifecycleState('military-installations'), fetchingCounts, fetchingReasons, answered, settledCount: installationCount(), settledReason: installationReason(), }; } finally { released = true; window.fetch = realFetch; if (transition) await settleWithin(transition, 20_000); if (styleManager._contextMode !== 'flights') { await settleWithin(styleManager._selectContextMode('flights'), 15_000); } } }); // The panel has two truthful ways to say "nothing has answered yet" — the // cohort count renders `?`, and an UNKNOWN relationship renders as that word. // Which one is on screen depends on which panel surface is mounted, and the // property under test is not the token: it is that the operator is NEVER // shown a fabricated NUMBER for a source that has not answered. So these // assert numeric-vs-not, which is exactly the field report. const readsUnknown = (value) => typeof value === 'string' && value.length > 0 && !/^\d/.test(value); const readsNumber = (value) => typeof value === 'string' && /^\d+$/.test(value); check( 'mapped installations load behind Contacts without a false all-clear or a locked Cockpit', deferredInstallationReadiness.exercised && deferredInstallationReadiness.started?.settled && deferredInstallationReadiness.contacts?.settled && deferredInstallationReadiness.contacts.value === true && deferredInstallationReadiness.pendingLifecycle?.lifecycleState === 'enabling' && readsUnknown(deferredInstallationReadiness.pendingCount) && /unavailable|stale/i.test(String(deferredInstallationReadiness.pendingReason)) && deferredInstallationReadiness.cockpitAvailableAfterActivation && deferredInstallationReadiness.installed?.settled, JSON.stringify(deferredInstallationReadiness), ); check( 'installations still fetching behind a live Contacts panel never reads a number', deferredInstallationReadiness.exercised && deferredInstallationReadiness.pendingLifecycle?.lifecycleState === 'enabling' && Array.isArray(deferredInstallationReadiness.fetchingCounts) && deferredInstallationReadiness.fetchingCounts.length > 0 && deferredInstallationReadiness.fetchingCounts.every(readsUnknown) && Array.isArray(deferredInstallationReadiness.fetchingReasons) && deferredInstallationReadiness.fetchingReasons.every((r) => /unavailable|stale/i.test(String(r))), JSON.stringify({ settledLifecycle: deferredInstallationReadiness.settledLifecycle, fetchingCounts: deferredInstallationReadiness.fetchingCounts, }), ); check( 'the mapped-installations count appears once the first fetch actually answers', deferredInstallationReadiness.exercised && deferredInstallationReadiness.answered?.settled && readsNumber(deferredInstallationReadiness.settledCount) && !/unavailable|stale/i.test(String(deferredInstallationReadiness.settledReason)), JSON.stringify({ answered: deferredInstallationReadiness.answered, settledCount: deferredInstallationReadiness.settledCount, }), ); const locationContactHandoff = await page.evaluate(async () => { const { styleManager, dataManager, viewer } = window.__godsEyeView; const awareness = dataManager.layers.get('military-awareness')?.module; const before = awareness?.getContextSnapshot?.()?.subject || null; document.querySelector('#location-pills .location-pill')?.click(); await new Promise((resolve) => setTimeout(resolve, 3600)); const after = awareness?.getContextSnapshot?.()?.subject || null; const released = !viewer.trackedEntity; const refocused = awareness?.focusCurrent?.() === true; await new Promise((resolve) => setTimeout(resolve, 120)); const owningLayer = after?.layerId === 'militaryFlights' ? 'military-flights' : after?.layerId; const trackedInfo = dataManager.layers.get(owningLayer)?.module?.getTrackedInfo?.() || null; return { before: before ? { layerId: before.layerId, id: before.id } : null, after: after ? { layerId: after.layerId, id: after.id } : null, mode: styleManager._contextMode, released, refocused, trackedId: trackedInfo?.icao24 || trackedInfo?.id || null, }; }); check( 'Location moves independently while Contact selection persists and Focus restores it', locationContactHandoff.before?.id && locationContactHandoff.after?.id === locationContactHandoff.before.id && locationContactHandoff.after?.layerId === locationContactHandoff.before.layerId && locationContactHandoff.mode === 'flights' && locationContactHandoff.released && locationContactHandoff.refocused && String(locationContactHandoff.trackedId).toLowerCase() === String(locationContactHandoff.before.id).toLowerCase(), JSON.stringify(locationContactHandoff), ); const zoomedOutContactRefocus = await page.evaluate(async () => { const { dataManager, viewer } = window.__godsEyeView; const awareness = dataManager.layers.get('military-awareness')?.module; const before = awareness?.getContextSnapshot?.()?.subject || null; const entityBefore = viewer.trackedEntity; viewer.camera.zoomOut(1_500_000); const cameraRange = () => Math.hypot( viewer.camera.position.x, viewer.camera.position.y, viewer.camera.position.z, ); const zoomedRange = cameraRange(); const refocused = awareness?.focusCurrent?.() === true; await new Promise((resolve) => setTimeout(resolve, 180)); const focusedRange = cameraRange(); const after = awareness?.getContextSnapshot?.()?.subject || null; return { before: before ? { layerId: before.layerId, id: before.id } : null, after: after ? { layerId: after.layerId, id: after.id } : null, sameEntity: viewer.trackedEntity === entityBefore, refocused, zoomedRange: Math.round(zoomedRange), focusedRange: Math.round(focusedRange), }; }); check( 'Contact Focus restores the canonical follow frame after a manual zoom-out', zoomedOutContactRefocus.before?.id && zoomedOutContactRefocus.after?.id === zoomedOutContactRefocus.before.id && zoomedOutContactRefocus.after?.layerId === zoomedOutContactRefocus.before.layerId && zoomedOutContactRefocus.sameEntity && zoomedOutContactRefocus.refocused && zoomedOutContactRefocus.zoomedRange > 1_000_000 && zoomedOutContactRefocus.focusedRange < 50_000, JSON.stringify(zoomedOutContactRefocus), ); await page.waitForFunction(() => { const entry = document.getElementById('cockpit-entry'); return entry && !entry.hidden && !entry.disabled; }, { timeout: 10_000 }); await page.$eval('#cockpit-entry', (entry) => entry.click()); await page.waitForFunction( () => document.body.classList.contains('cockpit-mode') && window.__godsEyeView.styleManager.cockpitView.active && !document.getElementById('cockpit-hud').hidden, { timeout: 10_000 }, ); await page.waitForFunction( () => { // Require the node: `!missing?.hidden` is vacuously true, so a dropped // #cockpit-context would sail past this gate instead of failing here. const context = document.getElementById('cockpit-context'); return Boolean(context) && !context.hidden; }, { timeout: 10_000 }, ); const firstCockpitContact = await page.evaluate(() => { const awareness = window.__godsEyeView.dataManager.layers .get('military-awareness')?.module; const snapshot = awareness?.getContextSnapshot?.() || null; const context = document.getElementById('cockpit-context'); const subjectText = document.getElementById('cockpit-context-subject')?.textContent || ''; const previous = document.getElementById('cockpit-context-previous'); const next = document.getElementById('cockpit-context-next'); const signalText = document.getElementById('cockpit-signal-list')?.textContent || ''; return { subject: snapshot?.subject ? { layerId: snapshot.subject.layerId, id: snapshot.subject.id, label: snapshot.subject.label, } : null, contextVisible: Boolean(context && !context.hidden && getComputedStyle(context).display !== 'none'), subjectText, previousDisabled: previous?.disabled, nextDisabled: next?.disabled, navigation: snapshot?.navigation || null, contextStandby: signalText.includes('CONTEXT STANDBY'), }; }); check( 'first Cockpit entry shows matching Contact Previous/Next controls', firstCockpitContact.contextVisible && firstCockpitContact.subject?.layerId === 'flights' && String(firstCockpitContact.subject.id).toLowerCase() === String(tracked.id).toLowerCase() && firstCockpitContact.subjectText.startsWith( `${firstCockpitContact.subject.label} ·`, ) && firstCockpitContact.previousDisabled === !firstCockpitContact.navigation?.canPrevious && firstCockpitContact.nextDisabled === !firstCockpitContact.navigation?.canNext && !firstCockpitContact.contextStandby, JSON.stringify(firstCockpitContact), ); // Owner playtest 2026-08-18: "when you click on Contacts, detections should // just turn on, and they should stay on in Cockpit or in third-person // tracking inside Contacts or inside Cockpit, both… when I leave the Cockpit, // detections go off" — that last part being the bug. Driven through the REAL // context-mode transaction and the REAL CockpitViewController with a live // tracked flight: the one path a Node unit test cannot boot. const contactsDetection = await page.evaluate(async () => { const { styleManager } = window.__godsEyeView; const cockpit = styleManager.cockpitView; const mode = () => styleManager.getDetectionState().detectionMode; const density = () => styleManager.getDetectionState().densityPct; const settle = (ms = 160) => new Promise((resolve) => setTimeout(resolve, ms)); // Cockpit entry needs an auto-focused subject, which arrives a beat after // the Contacts transaction settles. Bounded so a stall fails the check // rather than hanging the harness. const enterCockpit = async () => { for (let attempt = 0; attempt < 40; attempt += 1) { if (cockpit.enter() === true) return true; await settle(200); } return false; }; const originalOverridden = styleManager._detectionUserOverridden; // Start from outside both, so activation is a real edge. cockpit.exit({ restoreTracking: true }); await settle(); await styleManager._selectContextMode(null); await settle(400); const cleanupSnapshotCleared = styleManager._contextSessionSnapshot === null; const cleanupBlockerId = '__qa_slow_contacts_sibling__'; const cleanupUnregistered = await window.__gevQaUnregisterLayer( window.__godsEyeView.dataManager, cleanupBlockerId, ); const cleanupBlockerAbsent = !window.__godsEyeView.dataManager.layers.has(cleanupBlockerId); // Adversarial precondition: detection explicitly OFF at a NON-tactical // density, and the operator already flagged as having overridden detection // this session — the flag that suppresses the military-style auto-enable. styleManager.setDetection({ enabled: false, densityPct: 25 }); await settle(); const beforeContacts = mode(); const overriddenBeforeContacts = styleManager._detectionUserOverridden; // 1. Activating Contacts forces the tactical preset on. const contactsOn = await styleManager._selectContextMode('flights'); await settle(400); const afterContactsOn = mode(); const afterContactsOnDensity = density(); // 2. Cockpit enter and exit are moves WITHIN the session: detection unchanged. const entered = await enterCockpit(); await settle(); const insideCockpit = mode(); cockpit.cycleVisionMode(1); await settle(); const afterVisionCycle = mode(); cockpit.setVisionMode('optical'); await settle(); const exited = cockpit.exit({ restoreTracking: true }) === true; await settle(); const afterCockpitExit = mode(); const afterCockpitExitDensity = density(); // 3. A manual off during the session holds — even across a cockpit re-entry. document.getElementById('detection-toggle')?.click(); await settle(); const afterManualOff = mode(); const reentered = await enterCockpit(); await settle(); const afterCockpitReentry = mode(); cockpit.exit({ restoreTracking: true }); await settle(); // 4. Deactivating Contacts restores the pre-Contacts state. await styleManager._selectContextMode(null); await settle(400); const afterContactsOff = mode(); const afterContactsOffDensity = density(); // The operator's next manual enable must come back at THEIR profile, not // the tactical density Contacts stamped on. document.getElementById('detection-toggle')?.click(); await settle(); const manualEnableMode = mode(); const manualEnableDensity = density(); styleManager.setDetection({ enabled: false }); await settle(); // Leave the session exactly as the following checks expect it. const restoredContacts = await styleManager._selectContextMode('flights'); await settle(400); const restoredCockpit = await enterCockpit(); styleManager._detectionUserOverridden = originalOverridden; await settle(); return { beforeContacts, overriddenBeforeContacts, contactsOn, afterContactsOn, afterContactsOnDensity, entered, insideCockpit, afterVisionCycle, exited, afterCockpitExit, afterCockpitExitDensity, afterManualOff, reentered, afterCockpitReentry, afterContactsOff, afterContactsOffDensity, manualEnableMode, manualEnableDensity, restoredContacts, restoredCockpit, cockpitActive: cockpit.active, cleanupSnapshotCleared, cleanupUnregistered, cleanupBlockerAbsent, }; }); check( 'Contacts owns detection: activation forces the tactical preset, cockpit transitions leave it alone, deactivation restores', contactsDetection.contactsOn === true && contactsDetection.entered && contactsDetection.exited && contactsDetection.reentered && contactsDetection.restoredContacts === true && contactsDetection.restoredCockpit && contactsDetection.cockpitActive && contactsDetection.cleanupSnapshotCleared && contactsDetection.cleanupUnregistered && contactsDetection.cleanupBlockerAbsent && contactsDetection.beforeContacts === 'OFF' && contactsDetection.overriddenBeforeContacts === true // Activation forces the military look — Dense @ 75%, not the 25% the // operator was sitting at, and regardless of the override flag. && contactsDetection.afterContactsOn === 'DENSE' && contactsDetection.afterContactsOnDensity === 75 // Cockpit is a move WITHIN Contacts: enter, vision cycle and — the actual // bug — EXIT must all leave detection exactly where it was. && contactsDetection.insideCockpit === 'DENSE' && contactsDetection.afterVisionCycle === 'DENSE' && contactsDetection.afterCockpitExit === 'DENSE' && contactsDetection.afterCockpitExitDensity === 75 // A manual off holds for the session, including across a cockpit re-entry. && contactsDetection.afterManualOff === 'OFF' && contactsDetection.afterCockpitReentry === 'OFF' // Leaving Contacts restores the pre-Contacts state — mode AND density, so // the operator's next manual enable returns their own 25% profile rather // than the tactical 75% Contacts stamped on. && contactsDetection.afterContactsOff === 'OFF' && contactsDetection.afterContactsOffDensity === 25 && contactsDetection.manualEnableMode === 'SPARSE' && contactsDetection.manualEnableDensity === 25, JSON.stringify(contactsDetection), ); const densityNavigation = await page.evaluate(async () => { const { styleManager, dataManager, viewer } = window.__godsEyeView; const cockpit = styleManager.cockpitView; const awareness = dataManager.layers.get('military-awareness')?.module; const settle = (ms = 260) => new Promise((resolve) => setTimeout(resolve, ms)); const snapshot = (step) => { const context = awareness?.getContextSnapshot?.() || null; const tracker = viewer.trackedEntity || cockpit.trackedEntity; return { step, cockpitActive: cockpit.active, bodyCockpit: document.body.classList.contains('cockpit-mode'), contextMode: styleManager._contextMode, contextChanging: styleManager._contextModeChanging, subject: context?.subject ? `${context.subject.layerId}:${context.subject.id}` : null, tracked: tracker?.gevTrackedId || null, density: styleManager.getDetectionState().densityPct, detectionMode: styleManager.getDetectionState().detectionMode, installations: dataManager.getLayerLifecycleState('military-installations'), }; }; const setDensityFromUi = (value) => { const slider = document.getElementById('detection-density-slider'); slider.value = String(value); slider.dispatchEvent(new Event('input', { bubbles: true })); }; const states = [snapshot('before')]; setDensityFromUi(25); states.push(snapshot('sparse')); document.getElementById('cockpit-context-next')?.click(); await settle(1700); states.push(snapshot('ui-next')); setDensityFromUi(75); document.getElementById('cockpit-context-previous')?.click(); await settle(1700); states.push(snapshot('ui-previous')); const voiceNext = styleManager.controlCockpit('next'); await settle(1700); states.push(snapshot('voice-next')); const voicePrevious = styleManager.controlCockpit('previous'); await settle(1700); states.push(snapshot('voice-previous')); const exited = cockpit.exit({ restoreTracking: true }) === true; await settle(100); const mapBefore = snapshot('map-before'); const mapNext = awareness?.navigateNext?.({ origin: 'user' }) === true; await settle(); const mapAfterNext = snapshot('map-next'); const mapPrevious = awareness?.navigatePrevious?.({ origin: 'user' }) === true; await settle(); const mapAfterPrevious = snapshot('map-previous'); const reentered = cockpit.enter() === true; await settle(100); states.push(snapshot('reentered')); return { states, voiceNext: voiceNext.ok, voicePrevious: voicePrevious.ok, exited, mapBefore, mapNext, mapAfterNext, mapPrevious, mapAfterPrevious, reentered, }; }); const cockpitStatesStable = densityNavigation.states.every((state) => ( state.cockpitActive && state.bodyCockpit && state.contextMode === 'flights' && !state.contextChanging && state.subject && state.tracked )); check( 'Dense/Sparse UI and voice Next/Previous keep Cockpit active and standard Flights tracking stable', cockpitStatesStable && densityNavigation.states.find(({ step }) => step === 'sparse')?.density === 25 && densityNavigation.states.find(({ step }) => step === 'ui-next')?.density === 25 && densityNavigation.states.find(({ step }) => step === 'ui-previous')?.density === 75 && densityNavigation.voiceNext && densityNavigation.voicePrevious && densityNavigation.exited && !densityNavigation.mapBefore.cockpitActive && densityNavigation.mapBefore.contextMode === 'flights' && densityNavigation.mapNext && densityNavigation.mapAfterNext.tracked && densityNavigation.mapPrevious && densityNavigation.mapAfterPrevious.tracked && densityNavigation.reentered, JSON.stringify(densityNavigation), ); const cockpitExitOwnership = await page.evaluate(async () => { const { styleManager, dataManager, viewer } = window.__godsEyeView; const awareness = dataManager.layers.get('military-awareness')?.module; const entity = viewer.trackedEntity || styleManager.cockpitView.trackedEntity; const listenersBeforeExit = viewer.scene.preUpdate.numberOfListeners; const exited = styleManager.cockpitView.exit() === true; await new Promise((resolve) => setTimeout(resolve, 80)); const listenersAfterExit = viewer.scene.preUpdate.numberOfListeners; const refocused = awareness?.focusCurrent?.() === true; await new Promise((resolve) => setTimeout(resolve, 80)); return { exited, refocused, sameEntity: viewer.trackedEntity === entity, listenersBeforeExit, listenersAfterExit, listenersAfterFocus: viewer.scene.preUpdate.numberOfListeners, }; }); check( 'Cockpit exit and later Contact Focus retain one source-owned camera-frame listener', cockpitExitOwnership.exited && cockpitExitOwnership.refocused && cockpitExitOwnership.sameEntity && cockpitExitOwnership.listenersAfterExit === cockpitExitOwnership.listenersBeforeExit + 1 && cockpitExitOwnership.listenersAfterFocus === cockpitExitOwnership.listenersAfterExit, JSON.stringify(cockpitExitOwnership), ); const cockpitPanelRoundTrip = await page.evaluate(async () => { const manager = window.__godsEyeView.styleManager; const panelIds = [ 'data-panel', 'cctv-panel', 'scene-panel', 'pp-toggles', 'global-context-panel', 'radio-panel', ]; const read = () => Object.fromEntries(panelIds.map((panelId) => [ panelId, document.getElementById(panelId)?.classList.contains('collapsed'), ])); const desired = new Map([ ['data-panel', false], ['cctv-panel', true], ['scene-panel', true], ['pp-toggles', true], ['global-context-panel', false], ['radio-panel', true], ]); for (const [panelId, collapsed] of desired) { manager.setPanelCollapsed(panelId, collapsed, { persist: false, syncShare: false }); } const before = read(); document.getElementById('cockpit-entry')?.click(); await new Promise((resolve) => setTimeout(resolve, 120)); const during = read(); manager.setPanelCollapsed('data-panel', false, { persist: false, syncShare: false }); await new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve))); const dataRect = document.getElementById('data-panel')?.getBoundingClientRect(); const contactRect = document.getElementById('cockpit-context')?.getBoundingClientRect(); const clearancePx = dataRect && contactRect ? contactRect.top - dataRect.bottom : null; const contactAutoCollapsed = manager.cockpitView.contextCollapsed === true; manager.setPanelCollapsed('data-panel', true, { persist: false, syncShare: false }); const contactAutoRestored = manager.cockpitView.contextCollapsed === false; manager.cockpitView.setContextCollapsed(true); manager.setPanelCollapsed('data-panel', false, { persist: false, syncShare: false }); manager.setPanelCollapsed('data-panel', true, { persist: false, syncShare: false }); const manualContactCollapseRetained = manager.cockpitView.contextCollapsed === true; manager.cockpitView.setContextCollapsed(false); const exited = manager.cockpitView.exit() === true; await new Promise((resolve) => setTimeout(resolve, 80)); return { before, during, after: read(), exited, clearancePx, contactAutoCollapsed, contactAutoRestored, manualContactCollapseRetained, }; }); check( 'Cockpit temporarily collapses standard panels and restores the exact map layout on exit', cockpitPanelRoundTrip.exited && Object.values(cockpitPanelRoundTrip.during).every(Boolean) && JSON.stringify(cockpitPanelRoundTrip.after) === JSON.stringify(cockpitPanelRoundTrip.before) && Number.isFinite(cockpitPanelRoundTrip.clearancePx) && cockpitPanelRoundTrip.clearancePx >= 0 && cockpitPanelRoundTrip.contactAutoCollapsed && cockpitPanelRoundTrip.contactAutoRestored && cockpitPanelRoundTrip.manualContactCollapseRetained, JSON.stringify(cockpitPanelRoundTrip), ); await page.waitForFunction(() => { const entry = document.getElementById('cockpit-entry'); return entry && !entry.hidden && !entry.disabled; }, { timeout: 10_000 }); await page.$eval('#cockpit-entry', (entry) => entry.click()); await page.waitForFunction( () => document.body.classList.contains('cockpit-mode') && window.__godsEyeView.styleManager.cockpitView.active, { timeout: 10_000 }, ); await page.evaluate(() => { const manager = window.__godsEyeView.styleManager; manager._setCockpitDisclosure('display', false); manager._setCockpitDisclosure('radio', false); }); const visionCycle = await page.evaluate(async () => { const manager = window.__godsEyeView.styleManager; const cockpit = manager.cockpitView; const current = document.getElementById('cockpit-vision-current'); const label = document.getElementById('cockpit-vision-current-label'); const read = () => ({ mode: current?.dataset.cockpitVision, label: label?.textContent?.trim(), aria: current?.getAttribute('aria-label'), displayOpen: document.getElementById('cockpit-display-toggle-btn')?.getAttribute('aria-expanded'), radioOpen: document.getElementById('cockpit-radio-toggle-btn')?.getAttribute('aria-expanded'), parametersActive: document.getElementById('param-slider-panel')?.classList.contains('active'), parametersCollapsed: document.getElementById('param-slider-panel')?.classList.contains('collapsed'), signalCollapsed: cockpit.signalCollapsed, focusRetained: document.activeElement === current, }); manager._setCockpitDisclosure('display', false); manager._setCockpitDisclosure('radio', false); cockpit.setVisionMode('optical'); current.focus({ preventScroll: true }); const states = [read()]; for (let index = 0; index < 5; index += 1) { current.click(); states.push(read()); } const originalStyle = manager.activeStyle; manager.setStyle('noir'); await new Promise((resolve) => setTimeout(resolve, 900)); cockpit.setVisionMode('optical'); const inheritedNoir = read(); cockpit.setVisionMode('noir'); const explicitNoir = read(); cockpit.setVisionMode('optical'); const restoredNoir = { ...read(), activeStyle: manager.activeStyle, intensity: manager.stages.noir?.uniforms?.intensity, }; manager.setStyle(originalStyle); await new Promise((resolve) => setTimeout(resolve, 900)); cockpit.setVisionMode('optical'); return { states, inheritedNoir, explicitNoir, restoredNoir }; }); check( 'Cockpit vision control exposes inherited, CRT, NVG, FLIR, and NOIR before wrapping', JSON.stringify(visionCycle.states.map((state) => state.mode)) === JSON.stringify(['optical', 'crt', 'nvg', 'thermal', 'noir', 'optical']) && visionCycle.states[4]?.label === 'NOIR' && visionCycle.states[4]?.aria === 'Current cockpit vision style: Noir. Activate for next style.', JSON.stringify(visionCycle), ); check( 'user vision changes open Display for every temporary treatment and retain selector focus', visionCycle.states[1]?.mode === 'crt' && visionCycle.states.slice(1, 5).every((state) => state.displayOpen === 'true') && visionCycle.states.slice(1, 5).every((state) => state.radioOpen === 'false') && visionCycle.states.slice(1, 5).every((state) => state.parametersActive) && visionCycle.states.slice(1, 5).every((state) => !state.parametersCollapsed) && visionCycle.states.slice(1, 5).every((state) => state.signalCollapsed) && visionCycle.states.every((state) => state.focusRetained), JSON.stringify(visionCycle.states), ); check( 'inherited Noir and explicit Noir keep distinct ownership and restore the Noir map preset', visionCycle.inheritedNoir?.mode === 'optical' && visionCycle.inheritedNoir?.label === 'NOIR' && visionCycle.explicitNoir?.mode === 'noir' && visionCycle.explicitNoir?.label === 'NOIR' && visionCycle.restoredNoir?.mode === 'optical' && visionCycle.restoredNoir?.activeStyle === 'noir' && visionCycle.restoredNoir?.intensity === 1, JSON.stringify(visionCycle), ); await page.evaluate(() => window.__godsEyeView.styleManager.cockpitView.setVisionMode('noir')); await page.screenshot({ path: path.join(shotsDir, 'vision-noir.png') }); await page.evaluate(() => window.__godsEyeView.styleManager.cockpitView.setVisionMode('optical')); const desktopState = async (variant, openKind) => page.evaluate(async ({ variantName, kind }) => { const manager = window.__godsEyeView.styleManager; const hud = document.getElementById('cockpit-hud'); const signal = document.getElementById('cockpit-signal-stream'); const utility = document.getElementById('cockpit-utility-controls'); const display = document.getElementById('cockpit-display-toggle-btn'); const radio = document.getElementById('cockpit-radio-toggle-btn'); const displayControl = display.closest('.cockpit-utility-control'); const radioControl = radio.closest('.cockpit-utility-control'); manager._setCockpitDisclosure('display', false); manager._setCockpitDisclosure('radio', false); if (variantName === 'off') manager.hud.setMode('off'); else { manager._setHudVariant(variantName); manager.hud.setMode('on'); } manager._updateHudButtonState(); await new Promise((resolve) => setTimeout(resolve, 360)); document.body.classList.add('cockpit-mode'); manager.cockpitView.active = true; hud.hidden = false; signal.hidden = false; // Cockpit owns --cockpit-utility-top and republishes it every layout tick, // so the corridor is driven through its real input: how far up the briefing // card reaches. A short card leaves the strip a roomy corridor. const priorSignalMaxHeight = signal.style.maxHeight; signal.style.maxHeight = '150px'; manager._setCockpitDisclosure(kind, true); // One pass must be enough. Record the result of the FIRST layout call, then // confirm a second changes nothing, so a convergence regression cannot hide // behind a repeated call. manager.cockpitView.syncSignalLayout(); const firstPassTop = hud.style.getPropertyValue('--cockpit-utility-top'); const firstPassPrimaryOnly = utility.classList.contains('layout-primary-only'); manager.cockpitView.syncSignalLayout(); const signalTop = signal.getBoundingClientRect().top; const expanded = kind === 'display' ? displayControl : radioControl; const sibling = kind === 'display' ? radioControl : displayControl; const state = { variant: variantName, kind, signalTop: Math.round(signalTop), firstPassTop, idempotent: firstPassTop === hud.style.getPropertyValue('--cockpit-utility-top') && firstPassPrimaryOnly === utility.classList.contains('layout-primary-only'), utilityTop: hud.style.getPropertyValue('--cockpit-utility-top'), primaryOnly: utility.classList.contains('layout-primary-only'), expandedRect: expanded.getBoundingClientRect().toJSON(), siblingRect: sibling.getBoundingClientRect().toJSON(), siblingDisplay: getComputedStyle(sibling).display, siblingAriaHidden: sibling.getAttribute('aria-hidden'), siblingExpanded: sibling.querySelector('[aria-expanded]')?.getAttribute('aria-expanded'), contained: expanded.getBoundingClientRect().bottom <= signalTop - 7, }; signal.style.maxHeight = priorSignalMaxHeight; manager.cockpitView.syncSignalLayout(); return state; }, { variantName: variant, kind: openKind }); for (const variant of ['off', 'minimal', 'tactical', 'operator']) { for (const kind of ['display', 'radio']) { const state = await desktopState(variant, kind); check( `${variant} ${kind} keeps its collapsed sibling visible in a roomy corridor`, !state.primaryOnly && state.expandedRect.width > 0 && state.siblingRect.width > 0 && state.siblingRect.height > 0 && state.siblingDisplay !== 'none' && state.siblingAriaHidden === 'false' && state.siblingExpanded === 'false' && state.contained, JSON.stringify(state), ); check( `${variant} ${kind} settles the strip anchor in one layout pass`, state.idempotent && state.firstPassTop === state.utilityTop, `first=${state.firstPassTop} settled=${state.utilityTop}`, ); } } await page.screenshot({ path: path.join(shotsDir, 'roomy-desktop.png') }); check( 'roomy screenshot remains in a real Cockpit session', await page.evaluate(() => document.body.classList.contains('cockpit-mode') && window.__godsEyeView.styleManager.cockpitView.active && getComputedStyle(document.getElementById('cockpit-utility-controls')).display !== 'none'), ); const portalScroll = await page.evaluate(async () => { const manager = window.__godsEyeView.styleManager; const standard = document.getElementById('pp-toggles'); const cockpit = document.getElementById('cockpit-display-panel'); const waitFrames = () => new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve))); const priorStandardMaxHeight = standard.style.maxHeight; const priorStandardHeight = standard.style.height; const priorStandardOverflow = standard.style.overflowY; const priorCockpitMaxHeight = cockpit.style.maxHeight; const priorCockpitHeight = cockpit.style.height; const priorCockpitOverflow = cockpit.style.overflowY; const standardWasCollapsed = standard.classList.contains('collapsed'); manager._setCockpitDisplayPortalActive(false); document.body.classList.remove('cockpit-mode'); await waitFrames(); standard.classList.remove('collapsed'); standard.style.height = '120px'; standard.style.maxHeight = '120px'; standard.style.overflowY = 'auto'; standard.scrollTop = Math.min(80, standard.scrollHeight - standard.clientHeight); await waitFrames(); const standardBefore = standard.scrollTop; document.body.classList.add('cockpit-mode'); manager._setCockpitDisplayPortalActive(true); manager._setCockpitDisclosure('display', true); await waitFrames(); cockpit.style.height = '120px'; cockpit.style.maxHeight = '120px'; cockpit.style.overflowY = 'auto'; cockpit.scrollTop = Math.min(60, cockpit.scrollHeight - cockpit.clientHeight); await waitFrames(); const cockpitBefore = cockpit.scrollTop; document.body.classList.remove('cockpit-mode'); manager._setCockpitDisplayPortalActive(false); await waitFrames(); const standardAfter = standard.scrollTop; const standardSaved = manager._standardDisplayScrollTop; const standardClientHeight = standard.clientHeight; const standardScrollHeight = standard.scrollHeight; document.body.classList.add('cockpit-mode'); manager._setCockpitDisplayPortalActive(true); manager._setCockpitDisclosure('display', true); await waitFrames(); const cockpitAfter = cockpit.scrollTop; standard.style.height = priorStandardHeight; standard.style.maxHeight = priorStandardMaxHeight; standard.style.overflowY = priorStandardOverflow; cockpit.style.height = priorCockpitHeight; cockpit.style.maxHeight = priorCockpitMaxHeight; cockpit.style.overflowY = priorCockpitOverflow; standard.classList.toggle('collapsed', standardWasCollapsed); return { standardBefore, standardAfter, standardSaved, standardClientHeight, standardScrollHeight, cockpitBefore, cockpitAfter, }; }); check( 'Display portal round trip preserves standard and Cockpit scroll owners', portalScroll.standardBefore > 0 && portalScroll.cockpitBefore > 0 && portalScroll.standardAfter === portalScroll.standardBefore && portalScroll.cockpitAfter === portalScroll.cockpitBefore, JSON.stringify(portalScroll), ); const boundary = await page.evaluate(() => { const manager = window.__godsEyeView.styleManager; const hud = document.getElementById('cockpit-hud'); const signal = document.getElementById('cockpit-signal-stream'); const utility = document.getElementById('cockpit-utility-controls'); const display = document.getElementById('cockpit-display-toggle-btn'); const radio = document.getElementById('cockpit-radio-toggle-btn'); const displayControl = display.closest('.cockpit-utility-control'); const radioControl = radio.closest('.cockpit-utility-control'); document.body.classList.add('cockpit-mode'); manager.cockpitView.active = true; hud.hidden = false; signal.hidden = false; manager._setCockpitDisclosure('radio', false); manager._setCockpitDisclosure('display', true); const priorSignalMaxHeight = signal.style.maxHeight; const priorSignalHeight = signal.style.height; // The strip is pinned to the viewport ceiling once the briefing card grows // into its lane, so the corridor is sized by moving that card's top edge — // the wall Cockpit actually solves against — not by injecting an anchor. // The card is bottom-anchored, so an explicit height moves its top edge. const minTop = Math.max(96, window.innerHeight * 0.12); const moveSignalTopTo = (wantTop) => { for (let pass = 0; pass < 8; pass += 1) { const rect = signal.getBoundingClientRect(); const delta = wantTop - rect.top; if (Math.abs(delta) < 0.2) break; const current = parseFloat(signal.style.height) || rect.height; signal.style.height = `${Math.max(40, current - delta)}px`; } // One layout pass owns the decision; the second only proves it settled. // (A pass that newly hides the collapsed sibling legitimately re-anchors // the now-shorter strip, so idempotence is asserted where the strip's // composition is unchanged.) manager.cockpitView.syncSignalLayout(); const firstPassTop = hud.style.getPropertyValue('--cockpit-utility-top'); const firstPassPrimaryOnly = utility.classList.contains('layout-primary-only'); manager.cockpitView.syncSignalLayout(); return { firstPassTop, firstPassPrimaryOnly, idempotent: firstPassTop === hud.style.getPropertyValue('--cockpit-utility-top') && firstPassPrimaryOnly === utility.classList.contains('layout-primary-only'), }; }; signal.style.maxHeight = 'none'; signal.style.height = '150px'; manager.cockpitView.syncSignalLayout(); const expandedHeight = Math.max(displayControl.scrollHeight, displayControl.getBoundingClientRect().height); const collapsedHeight = Math.max(50, radioControl.scrollHeight); const stripHeight = expandedHeight + collapsedHeight + 7; // Straddle the fit by a pixel instead of aiming AT it. `moveSignalTopTo` only // converges to within 0.2 px and the production decision is a strict `>` // against exactly that budget, so a corridor sized to the boundary itself // resolves on sub-pixel residue — a coin flip, not a behaviour. It happened to // land heads until Display grew 36 px on 2026-08-22 (the 3D Proximity/All row // now ships open), which is what surfaced it. One pixel inside the fit and one // pixel outside proves the same transition, deterministically. const BOUNDARY_EPSILON_PX = 1; const exactSignalTop = minTop + 8 + stripHeight + BOUNDARY_EPSILON_PX; // The boundary is only meaningful when approached from the TWO-control // composition. The anchor is solved against the strip's currently RENDERED // height, so arriving here already collapsed to primary-only makes the strip // short, pushes the resolved top above minTop, and the "exact" corridor is // then never evaluated at the boundary at all — the check would fail while // production is behaving correctly. // // The fixed `height: 150px` card seed above used to guarantee that; it stopped // once Display grew (the 3D Proximity/All row ships open from 2026-08-22, +36 px), // because 150 px of card leaves a corridor sized for the OLD strip. Seed from // the measured requirement instead, which holds for any future panel height, // and assert the precondition rather than assuming it. const roomySeed = moveSignalTopTo(exactSignalTop + 80); const roomySeedExpanded = !utility.classList.contains('layout-primary-only') && roomySeed.firstPassPrimaryOnly === false; const exact = { ...moveSignalTopTo(exactSignalTop), utilityTop: hud.style.getPropertyValue('--cockpit-utility-top'), primaryOnly: utility.classList.contains('layout-primary-only'), siblingVisible: getComputedStyle(radioControl).display !== 'none', siblingAriaHidden: radioControl.getAttribute('aria-hidden'), }; radio.focus({ preventScroll: true }); const constrained = { // One pixel on the far side of the same fit (`exactSignalTop` already sits // one pixel inside it), so this is still the one-pixel constraint it claims. ...moveSignalTopTo(exactSignalTop - 2 * BOUNDARY_EPSILON_PX), utilityTop: hud.style.getPropertyValue('--cockpit-utility-top'), primaryOnly: utility.classList.contains('layout-primary-only'), siblingDisplay: getComputedStyle(radioControl).display, siblingRect: radioControl.getBoundingClientRect().toJSON(), siblingAriaHidden: radioControl.getAttribute('aria-hidden'), focusReturned: document.activeElement === display, contained: displayControl.getBoundingClientRect().bottom <= signal.getBoundingClientRect().top - 7, }; const restored = { ...moveSignalTopTo(exactSignalTop + 80), utilityTop: hud.style.getPropertyValue('--cockpit-utility-top'), primaryOnly: utility.classList.contains('layout-primary-only'), siblingVisible: getComputedStyle(radioControl).display !== 'none', siblingAriaHidden: radioControl.getAttribute('aria-hidden'), }; signal.style.maxHeight = priorSignalMaxHeight; signal.style.height = priorSignalHeight; manager.cockpitView.syncSignalLayout(); return { minTop, stripHeight, exactSignalTop, roomySeedExpanded, exact, constrained, restored }; }); check( 'exact fit keeps the sibling; one-pixel constraint hides it, transfers focus, and restores it', boundary.roomySeedExpanded && !boundary.exact.primaryOnly && boundary.exact.siblingVisible && boundary.exact.siblingAriaHidden === 'false' && boundary.constrained.primaryOnly && boundary.constrained.siblingDisplay === 'none' && boundary.constrained.siblingRect.width === 0 && boundary.constrained.siblingAriaHidden === 'true' && boundary.constrained.focusReturned && boundary.constrained.contained && !boundary.restored.primaryOnly && boundary.restored.siblingVisible && boundary.restored.siblingAriaHidden === 'false', JSON.stringify(boundary), ); check( 'each corridor change is decided by the first layout pass, not a repeated one', boundary.exact.idempotent && boundary.restored.idempotent && boundary.constrained.firstPassPrimaryOnly, JSON.stringify({ exact: { first: boundary.exact.firstPassTop, idempotent: boundary.exact.idempotent }, constrained: { first: boundary.constrained.firstPassTop, firstPassPrimaryOnly: boundary.constrained.firstPassPrimaryOnly, }, restored: { first: boundary.restored.firstPassTop, idempotent: boundary.restored.idempotent }, }), ); const signalTransition = await page.evaluate(() => { const manager = window.__godsEyeView.styleManager; const cockpit = manager.cockpitView; const signalToggle = document.getElementById('cockpit-signal-toggle'); let expandedEvents = 0; const onExpanded = () => { expandedEvents += 1; }; cockpit.signalUserCollapsed = false; manager._setCockpitDisclosure('display', false); manager._setCockpitDisclosure('radio', false); cockpit.setSignalCollapsed(true); window.addEventListener('gev:cockpit-signal-expanded', onExpanded); try { cockpit.setSignalCollapsed(false); const afterExpansion = expandedEvents; cockpit.setSignalCollapsed(false); const afterRepeatedExpansion = expandedEvents; manager._setCockpitDisclosure('display', true); const displayCollapsedSignals = cockpit.signalCollapsed; manager._setCockpitDisclosure('display', false); const afterUtilityClose = expandedEvents; const utilityCloseReopenedSignals = !cockpit.signalCollapsed; cockpit.setSignalCollapsed(true, { user: true }); manager._setCockpitDisclosure('radio', true); manager._setCockpitDisclosure('radio', false); const manualCollapseRetained = cockpit.signalCollapsed && cockpit.signalUserCollapsed; return { afterExpansion, afterRepeatedExpansion, afterUtilityClose, displayCollapsedSignals, utilityCloseReopenedSignals, manualCollapseRetained, signalAriaExpanded: signalToggle?.getAttribute('aria-expanded'), }; } finally { window.removeEventListener('gev:cockpit-signal-expanded', onExpanded); cockpit.signalUserCollapsed = false; cockpit.setSignalCollapsed(false); } }); check( 'Live Signals expansion is edge-triggered and manual collapse remains authoritative', signalTransition.afterExpansion === 1 && signalTransition.afterRepeatedExpansion === 1 && signalTransition.afterUtilityClose === 2 && signalTransition.displayCollapsedSignals && signalTransition.utilityCloseReopenedSignals && signalTransition.manualCollapseRetained && signalTransition.signalAriaExpanded === 'false', JSON.stringify(signalTransition), ); const contextTransition = await page.evaluate(() => { const cockpit = window.__godsEyeView.styleManager.cockpitView; const priorCollapsed = cockpit.contextCollapsed; const contextToggle = document.getElementById('cockpit-context-toggle'); let expandedEvents = 0; const onExpanded = () => { expandedEvents += 1; }; cockpit.setContextCollapsed(true); window.addEventListener('gev:cockpit-context-expanded', onExpanded); try { cockpit.setContextCollapsed(false); const afterExpansion = expandedEvents; cockpit.setContextCollapsed(false); return { afterExpansion, afterRepeatedExpansion: expandedEvents, ariaExpanded: contextToggle?.getAttribute('aria-expanded'), label: contextToggle?.getAttribute('aria-label'), }; } finally { window.removeEventListener('gev:cockpit-context-expanded', onExpanded); cockpit.setContextCollapsed(priorCollapsed); } }); check( 'Contact expansion is edge-triggered and retains its disclosure semantics', contextTransition.afterExpansion === 1 && contextTransition.afterRepeatedExpansion === 1 && contextTransition.ariaExpanded === 'true' && contextTransition.label === 'Collapse Contact panel', JSON.stringify(contextTransition), ); await page.screenshot({ path: path.join(shotsDir, 'restored-desktop.png') }); check( 'restored screenshot remains in a real Cockpit session', await page.evaluate(() => document.body.classList.contains('cockpit-mode') && window.__godsEyeView.styleManager.cockpitView.active && getComputedStyle(document.getElementById('cockpit-utility-controls')).display !== 'none'), ); const desktopViewActions = await page.evaluate(() => { const reset = document.getElementById('cockpit-reset-globe')?.getBoundingClientRect(); const exit = document.getElementById('map-view-switch')?.getBoundingClientRect(); return { reset: reset?.toJSON() || null, exit: exit?.toJSON() || null, viewport: { width: innerWidth, height: innerHeight }, }; }); check( 'desktop Cockpit Reset and Exit remain readable without overlap', desktopViewActions.reset?.width > 44 && desktopViewActions.exit?.width > 70 && desktopViewActions.reset.right <= desktopViewActions.exit.left && desktopViewActions.reset.left >= 0 && desktopViewActions.exit.right <= desktopViewActions.viewport.width, JSON.stringify(desktopViewActions), ); await page.setViewport({ width: 390, height: 844, deviceScaleFactor: 1 }); const mobile = await page.evaluate(async () => { const manager = window.__godsEyeView.styleManager; const hud = document.getElementById('cockpit-hud'); const signal = document.getElementById('cockpit-signal-stream'); const display = document.getElementById('cockpit-display-toggle-btn'); const radio = document.getElementById('cockpit-radio-toggle-btn'); const displayControl = display.closest('.cockpit-utility-control'); const radioControl = radio.closest('.cockpit-utility-control'); document.body.classList.add('cockpit-mode'); manager.cockpitView.active = true; hud.hidden = false; signal.hidden = false; manager._setCockpitDisclosure('display', false); manager._setCockpitDisclosure('radio', false); manager.cockpitView.syncSignalLayout(); const collapsed = { display: displayControl.getBoundingClientRect().toJSON(), radio: radioControl.getBoundingClientRect().toJSON(), }; display.click(); manager.cockpitView.syncSignalLayout(); return { collapsed, expandedDisplay: displayControl.getBoundingClientRect().toJSON(), radioDisplay: getComputedStyle(radioControl).display, radioAriaHidden: radioControl.getAttribute('aria-hidden'), }; }); check( 'mobile keeps both collapsed launchers and the existing fixed expanded behavior', mobile.collapsed.display.width > 0 && mobile.collapsed.radio.width > 0 && mobile.expandedDisplay.width > 0 && mobile.expandedDisplay.width <= 366 && mobile.radioDisplay === 'none' && mobile.radioAriaHidden === 'true', JSON.stringify(mobile), ); await page.screenshot({ path: path.join(shotsDir, 'mobile.png') }); check( 'mobile screenshot remains in a real Cockpit session', await page.evaluate(() => document.body.classList.contains('cockpit-mode') && window.__godsEyeView.styleManager.cockpitView.active && getComputedStyle(document.getElementById('cockpit-utility-controls')).display !== 'none'), ); const narrowViewActions = await page.evaluate(() => { const reset = document.getElementById('cockpit-reset-globe')?.getBoundingClientRect(); const exit = document.getElementById('map-view-switch')?.getBoundingClientRect(); return { reset: reset?.toJSON() || null, exit: exit?.toJSON() || null, viewport: { width: innerWidth, height: innerHeight }, }; }); check( 'narrow Cockpit Reset and Exit remain readable without overlap', narrowViewActions.reset?.width > 44 && narrowViewActions.exit?.width > 70 && narrowViewActions.reset.right <= narrowViewActions.exit.left && narrowViewActions.reset.left >= 0 && narrowViewActions.exit.right <= narrowViewActions.viewport.width, JSON.stringify(narrowViewActions), ); const resetResult = await page.evaluate(() => { const manager = window.__godsEyeView.styleManager; const awareness = window.__godsEyeView.dataManager.layers.get('military-awareness')?.module; window.__qaCockpitReset = { calls: 0, original: manager.resetToGlobeView, subjectId: awareness?.getContextSnapshot?.()?.subject?.id || null, }; manager.resetToGlobeView = function qaCountedCockpitReset(...args) { window.__qaCockpitReset.calls += 1; return window.__qaCockpitReset.original.apply(this, args); }; return Boolean(document.getElementById('cockpit-reset-globe')); }); check('Cockpit Reset is present before keyboard activation', resetResult); await page.focus('#cockpit-reset-globe'); await page.keyboard.press('Enter'); await page.waitForFunction( () => !window.__godsEyeView.styleManager.cockpitView.active, { timeout: 6_000 }, ); await page.waitForFunction(() => { const viewer = window.__godsEyeView.viewer; if (!viewer) return false; const height = viewer.camera.positionCartographic?.height; return Math.abs(height - 18_000_000) < 150_000; }, { timeout: 6_000 }); const resetState = await page.evaluate(() => { const gev = window.__godsEyeView; const qa = window.__qaCockpitReset; const awareness = gev.dataManager.layers.get('military-awareness')?.module; const subjectId = awareness?.getContextSnapshot?.()?.subject?.id || null; const height = gev.viewer.camera.positionCartographic?.height; gev.styleManager.resetToGlobeView = qa.original; delete window.__qaCockpitReset; return { calls: qa.calls, cockpitActive: gev.styleManager.cockpitView.active, trackedEntity: Boolean(gev.viewer.trackedEntity), resetHidden: document.getElementById('cockpit-reset-globe')?.hidden, height, subjectPreserved: Boolean(qa.subjectId && subjectId === qa.subjectId), }; }); check( 'keyboard Cockpit Reset uses one canonical route and preserves Contact selection', resetState.calls === 1 && !resetState.cockpitActive && !resetState.trackedEntity && resetState.resetHidden && Math.abs(resetState.height - 18_000_000) < 150_000 && resetState.subjectPreserved, JSON.stringify(resetState), ); check('runtime console remains clean', consoleErrors.length === 0 && localHttpErrors.length === 0, [...localHttpErrors, ...consoleErrors].slice(0, 6).join(' | ')); } finally { await page.evaluate(() => { const manager = window.__godsEyeView?.styleManager; const prior = window.__qaCockpitUtilityPrior; if (!manager || !prior) return; manager._setCockpitDisclosure('display', false); manager._setCockpitDisclosure('radio', false); if (manager.cockpitView.active && !prior.active) manager.cockpitView.exit(); else manager.cockpitView.active = prior.active; const hud = document.getElementById('cockpit-hud'); const signal = document.getElementById('cockpit-signal-stream'); hud.hidden = prior.hudHidden; signal.hidden = prior.signalHidden; manager._setHudVariant(prior.hudVariant); manager.hud.setMode(prior.hudVisible ? 'on' : 'off'); if (prior.utilityTop) hud.style.setProperty('--cockpit-utility-top', prior.utilityTop); else hud.style.removeProperty('--cockpit-utility-top'); if (!prior.cockpit) document.body.classList.remove('cockpit-mode'); }).catch(() => {}); await browser.close(); } console.log(`RESULT: ${failures.length ? 'NOT_READY' : 'READY'} (${failures.length} failures)`); process.exitCode = failures.length ? 1 : 0;