mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
refactor(space): separate satellite and mission layer components
This commit is contained in:
1 parent
61db945b21
commit
ce0568983a
44 files changed
+8767
-6095
No files matched your search
@@ -0,0 +1,251 @@
|
||||
import * as Cesium from 'cesium';
|
||||
import { ISS_NORAD, ISS_OVERLAY_SOURCE_ID } from './policy.js';
|
||||
|
||||
export function createTesting({ state: layerState, services, parts, source }) {
|
||||
/**
|
||||
* Seed a single tracked satellite so tests can invoke the exact production
|
||||
* pre-render callback without constructing a WebGL viewer.
|
||||
* @param {object} state
|
||||
* @param {number} state.noradId
|
||||
* @param {string} state.name
|
||||
* @param {object} state.satrec
|
||||
* @param {object} state.entity
|
||||
* @param {object} state.point
|
||||
* @param {object} state.viewer
|
||||
* @param {() => (number|Date)} state.now
|
||||
*/
|
||||
|
||||
function _setTrackedSatelliteRefreshStateForTest({
|
||||
noradId,
|
||||
name,
|
||||
satrec,
|
||||
entity,
|
||||
point,
|
||||
viewer,
|
||||
now,
|
||||
// Extra catalog/point rows so a test can exercise a docked cluster (and a
|
||||
// control satellite that must NOT be treated as part of it).
|
||||
neighbours = [],
|
||||
}) {
|
||||
layerState._viewer = viewer;
|
||||
layerState._catalog = new Map([
|
||||
[noradId, { name, satrec, group: 'stations' }],
|
||||
]);
|
||||
layerState._points = new Map([[noradId, point]]);
|
||||
for (const neighbour of neighbours) {
|
||||
layerState._catalog.set(neighbour.noradId, {
|
||||
name: neighbour.name,
|
||||
satrec: neighbour.satrec || satrec,
|
||||
group: neighbour.group || 'stations',
|
||||
});
|
||||
layerState._points.set(neighbour.noradId, neighbour.point);
|
||||
}
|
||||
layerState._dockedCompanions = new Set();
|
||||
layerState._lastDockedScanMs = Number.NEGATIVE_INFINITY;
|
||||
layerState._trackedNorad = noradId;
|
||||
layerState._trackedEntity = entity;
|
||||
layerState._trackedFrameNumber = -1;
|
||||
layerState._trackedFrameGeo = null;
|
||||
layerState._trackedFrameNowForTest = now;
|
||||
layerState._params = {
|
||||
catalog: 'core',
|
||||
showPoints: false,
|
||||
showOrbits: false,
|
||||
};
|
||||
layerState._enabled = true;
|
||||
}
|
||||
|
||||
/** Seed catalog authority and optional dense settlement for share-Follow tests. */
|
||||
|
||||
function _setSatelliteTrackingRefreshOutcomeForTest({
|
||||
status = 'accepted',
|
||||
failedGroups = [],
|
||||
catalog = 'core',
|
||||
densePromise = null,
|
||||
} = {}) {
|
||||
const epoch = ++layerState._trackingRefreshEpoch;
|
||||
layerState._lastTrackingRefreshOutcome = {
|
||||
epoch,
|
||||
status,
|
||||
failedGroups: [...failedGroups],
|
||||
};
|
||||
layerState._params.catalog = catalog;
|
||||
layerState._denseLoadPromise =
|
||||
densePromise || Promise.resolve({ status: 'not-requested' });
|
||||
}
|
||||
|
||||
/** The tracked satellite's current ECEF sample — the value the docked-cluster
|
||||
* scan measures against. Exposed so a test can place neighbours around it. */
|
||||
|
||||
function _trackedFrameCartesianForTest() {
|
||||
return layerState._trackedFrameCartesian;
|
||||
}
|
||||
|
||||
/** Invoke the same callback registered on `scene.preRender` in production. */
|
||||
|
||||
function _runSatellitePreRenderForTest() {
|
||||
parts.rendering._preRenderTick();
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed the minimum render state a dense-catalog load needs, so a test can
|
||||
* exercise the real async load/settle/fail path (and the row-control states it
|
||||
* drives) without constructing a WebGL viewer.
|
||||
* @param {{ catalog?: 'core'|'dense', showPoints?: boolean }} [options]
|
||||
*/
|
||||
|
||||
function _setDenseCatalogStateForTest({
|
||||
catalog = 'core',
|
||||
showPoints = true,
|
||||
} = {}) {
|
||||
layerState._viewer = {
|
||||
scene: { primitives: { add: (p) => p, remove() {} } },
|
||||
};
|
||||
// Neutralize the shared world-overlay host: these tests exercise catalog and
|
||||
// row-control logic, not the ISS callout.
|
||||
layerState._overlayHost = {
|
||||
setEntries() {},
|
||||
setVisible() {},
|
||||
clearSource() {},
|
||||
};
|
||||
layerState._pointCollection = {
|
||||
show: true,
|
||||
add: (opts) => ({ ...opts }),
|
||||
remove() {},
|
||||
removeAll() {},
|
||||
};
|
||||
layerState._catalog = new Map();
|
||||
layerState._points = new Map();
|
||||
layerState._detectionObjects = new Map();
|
||||
layerState._orbitPaths = new Map();
|
||||
layerState._denseIds = [];
|
||||
layerState._denseCursor = 0;
|
||||
layerState._denseLoadToken++;
|
||||
layerState._denseStatus = 'idle';
|
||||
layerState._denseError = null;
|
||||
layerState._catalogRevision++;
|
||||
layerState._trackedNorad = null;
|
||||
parts.tracking._cancelPendingTrackingRestore();
|
||||
layerState._params = { catalog, showPoints, showOrbits: false };
|
||||
layerState._enabled = true;
|
||||
}
|
||||
|
||||
/** Tear the dense seam back down so ordering cannot leak into other tests. */
|
||||
|
||||
function _clearDenseCatalogStateForTest() {
|
||||
layerState._rowControlsListener = null;
|
||||
layerState._overlayHost = layerState.DEFAULT_OVERLAY_HOST;
|
||||
layerState._orbitPaths = new Map();
|
||||
layerState._viewer = null;
|
||||
layerState._pointCollection = null;
|
||||
layerState._catalog = new Map();
|
||||
layerState._points = new Map();
|
||||
layerState._denseIds = [];
|
||||
layerState._denseLoadToken++;
|
||||
layerState._denseStatus = 'idle';
|
||||
layerState._denseError = null;
|
||||
layerState._params = {
|
||||
catalog: 'core',
|
||||
showPoints: true,
|
||||
showOrbits: true,
|
||||
};
|
||||
parts.tracking._cancelPendingTrackingRestore();
|
||||
layerState._enabled = false;
|
||||
}
|
||||
|
||||
/** Catalog group tag recorded for a satellite, for ingestion-path assertions. */
|
||||
|
||||
function _catalogGroupForTest(noradId) {
|
||||
return layerState._catalog.get(Number(noradId))?.group;
|
||||
}
|
||||
|
||||
/** Seed ISS/tracking state while retaining the production track and host paths. */
|
||||
|
||||
function _setSatelliteLabelLifecycleStateForTest({
|
||||
viewer,
|
||||
satrec,
|
||||
point,
|
||||
overlayHost,
|
||||
preservePending = false,
|
||||
}) {
|
||||
layerState._viewer = viewer;
|
||||
layerState._catalog = new Map([
|
||||
[ISS_NORAD, { name: 'ISS (ZARYA)', satrec, group: 'stations' }],
|
||||
]);
|
||||
layerState._points = new Map([[ISS_NORAD, point]]);
|
||||
layerState._orbitPaths = new Map([
|
||||
[
|
||||
ISS_NORAD,
|
||||
{
|
||||
primitive: { show: true, modelMatrix: new Cesium.Matrix4() },
|
||||
gmstAtBake: 0,
|
||||
},
|
||||
],
|
||||
]);
|
||||
layerState._trackedNorad = null;
|
||||
layerState._trackedEntity = null;
|
||||
if (!preservePending) parts.tracking._cancelPendingTrackingRestore();
|
||||
layerState._trackedFrameNumber = -1;
|
||||
layerState._trackedFrameGeo = null;
|
||||
layerState._enabled = true;
|
||||
layerState._params = {
|
||||
catalog: 'core',
|
||||
showPoints: true,
|
||||
showOrbits: true,
|
||||
};
|
||||
layerState._overlayHost = overlayHost || layerState.DEFAULT_OVERLAY_HOST;
|
||||
parts.labels._syncIssOverlay();
|
||||
}
|
||||
|
||||
/** Exercise production ISS tracking from the cached catalog and point. */
|
||||
|
||||
function _trackIssForTest() {
|
||||
parts.tracking._trackSatellite(ISS_NORAD);
|
||||
return layerState._trackedEntity;
|
||||
}
|
||||
|
||||
/** Return the deferred restore target held by the production tracker. */
|
||||
|
||||
function _pendingSatelliteTrackingRestoreForTest() {
|
||||
return layerState._pendingTrackingRestore?.id ?? null;
|
||||
}
|
||||
|
||||
/** Exercise the production deferred-restore retry after a simulated catalog refresh. */
|
||||
|
||||
function _applyPendingSatelliteTrackingRestoreForTest() {
|
||||
return parts.tracking._applyPendingTrackingRestore();
|
||||
}
|
||||
|
||||
/** Remove a cached catalog row so tests can model a target arriving later. */
|
||||
|
||||
function _removeSatelliteTrackingCandidateForTest(noradId) {
|
||||
const id = Number(noradId);
|
||||
layerState._catalog.delete(id);
|
||||
layerState._points.delete(id);
|
||||
}
|
||||
|
||||
/** Exercise production untrack and restore the default host seam. */
|
||||
|
||||
function _clearSatelliteLabelLifecycleForTest() {
|
||||
parts.tracking._clearTracking();
|
||||
layerState._enabled = false;
|
||||
layerState._overlayHost.clearSource(ISS_OVERLAY_SOURCE_ID);
|
||||
layerState._overlayHost.setVisible(ISS_OVERLAY_SOURCE_ID, false);
|
||||
layerState._overlayHost = layerState.DEFAULT_OVERLAY_HOST;
|
||||
}
|
||||
return {
|
||||
_setTrackedSatelliteRefreshStateForTest,
|
||||
_setSatelliteTrackingRefreshOutcomeForTest,
|
||||
_trackedFrameCartesianForTest,
|
||||
_runSatellitePreRenderForTest,
|
||||
_setDenseCatalogStateForTest,
|
||||
_clearDenseCatalogStateForTest,
|
||||
_catalogGroupForTest,
|
||||
_setSatelliteLabelLifecycleStateForTest,
|
||||
_trackIssForTest,
|
||||
_pendingSatelliteTrackingRestoreForTest,
|
||||
_applyPendingSatelliteTrackingRestoreForTest,
|
||||
_removeSatelliteTrackingCandidateForTest,
|
||||
_clearSatelliteLabelLifecycleForTest,
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user