mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 02:14:01 +00:00
180 lines
6.0 KiB
JavaScript
180 lines
6.0 KiB
JavaScript
import { DEFAULT_AIS_RUNTIME } from './policy.js';
|
|
|
|
export function createTesting({
|
|
vesselState,
|
|
services,
|
|
parts: components,
|
|
layer,
|
|
options,
|
|
}) {
|
|
const { state } = vesselState;
|
|
const aisLiveVesselsLayer = layer;
|
|
|
|
/**
|
|
* Bind the production interaction callbacks to mockable viewer/handler
|
|
* surfaces. Test-only seam; behavior is shared with installInteraction().
|
|
* @param {Object} viewer - Viewer-like object with scene.pick().
|
|
* @param {Object} handler - Handler-like object with setInputAction().
|
|
* @param {Object} keyTarget - EventTarget-like object with add/removeEventListener().
|
|
* @returns {void}
|
|
*/
|
|
|
|
function _bindVesselInteractionForTest(viewer, handler, keyTarget) {
|
|
components.selection.bindVesselInteraction(viewer, handler, keyTarget);
|
|
}
|
|
|
|
/**
|
|
* Prime the minimum live state needed by interaction/lifecycle wire tests.
|
|
* @param {Object} [options={}] - Test state values.
|
|
* @returns {void}
|
|
*/
|
|
|
|
function _setVesselStateForTest(options = {}) {
|
|
components.lifecycle.resetState();
|
|
const records = Array.isArray(options.records) ? options.records : [];
|
|
state.viewer = options.viewer || null;
|
|
state.enabled = options.enabled !== false;
|
|
state.loaded = options.loaded === true;
|
|
state.loading = options.loading === true;
|
|
state.stale = options.stale === true;
|
|
state.error = options.error || null;
|
|
state.lastUpdate = options.lastUpdate ?? null;
|
|
state.vesselRecords = records;
|
|
state.count = records.length;
|
|
state.vesselMap = new Map(
|
|
records
|
|
.filter((record) => record?.mmsi)
|
|
.map((record) => [record.mmsi, record]),
|
|
);
|
|
state.selectedRecord = options.selectedRecord || null;
|
|
state.billboardCollection = options.billboardCollection || { remove() {} };
|
|
state.trail = options.trail || null;
|
|
state.trailMmsi = options.trailMmsi || null;
|
|
state.trailPositions = Array.isArray(options.trailPositions)
|
|
? [...options.trailPositions]
|
|
: [];
|
|
state.transportStatus = options.transportStatus || null;
|
|
state.lastMessageAt = options.lastMessageAt ?? null;
|
|
state.rawRowCount = Number.isFinite(options.rawRowCount)
|
|
? options.rawRowCount
|
|
: 0;
|
|
state.acceptedRowCount = Number.isFinite(options.acceptedRowCount)
|
|
? options.acceptedRowCount
|
|
: records.length;
|
|
state.firstConnectPhase = options.firstConnectPhase || 'idle';
|
|
state.firstConnectStartedAt = options.firstConnectStartedAt ?? null;
|
|
state.firstConnectDeadline = options.firstConnectDeadline ?? null;
|
|
state.interactionHandlerFactory = options.interactionHandlerFactory || null;
|
|
state.interactionKeyTarget = options.interactionKeyTarget || null;
|
|
}
|
|
|
|
/** Inject a host recorder for lifecycle/contract tests; null restores production. */
|
|
|
|
function _setVesselOverlayHostForTest(host = null) {
|
|
vesselState._vesselOverlayHost =
|
|
host || vesselState.DEFAULT_VESSEL_OVERLAY_HOST;
|
|
}
|
|
|
|
/** Exercise the production selector/publisher through a test-owned state. */
|
|
|
|
function _updateVesselCardsForTest(records = []) {
|
|
components.rendering.updateClusteredLabels(records);
|
|
}
|
|
|
|
/**
|
|
* Reconcile AIS rows through the production lifecycle. Test-only seam.
|
|
* @param {Object} viewer - Viewer-like object.
|
|
* @param {Array<Object>} rows - Raw AIS rows.
|
|
* @returns {void}
|
|
*/
|
|
|
|
function _reconcileVesselsForTest(viewer, rows) {
|
|
components.store.reconcileVessels(viewer, rows);
|
|
}
|
|
|
|
/** Apply one server snapshot through the production pre-reconcile health gate. */
|
|
|
|
function _applyAisFeedSnapshotForTest(viewer, payload) {
|
|
return components.ingestion.applyAisFeedSnapshot(viewer, payload);
|
|
}
|
|
|
|
/** Exercise the request-owned live loader with a test-controlled fetch. */
|
|
|
|
function _loadLivePositionsForTest(viewer) {
|
|
return components.ingestion.loadLivePositions(viewer);
|
|
}
|
|
|
|
/** Start the production first-connect grace state without installing UI. */
|
|
|
|
function _beginAisSessionForTest() {
|
|
components.lifecycle.beginAisSession();
|
|
}
|
|
|
|
/** Inject a deterministic clock/scheduler; null restores production runtime. */
|
|
|
|
function _setAisRuntimeForTest(runtime = null) {
|
|
components.lifecycle.clearFirstConnectTimer();
|
|
vesselState._aisRuntime = runtime
|
|
? {
|
|
now: runtime.now,
|
|
setTimeout: runtime.setTimeout,
|
|
clearTimeout: runtime.clearTimeout,
|
|
}
|
|
: DEFAULT_AIS_RUNTIME;
|
|
}
|
|
|
|
/** Read feed-health fields without exposing mutable production state. */
|
|
|
|
function _getVesselFeedStateForTest() {
|
|
const stats = aisLiveVesselsLayer.getStats();
|
|
return {
|
|
count: state.count,
|
|
loaded: state.loaded,
|
|
loading: stats.loading,
|
|
loadingLabel: stats.loadingLabel,
|
|
stale: state.stale,
|
|
error: state.error,
|
|
status: stats.status,
|
|
lastUpdate: state.lastUpdate,
|
|
transportStatus: state.transportStatus,
|
|
lastMessageAt: state.lastMessageAt,
|
|
rawRowCount: state.rawRowCount,
|
|
acceptedRowCount: state.acceptedRowCount,
|
|
selectedMmsi: state.selectedRecord?.mmsi || null,
|
|
trailMmsi: state.trailMmsi,
|
|
trailPositionCount: state.trailPositions.length,
|
|
sessionId: state.sessionId,
|
|
firstConnectPhase: state.firstConnectPhase,
|
|
firstConnectStartedAt: state.firstConnectStartedAt,
|
|
firstConnectDeadline: state.firstConnectDeadline,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Read lifecycle ownership state without exposing the mutable state object.
|
|
* Test-only seam.
|
|
* @returns {{trailMmsi: string|null, trailPositionCount: number, vesselCount: number}}
|
|
*/
|
|
|
|
function _getVesselStateForTest() {
|
|
return {
|
|
trailMmsi: state.trailMmsi,
|
|
trailPositionCount: state.trailPositions.length,
|
|
vesselCount: state.vesselMap.size,
|
|
};
|
|
}
|
|
return {
|
|
_bindVesselInteractionForTest,
|
|
_setVesselStateForTest,
|
|
_setVesselOverlayHostForTest,
|
|
_updateVesselCardsForTest,
|
|
_reconcileVesselsForTest,
|
|
_applyAisFeedSnapshotForTest,
|
|
_loadLivePositionsForTest,
|
|
_beginAisSessionForTest,
|
|
_setAisRuntimeForTest,
|
|
_getVesselFeedStateForTest,
|
|
_getVesselStateForTest,
|
|
};
|
|
}
|