From 5c3f558766fe45a92ef7e2042c30ac6169fc25bc Mon Sep 17 00:00:00 2001 From: Bilawal Sidhu Date: Tue, 15 Sep 2026 02:18:42 -0500 Subject: [PATCH] fix: verify bounded analyst scope and empty satellite identity --- src/data/analystEngine.test.mjs | 14 ++++++++++++++ src/data/localGeojson.analyst.test.mjs | 1 + src/layers/satellites/records.js | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/data/analystEngine.test.mjs b/src/data/analystEngine.test.mjs index 4456c0a12..4f56c834b 100644 --- a/src/data/analystEngine.test.mjs +++ b/src/data/analystEngine.test.mjs @@ -248,3 +248,17 @@ test('helpers: haversine sanity + scope radius', () => { const scoped = applyScope(FLIGHTS, { kind: 'radius' }, { center: { lat: 30.27, lon: -97.74 }, km: 50 }); assert.deepEqual(scoped.map((f) => f.id).sort(), ['GND1', 'SWA1']); }); + +test('bounded loaded cohorts disclose truncation before filtering and retain it on follow-up', async () => { + const engine = createAnalystEngine({ + getRecords: () => [{ id: 'sample dam', lat: 0, lon: 0, name: 'sample' }], + getRecordCoverage: () => ({ basis: 'bounded-loaded-records', recordsExamined: 1, loadedCount: 3000, sourceTruncated: true }), + getViewContext: () => ({ lat: 0, lon: 0, viewRadiusKm: 25 }), + }); + const result = await engine.query({ layers: ['local-dams'], scope: { kind: 'anywhere' }, sortBy: 'distance' }); + assert.equal(result.count, 1); + assert.equal(result.coverage.layersQueried[0].sourceTruncated, true); + assert.match(result.coverage.note, /omitted records may change the nearest item or count/); + const followUp = await engine.query({ followUp: true }); + assert.equal(followUp.coverage.layersQueried[0].loadedCount, 3000); +}); diff --git a/src/data/localGeojson.analyst.test.mjs b/src/data/localGeojson.analyst.test.mjs index c695004f6..d1cc74343 100644 --- a/src/data/localGeojson.analyst.test.mjs +++ b/src/data/localGeojson.analyst.test.mjs @@ -175,6 +175,7 @@ test('infra getAnalystRecords: enabled layer snapshots loaded stems; disable ret assert.deepEqual(layer.getAnalystRecords(), [], 'disable keeps stems but analyst snapshot is empty'); } finally { layer.destroy(viewer); + assert.deepEqual(layer.getAnalystRecords(), [], 'destroy releases analyst records'); globalThis.fetch = originalFetch; if (originalWindow === undefined) delete globalThis.window; else globalThis.window = originalWindow; diff --git a/src/layers/satellites/records.js b/src/layers/satellites/records.js index 962e52f86..7b4e6603a 100644 --- a/src/layers/satellites/records.js +++ b/src/layers/satellites/records.js @@ -15,7 +15,7 @@ import { ISS_NORAD } from './policy.js'; export function mapAnalystRecord(raw) { const num = (v) => (Number.isFinite(v) ? v : null); const text = (v) => { const t = String(v ?? '').trim(); return t || null; }; - const noradNum = Number(raw?.noradId); + const noradNum = raw?.noradId == null || raw.noradId === '' ? NaN : Number(raw.noradId); const noradId = Number.isFinite(noradNum) ? String(Math.trunc(noradNum)) : text(raw?.noradId); const name = text(raw?.name); const group = text(raw?.group);