mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 18:34:02 +00:00
The flight, military and vessel feeds were named after the providers the bundled server uses (/api/opensky, /api/adsblol/mil, /api/ais-live and their track routes; createOpenSkySource, createAdsbLolSource, createAisStreamSource). Any server should be able to answer a feed from its own provider, so the feeds are now: /api/flights /api/flights/track?icao24= /api/military /api/military/track?hex= /api/vessels /api/vessels/track?mmsi= with createFlightSource, createMilitarySource and createVesselSource. The old routes are removed. Each server names its provider in X-Feed-Source (the bundled server sends OpenSky Network, adsb.lol and AISStream, so its attribution is unchanged) and the military feed's cache state and age in X-Feed-Cache and X-Feed-Age-Ms. Sources report the provider the server names and fall back to the feed's name.
59 lines
2.0 KiB
JavaScript
59 lines
2.0 KiB
JavaScript
// src/data/aisLiveVessels.analyst.test.mjs
|
|
// Focused tests for the pure analyst-record mapper (analyst query engine seam).
|
|
// Separate file from aisLiveVessels.test.mjs (feed-status helper) by design.
|
|
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { mapAnalystRecord } from './aisLiveVessels.js';
|
|
|
|
const FULL_RECORD = {
|
|
mmsi: '353136000',
|
|
name: 'EVER GIVEN',
|
|
lat: 29.55,
|
|
lon: -94.98,
|
|
speed: 12.3,
|
|
course: 214.0,
|
|
type: 'Cargo',
|
|
destination: 'OAKLAND',
|
|
};
|
|
|
|
test('ais analyst record: full record maps every contract field', () => {
|
|
const r = mapAnalystRecord(FULL_RECORD);
|
|
assert.deepEqual(r, {
|
|
id: 'EVER GIVEN',
|
|
mmsi: '353136000',
|
|
name: 'EVER GIVEN',
|
|
lat: 29.55,
|
|
lon: -94.98,
|
|
speedKts: 12.3,
|
|
courseDeg: 214.0,
|
|
shipType: 'Cargo',
|
|
destination: 'OAKLAND',
|
|
navStatus: null, // /api/vessels does not surface NavigationalStatus
|
|
});
|
|
});
|
|
|
|
test('ais analyst record: nameless vessel falls back to mmsi id', () => {
|
|
const r = mapAnalystRecord({ ...FULL_RECORD, name: ' ' });
|
|
assert.equal(r.id, '353136000');
|
|
assert.equal(r.name, null);
|
|
});
|
|
|
|
test('ais analyst record: empty strings and NaN become null, never undefined', () => {
|
|
const r = mapAnalystRecord({ mmsi: '', name: 'TUG', speed: NaN, type: '', destination: '' });
|
|
assert.equal(r.mmsi, null);
|
|
assert.equal(r.speedKts, null);
|
|
assert.equal(r.shipType, null);
|
|
assert.equal(r.destination, null);
|
|
for (const [key, value] of Object.entries(r)) {
|
|
assert.notEqual(value, undefined, `${key} must not be undefined`);
|
|
if (typeof value === 'number') assert.ok(Number.isFinite(value), `${key} must not be NaN`);
|
|
}
|
|
});
|
|
|
|
test('ais analyst record: output is JSON-safe (no Cesium types leak from the record)', () => {
|
|
// Real records carry Cesium positions/billboards — the mapper must not copy them.
|
|
const r = mapAnalystRecord({ ...FULL_RECORD, position: { x: 1 }, billboard: {}, normal: {} });
|
|
assert.deepEqual(JSON.parse(JSON.stringify(r)), r);
|
|
assert.equal('position' in r, false);
|
|
});
|