mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
Merge commit '2b5bbeb' into codex/walkthrough-merge-train
This commit is contained in:
commit
28ea585ab7
3 files changed
+108
-50
No files matched your search
@@ -382,10 +382,9 @@
|
|||||||
"src/layers/launches/model.js",
|
"src/layers/launches/model.js",
|
||||||
"src/layers/launches/selection.js",
|
"src/layers/launches/selection.js",
|
||||||
"src/layers/launches/camera.js",
|
"src/layers/launches/camera.js",
|
||||||
"src/layers/satellites/records.js",
|
"src/data/localGeojson.analyst.test.mjs",
|
||||||
"src/data/layerSnapshot.js",
|
"src/data/satellites.analyst.test.mjs",
|
||||||
"src/data/layerSnapshot.test.mjs",
|
"src/data/layerSnapshot.test.mjs",
|
||||||
"src/data/satellitePass.js",
|
|
||||||
"src/data/satellitePass.test.mjs",
|
"src/data/satellitePass.test.mjs",
|
||||||
"src/data/satellites.js",
|
"src/data/satellites.js",
|
||||||
"src/data/rocketLaunches.js",
|
"src/data/rocketLaunches.js",
|
||||||
|
|||||||
@@ -2,10 +2,7 @@
|
|||||||
import { test } from 'node:test';
|
import { test } from 'node:test';
|
||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
import * as Cesium from 'cesium';
|
import * as Cesium from 'cesium';
|
||||||
import {
|
import { createLocalGeoJsonLayer, mapAnalystRecord } from './localGeojson.js';
|
||||||
createLocalGeoJsonLayer,
|
|
||||||
mapAnalystRecord,
|
|
||||||
} from './localGeojson.js';
|
|
||||||
|
|
||||||
const DC_RAW = {
|
const DC_RAW = {
|
||||||
id: '1176042553',
|
id: '1176042553',
|
||||||
@@ -63,12 +60,15 @@ test('infra analyst record: dam maps name, operator, river, output; names stay u
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('infra analyst record: unnamed feature falls back to source id', () => {
|
test('infra analyst record: unnamed feature falls back to source id', () => {
|
||||||
const r = mapAnalystRecord({
|
const r = mapAnalystRecord(
|
||||||
id: 'dc-42',
|
{
|
||||||
lat: 30.2,
|
id: 'dc-42',
|
||||||
lon: -97.7,
|
lat: 30.2,
|
||||||
properties: { tags: { operator: 'Example Cloud' } },
|
lon: -97.7,
|
||||||
}, 'local-datacenters');
|
properties: { tags: { operator: 'Example Cloud' } },
|
||||||
|
},
|
||||||
|
'local-datacenters',
|
||||||
|
);
|
||||||
assert.equal(r.id, 'dc-42');
|
assert.equal(r.id, 'dc-42');
|
||||||
assert.equal(r.name, null);
|
assert.equal(r.name, null);
|
||||||
assert.equal(r.operator, 'Example Cloud');
|
assert.equal(r.operator, 'Example Cloud');
|
||||||
@@ -79,16 +79,20 @@ test('infra analyst record: empty record yields nulls, never NaN/undefined', ()
|
|||||||
assert.equal(r.id, 'Dam');
|
assert.equal(r.id, 'Dam');
|
||||||
for (const [key, value] of Object.entries(r)) {
|
for (const [key, value] of Object.entries(r)) {
|
||||||
assert.notEqual(value, undefined, `${key} must not be undefined`);
|
assert.notEqual(value, undefined, `${key} must not be undefined`);
|
||||||
if (typeof value === 'number') assert.ok(Number.isFinite(value), `${key} must not be NaN`);
|
if (typeof value === 'number')
|
||||||
|
assert.ok(Number.isFinite(value), `${key} must not be NaN`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('infra analyst record: output is JSON-safe (no Cesium types leak)', () => {
|
test('infra analyst record: output is JSON-safe (no Cesium types leak)', () => {
|
||||||
const r = mapAnalystRecord({
|
const r = mapAnalystRecord(
|
||||||
...DAM_RAW,
|
{
|
||||||
entity: {},
|
...DAM_RAW,
|
||||||
position: { x: 1 },
|
entity: {},
|
||||||
}, 'local-dams');
|
position: { x: 1 },
|
||||||
|
},
|
||||||
|
'local-dams',
|
||||||
|
);
|
||||||
assert.deepEqual(JSON.parse(JSON.stringify(r)), r);
|
assert.deepEqual(JSON.parse(JSON.stringify(r)), r);
|
||||||
assert.equal('entity' in r, false);
|
assert.equal('entity' in r, false);
|
||||||
assert.equal('position' in r, false);
|
assert.equal('position' in r, false);
|
||||||
@@ -112,25 +116,37 @@ test('infra getAnalystRecords: enabled layer snapshots loaded stems; disable ret
|
|||||||
globalThis.fetch = async () => ({
|
globalThis.fetch = async () => ({
|
||||||
ok: true,
|
ok: true,
|
||||||
status: 200,
|
status: 200,
|
||||||
text: async () => JSON.stringify({
|
text: async () =>
|
||||||
type: 'Feature',
|
JSON.stringify({
|
||||||
id: 'runtime-dam',
|
type: 'Feature',
|
||||||
properties: {
|
id: 'runtime-dam',
|
||||||
name: 'Runtime Dam',
|
properties: {
|
||||||
output: '12 MW',
|
name: 'Runtime Dam',
|
||||||
tags: { associated_river: 'Test River', operator: 'Test Hydro' },
|
output: '12 MW',
|
||||||
},
|
tags: { associated_river: 'Test River', operator: 'Test Hydro' },
|
||||||
geometry: {
|
},
|
||||||
type: 'Polygon',
|
geometry: {
|
||||||
coordinates: [[[-97.70, 30.20], [-97.69, 30.20], [-97.69, 30.21], [-97.70, 30.20]]],
|
type: 'Polygon',
|
||||||
},
|
coordinates: [
|
||||||
}),
|
[
|
||||||
|
[-97.7, 30.2],
|
||||||
|
[-97.69, 30.2],
|
||||||
|
[-97.69, 30.21],
|
||||||
|
[-97.7, 30.2],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
const viewer = {
|
const viewer = {
|
||||||
selectedEntity: undefined,
|
selectedEntity: undefined,
|
||||||
dataSources: {
|
dataSources: {
|
||||||
add(dataSource) { return dataSource; },
|
add(dataSource) {
|
||||||
remove() { return true; },
|
return dataSource;
|
||||||
|
},
|
||||||
|
remove() {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
camera: {
|
camera: {
|
||||||
positionWC: Cesium.Cartesian3.fromDegrees(-97.695, 30.205, 100_000),
|
positionWC: Cesium.Cartesian3.fromDegrees(-97.695, 30.205, 100_000),
|
||||||
@@ -142,9 +158,13 @@ test('infra getAnalystRecords: enabled layer snapshots loaded stems; disable ret
|
|||||||
canvas: { clientWidth: 800, clientHeight: 600 },
|
canvas: { clientWidth: 800, clientHeight: 600 },
|
||||||
preRender: new MockLayerEvent(),
|
preRender: new MockLayerEvent(),
|
||||||
sampleHeightSupported: false,
|
sampleHeightSupported: false,
|
||||||
sampleHeight() { return undefined; },
|
sampleHeight() {
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
screenSpaceCameraController: { enableInputs: true },
|
screenSpaceCameraController: { enableInputs: true },
|
||||||
pick() { return null; },
|
pick() {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
requestRender() {},
|
requestRender() {},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -155,10 +175,17 @@ test('infra getAnalystRecords: enabled layer snapshots loaded stems; disable ret
|
|||||||
color: '#0088ff',
|
color: '#0088ff',
|
||||||
overlayHost: { setVisible() {}, setEntries() {}, clearSource() {} },
|
overlayHost: { setVisible() {}, setEntries() {}, clearSource() {} },
|
||||||
projectToWindow: () => ({ x: 400, y: 300 }),
|
projectToWindow: () => ({ x: 400, y: 300 }),
|
||||||
screenSpaceEventHandlerFactory: () => ({ setInputAction() {}, destroy() {} }),
|
screenSpaceEventHandlerFactory: () => ({
|
||||||
|
setInputAction() {},
|
||||||
|
destroy() {},
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
assert.deepEqual(layer.getAnalystRecords(), [], 'unenabled layer has no analyst records');
|
assert.deepEqual(
|
||||||
|
layer.getAnalystRecords(),
|
||||||
|
[],
|
||||||
|
'unenabled layer has no analyst records',
|
||||||
|
);
|
||||||
await layer.enable(viewer);
|
await layer.enable(viewer);
|
||||||
const rows = layer.getAnalystRecords();
|
const rows = layer.getAnalystRecords();
|
||||||
assert.equal(rows.length, 1);
|
assert.equal(rows.length, 1);
|
||||||
@@ -169,13 +196,25 @@ test('infra getAnalystRecords: enabled layer snapshots loaded stems; disable ret
|
|||||||
assert.equal(rows[0].output, '12 MW');
|
assert.equal(rows[0].output, '12 MW');
|
||||||
assert.ok(Number.isFinite(rows[0].lat) && Number.isFinite(rows[0].lon));
|
assert.ok(Number.isFinite(rows[0].lat) && Number.isFinite(rows[0].lon));
|
||||||
assert.deepEqual(JSON.parse(JSON.stringify(rows[0])), rows[0]);
|
assert.deepEqual(JSON.parse(JSON.stringify(rows[0])), rows[0]);
|
||||||
assert.equal(layer.getAnalystRecords(0).length, 1, 'non-finite/zero cap still returns at least one');
|
assert.equal(
|
||||||
|
layer.getAnalystRecords(0).length,
|
||||||
|
1,
|
||||||
|
'non-finite/zero cap still returns at least one',
|
||||||
|
);
|
||||||
|
|
||||||
layer.disable(viewer);
|
layer.disable(viewer);
|
||||||
assert.deepEqual(layer.getAnalystRecords(), [], 'disable keeps stems but analyst snapshot is empty');
|
assert.deepEqual(
|
||||||
|
layer.getAnalystRecords(),
|
||||||
|
[],
|
||||||
|
'disable keeps stems but analyst snapshot is empty',
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
layer.destroy(viewer);
|
layer.destroy(viewer);
|
||||||
assert.deepEqual(layer.getAnalystRecords(), [], 'destroy releases analyst records');
|
assert.deepEqual(
|
||||||
|
layer.getAnalystRecords(),
|
||||||
|
[],
|
||||||
|
'destroy releases analyst records',
|
||||||
|
);
|
||||||
globalThis.fetch = originalFetch;
|
globalThis.fetch = originalFetch;
|
||||||
if (originalWindow === undefined) delete globalThis.window;
|
if (originalWindow === undefined) delete globalThis.window;
|
||||||
else globalThis.window = originalWindow;
|
else globalThis.window = originalWindow;
|
||||||
|
|||||||
@@ -11,8 +11,10 @@ import satellitesLayer, {
|
|||||||
|
|
||||||
const ISS_NORAD = 25544;
|
const ISS_NORAD = 25544;
|
||||||
|
|
||||||
const ISS_L1 = '1 25544U 98067A 08264.51782528 -.00002182 00000-0 -11606-4 0 2927';
|
const ISS_L1 =
|
||||||
const ISS_L2 = '2 25544 51.6416 247.4627 0006703 130.5360 325.0288 15.72125391563537';
|
'1 25544U 98067A 08264.51782528 -.00002182 00000-0 -11606-4 0 2927';
|
||||||
|
const ISS_L2 =
|
||||||
|
'2 25544 51.6416 247.4627 0006703 130.5360 325.0288 15.72125391563537';
|
||||||
|
|
||||||
const FULL_RAW = {
|
const FULL_RAW = {
|
||||||
noradId: 25544,
|
noradId: 25544,
|
||||||
@@ -70,12 +72,17 @@ test('satellite analyst record: empty record yields nulls, never NaN/undefined',
|
|||||||
assert.equal(r.satelliteClass, null);
|
assert.equal(r.satelliteClass, null);
|
||||||
for (const [key, value] of Object.entries(r)) {
|
for (const [key, value] of Object.entries(r)) {
|
||||||
assert.notEqual(value, undefined, `${key} must not be undefined`);
|
assert.notEqual(value, undefined, `${key} must not be undefined`);
|
||||||
if (typeof value === 'number') assert.ok(Number.isFinite(value), `${key} must not be NaN`);
|
if (typeof value === 'number')
|
||||||
|
assert.ok(Number.isFinite(value), `${key} must not be NaN`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('satellite analyst record: output is JSON-safe (no Cesium types leak)', () => {
|
test('satellite analyst record: output is JSON-safe (no Cesium types leak)', () => {
|
||||||
const r = mapAnalystRecord({ ...FULL_RAW, position: { x: 1 }, satrec: { dummy: true } });
|
const r = mapAnalystRecord({
|
||||||
|
...FULL_RAW,
|
||||||
|
position: { x: 1 },
|
||||||
|
satrec: { dummy: true },
|
||||||
|
});
|
||||||
assert.deepEqual(JSON.parse(JSON.stringify(r)), r);
|
assert.deepEqual(JSON.parse(JSON.stringify(r)), r);
|
||||||
assert.equal('position' in r, false);
|
assert.equal('position' in r, false);
|
||||||
assert.equal('satrec' in r, false);
|
assert.equal('satrec' in r, false);
|
||||||
@@ -88,7 +95,9 @@ test('satellite getAnalystRecords: disabled or empty catalog returns []', () =>
|
|||||||
|
|
||||||
test('satellite getAnalystRecords: core rows beat dense extras under the cap', () => {
|
test('satellite getAnalystRecords: core rows beat dense extras under the cap', () => {
|
||||||
const satrec = twoline2satrec(ISS_L1, ISS_L2);
|
const satrec = twoline2satrec(ISS_L1, ISS_L2);
|
||||||
const point = { position: Cesium.Cartesian3.fromDegrees(-97.7, 30.2, 420_000) };
|
const point = {
|
||||||
|
position: Cesium.Cartesian3.fromDegrees(-97.7, 30.2, 420_000),
|
||||||
|
};
|
||||||
_setTrackedSatelliteRefreshStateForTest({
|
_setTrackedSatelliteRefreshStateForTest({
|
||||||
noradId: ISS_NORAD,
|
noradId: ISS_NORAD,
|
||||||
name: 'ISS (ZARYA)',
|
name: 'ISS (ZARYA)',
|
||||||
@@ -110,22 +119,33 @@ test('satellite getAnalystRecords: core rows beat dense extras under the cap', (
|
|||||||
name: 'GPS BIIR-2',
|
name: 'GPS BIIR-2',
|
||||||
satrec,
|
satrec,
|
||||||
group: 'gps-ops',
|
group: 'gps-ops',
|
||||||
point: { position: Cesium.Cartesian3.fromDegrees(-100, 10, 20_200_000) },
|
point: {
|
||||||
|
position: Cesium.Cartesian3.fromDegrees(-100, 10, 20_200_000),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
const capped = satellitesLayer.getAnalystRecords(2);
|
const capped = satellitesLayer.getAnalystRecords(2);
|
||||||
assert.equal(capped.length, 2);
|
assert.equal(capped.length, 2);
|
||||||
assert.deepEqual(capped.map((r) => r.noradId), ['25544', '24876']);
|
assert.deepEqual(
|
||||||
assert.equal(capped.some((r) => r.group === 'dense'), false);
|
capped.map((r) => r.noradId),
|
||||||
|
['25544', '24876'],
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
capped.some((r) => r.group === 'dense'),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
const all = satellitesLayer.getAnalystRecords(10);
|
const all = satellitesLayer.getAnalystRecords(10);
|
||||||
assert.equal(all.length, 3);
|
assert.equal(all.length, 3);
|
||||||
assert.equal(all[2].noradId, '99999');
|
assert.equal(all[2].noradId, '99999');
|
||||||
assert.equal(all[2].satelliteClass, 'COMMS · STARLINK');
|
assert.equal(all[2].satelliteClass, 'COMMS · STARLINK');
|
||||||
for (const row of all) {
|
for (const row of all) {
|
||||||
assert.ok(Number.isFinite(row.lat) && Number.isFinite(row.lon), `${row.id} needs a geodetic position`);
|
assert.ok(
|
||||||
|
Number.isFinite(row.lat) && Number.isFinite(row.lon),
|
||||||
|
`${row.id} needs a geodetic position`,
|
||||||
|
);
|
||||||
assert.deepEqual(JSON.parse(JSON.stringify(row)), row);
|
assert.deepEqual(JSON.parse(JSON.stringify(row)), row);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Reference in new issue
Block a user