Files
NODEDC_DESIGN_GUIDELINE/scripts/map-grid-lod.test.mjs
T

79 lines
2.7 KiB
JavaScript

import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import test from "node:test";
import {
gridShouldBeVisible,
resolveGridMode,
selectGridLod,
snapGridCenter,
} from "../apps/catalog/src/mapGridPolicy.mjs";
const settings = {
gridVisible: true,
gridLodEnabled: true,
gridLod1MaxHeightKm: 10,
gridLod1StepKm: 1,
gridLod1Mode: "3d",
gridLod2MaxHeightKm: 50,
gridLod2StepKm: 5,
gridLod2Mode: "3d",
gridLod3MaxHeightKm: 180,
gridLod3StepKm: 25,
gridLod3Mode: "3d",
gridLod4MaxHeightKm: 700,
gridLod4StepKm: 100,
gridLod4Mode: "graticule",
gridLod5StepKm: 500,
gridLod5Mode: "graticule",
grid3dEnabled: true,
gridGraticuleEnabled: true,
gridMax3dViewAngleDegrees: 30,
gridAutoDisableHeightKm: 10_000,
gridCenterMode: "camera",
gridTileSizeKm: 10,
};
test("five grid LODs preserve the close 3D and distant graticule contract", () => {
assert.deepEqual(
[5, 40, 120, 500, 2_000].map((height) => {
const band = selectGridLod(settings, height);
return [band.id, band.stepKm, band.mode];
}),
[
["lod-1", 1, "3d"],
["lod-2", 5, "3d"],
["lod-3", 25, "3d"],
["lod-4", 100, "graticule"],
["lod-5", 500, "graticule"],
],
);
});
test("LOD hysteresis holds the previous band around a threshold", () => {
assert.equal(selectGridLod(settings, 10.5, 0).id, "lod-1");
assert.equal(selectGridLod(settings, 10.9, 0).id, "lod-2");
assert.equal(selectGridLod(settings, 9.5, 1).id, "lod-2");
assert.equal(selectGridLod(settings, 9.1, 1).id, "lod-1");
});
test("oblique close view falls back to the graticule without dropping the grid", () => {
assert.equal(resolveGridMode(settings, "3d", 12), "3d");
assert.equal(resolveGridMode(settings, "3d", 48), "graticule");
assert.equal(resolveGridMode({ ...settings, gridGraticuleEnabled: false }, "3d", 48), "hidden");
});
test("grid auto-disable and stable camera tile center are deterministic", () => {
assert.equal(gridShouldBeVisible(settings, 9_999), true);
assert.equal(gridShouldBeVisible(settings, 10_001), false);
const first = snapGridCenter({ latitude: 55.7558, longitude: 37.6173 }, settings);
const second = snapGridCenter({ latitude: 55.76, longitude: 37.62 }, settings);
assert.deepEqual(first, second);
});
test("renderer swaps double-buffered data sources and never clears the live grid first", async () => {
const source = await readFile(new URL("../apps/catalog/src/CesiumMapRenderer.tsx", import.meta.url), "utf8");
assert.match(source, /class GridLayerController/);
assert.match(source, /dataSourceDisplay\.ready/);
assert.doesNotMatch(source, /function rebuildElevatedGrid[\s\S]*?entities\.removeAll\(\)/);
});