Files
gods-eye-view/src/data/fireAnchors.test.mjs
T
Bilawal Sidhu b6da93b8ac release: v0.1.0 — one-click install, keyless boot, in-app Provider Settings (#142)
The first formal release.

- One-click install via Pinokio; keyless boot lands on a live Esri World
  Imagery satellite globe with keyless terrain, with automatic OSM fallback
  and graceful degradation when terrain is unavailable.
- Provider Settings (the POWER UP panel): add, replace, or remove API keys
  inside the app; credential files made owner-only before any secret is
  written; external keys shown read-only; the panel refuses shared or proxied
  servers.
- Keyless capability responses for the optional HUD summary and place search.
- Aircraft-identity voice answers cover operator, type, and route, and say so
  plainly when enrichment is unavailable.
- README rewritten keyless-first; concise 0.1.0 changelog section; CI
  workflow included.

Gates: 2,672 unit tests pass / 0 fail, build clean, tracking regression
108/108, map-source tray QA pass, setup doctor ready.
2026-08-31 17:49:45 -05:00

162 lines
6.3 KiB
JavaScript

// src/data/fireAnchors.test.mjs — DEM ground anchors for rendered FIRMS
// detections (owner field finding 2026-07-21: close-zoom fire dots read as
// buried under high terrain because anchors sat at ellipsoid height 0).
//
// Locks the module's two jobs:
// fireAnchorHeight(lat, lon) — synchronous warm-cache read: shared
// ground floor + lift, or 0 when the floor isn't warm (the pre-fix anchor).
// warmFireAnchorFloors(points) — batched, sequential (never concurrent)
// resolve of the cold floor cells behind a rendered detection set.
// Resolves true only when at least one requested point actually gained a
// warm floor — a failed resolve reports false so render → warm → re-render
// chains terminate instead of looping against a down proxy.
//
// `fetch` is injected via `globalThis.fetch` (no real network), same pattern
// as terrainHeights.test.mjs. The terrainHeights/groundFloor module caches
// persist across tests in this file, so each test uses distinct coordinates.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import {
FIRE_ANCHOR_LIFT_M,
fireAnchorHeight,
warmFireAnchorFloors,
_resetFireAnchorsForTest,
} from './fireAnchors.js';
import { reportMeshFloorCell, setMeshFloorPreferred } from './groundFloor.js';
/** Installs a fake fetch for the duration of `fn`, restoring the original after. */
async function withFakeFetch(fakeFetch, fn) {
const original = globalThis.fetch;
globalThis.fetch = fakeFetch;
try {
return await fn();
} finally {
globalThis.fetch = original;
}
}
/** Parses the `points=lon,lat;…` query of a /api/terrain/heights request URL. */
function parsePoints(url) {
const raw = decodeURIComponent(String(url).split('points=')[1] || '');
return raw.split(';').filter(Boolean).map((pair) => {
const [lon, lat] = pair.split(',').map(Number);
return { lon, lat };
});
}
/** Fake proxy answering ellipsoid = lon + lat per requested point. */
function echoFetch(log) {
return async (url) => {
const points = parsePoints(url);
log.push(points);
return {
ok: true,
status: 200,
json: async () => ({
results: points.map(({ lon, lat }) => ({ lon, lat, elevation: 0, geoid: 0, ellipsoid: lon + lat })),
}),
};
};
}
test('fireAnchorHeight: unknown floor anchors at 0 (pre-fix behavior preserved)', () => {
_resetFireAnchorsForTest();
assert.equal(fireAnchorHeight(10.001, 10.001), 0);
});
test('fireAnchorHeight: warm shared ground floor anchors at floor + lift', () => {
_resetFireAnchorsForTest();
setMeshFloorPreferred(true);
// Seed via the mesh-cell path — proves fires read the SAME choke point
// (cachedGroundFloor) every other ground-adjacent consumer uses.
reportMeshFloorCell(51.301, -122.401, 1400);
assert.equal(fireAnchorHeight(51.3012, -122.4008), 1400 + FIRE_ANCHOR_LIFT_M);
});
test('warmFireAnchorFloors: one batched request, deduped to coarse cells', async () => {
_resetFireAnchorsForTest();
const log = [];
await withFakeFetch(echoFetch(log), async () => {
const warmed = await warmFireAnchorFloors([
{ lat: 20.0001, lon: 30.0001 }, // same ~111 m cell as the next point
{ lat: 20.0004, lon: 30.0004 },
{ lat: 20.101, lon: 30.101 }, // distinct cell
]);
assert.equal(warmed, true);
assert.equal(log.length, 1, 'one network request for the whole batch');
assert.equal(log[0].length, 2, 'two unique coarse cells, not three points');
});
// The warm floor is immediately readable at full precision…
assert.equal(fireAnchorHeight(20.0001, 30.0001), 50 + FIRE_ANCHOR_LIFT_M);
// …and for every other detection sharing the cell.
assert.equal(fireAnchorHeight(20.0004, 30.0004), 50 + FIRE_ANCHOR_LIFT_M);
});
test('warmFireAnchorFloors: warm cells never refetch (one lookup per fire ever)', async () => {
_resetFireAnchorsForTest();
const log = [];
await withFakeFetch(echoFetch(log), async () => {
await warmFireAnchorFloors([{ lat: 21.001, lon: 31.001 }]);
assert.equal(log.length, 1);
const warmedAgain = await warmFireAnchorFloors([
{ lat: 21.001, lon: 31.001 },
{ lat: 21.0012, lon: 31.0011 }, // same cell, different detection
]);
assert.equal(warmedAgain, false, 'nothing was cold, so nothing warmed');
assert.equal(log.length, 1, 'no second network request');
});
});
test('warmFireAnchorFloors: overlapping calls run sequentially, never concurrently', async () => {
_resetFireAnchorsForTest();
let release;
const gate = new Promise((resolve) => { release = resolve; });
let concurrent = 0;
let maxConcurrent = 0;
const log = [];
await withFakeFetch(async (url) => {
concurrent += 1;
maxConcurrent = Math.max(maxConcurrent, concurrent);
const points = parsePoints(url);
log.push(points);
await gate;
concurrent -= 1;
return {
ok: true,
status: 200,
json: async () => ({
results: points.map(({ lon, lat }) => ({ lon, lat, elevation: 0, geoid: 0, ellipsoid: lon + lat })),
}),
};
}, async () => {
const first = warmFireAnchorFloors([{ lat: 40.001, lon: 50.001 }]);
// Second call arrives while the first is in flight: overlaps the first
// cell and adds one new one.
const second = warmFireAnchorFloors([
{ lat: 40.001, lon: 50.001 },
{ lat: 41.201, lon: 51.201 },
]);
release();
const [warmedFirst, warmedSecond] = await Promise.all([first, second]);
assert.equal(warmedFirst, true);
assert.equal(warmedSecond, true, 'the new cell warmed in the follow-up batch');
assert.equal(maxConcurrent, 1, 'batches never overlap on the wire');
assert.equal(log.length, 2);
assert.equal(log[1].length, 1, 'follow-up batch re-filters: only the still-cold cell goes out');
});
});
test('warmFireAnchorFloors: proxy failure reports false (re-render chain terminates)', async () => {
_resetFireAnchorsForTest();
let calls = 0;
await withFakeFetch(async () => {
calls += 1;
throw new Error('proxy down');
}, async () => {
const warmed = await warmFireAnchorFloors([{ lat: 22.501, lon: 32.501 }]);
assert.equal(warmed, false, 'geoid fallback is NOT a warm floor for anchoring');
assert.ok(calls >= 1);
});
assert.equal(fireAnchorHeight(22.501, 32.501), 0, 'anchor stays at 0 until a real floor lands');
});