feat(foundry): close the operational map data loop
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import test from "node:test";
|
||||
import { normalizeMapPresentationProfile, normalizeMapPresentationProfiles } from "./map-presentation-profile.mjs";
|
||||
|
||||
const registry = JSON.parse(await readFile(new URL("../registry/map-presentation-profiles.json", import.meta.url), "utf8"));
|
||||
const mapFixtureSource = await readFile(new URL("../apps/catalog/src/MapFixturePreview.tsx", import.meta.url), "utf8");
|
||||
const catalogStyles = await readFile(new URL("../apps/catalog/src/styles.css", import.meta.url), "utf8");
|
||||
|
||||
test("canonical moving-object profile is provider-neutral and internally consistent", () => {
|
||||
assert.equal(registry.schemaVersion, "nodedc.map-presentation-profiles/v1");
|
||||
const profiles = normalizeMapPresentationProfiles(registry.profiles);
|
||||
assert.equal(profiles.length, 1);
|
||||
const profile = profiles[0];
|
||||
assert.equal(profile.id, "map.moving-object.operational.default");
|
||||
assert.deepEqual(profile.semanticTypes, ["map.moving_object"]);
|
||||
assert.equal(profile.target.variant, "elevated-spike");
|
||||
assert.equal(profile.target.stemHeightMeters, 1500);
|
||||
assert.equal(profile.target.headSizePx, 9);
|
||||
assert.equal(profile.target.stemWidthPx, 5);
|
||||
assert.equal(profile.label.mode, "subject_id");
|
||||
assert.equal(profile.label.sizePx, 18);
|
||||
assert.equal(profile.label.backgroundOpacity, 0.86);
|
||||
assert.equal(profile.styles.find((style) => style.id === "online")?.color, "#86fdb8");
|
||||
assert.equal(profile.styles.find((style) => style.id === "moving")?.color, "#6fb5fb");
|
||||
assert.equal(JSON.stringify(profile).toLowerCase().includes("gelios"), false);
|
||||
assert.deepEqual(profile.facets.map((facet) => facet.field), [
|
||||
"availability_state",
|
||||
"motion_state",
|
||||
]);
|
||||
assert.deepEqual(profile.facets.flatMap((facet) => facet.values.map((value) => value.label)), [
|
||||
"Онлайн",
|
||||
"Офлайн",
|
||||
"В движении",
|
||||
"Стоят",
|
||||
]);
|
||||
assert.equal(JSON.stringify(profile).includes("Неизвестно"), false);
|
||||
});
|
||||
|
||||
test("fleet filter window is one compact vertical list without group rows or All", () => {
|
||||
assert.match(mapFixtureSource, /catalog-map-fixture__target-filter-list/);
|
||||
assert.doesNotMatch(mapFixtureSource, /catalog-map-fixture__target-profile/);
|
||||
assert.doesNotMatch(mapFixtureSource, /catalog-map-fixture__target-facet/);
|
||||
assert.doesNotMatch(mapFixtureSource, />Все <span>/);
|
||||
assert.match(catalogStyles, /\.catalog-map-fixture__target-filter-list\s*\{[\s\S]*grid-template-columns:\s*minmax\(0, 1fr\)/);
|
||||
assert.match(catalogStyles, /\.catalog-map-fixture__target-filter-list button\s*\{[\s\S]*width:\s*100%/);
|
||||
});
|
||||
|
||||
test("profile rejects undeclared state matches and renderer transport", () => {
|
||||
const source = registry.profiles[0];
|
||||
const undeclared = structuredClone(source);
|
||||
undeclared.classes[0].match[0].equals = "provider_magic";
|
||||
assert.throws(() => normalizeMapPresentationProfile(undeclared), /map_presentation_profile_class_condition_not_declared/);
|
||||
|
||||
const transport = structuredClone(source);
|
||||
transport.providerUrl = "https://example.test";
|
||||
assert.throws(() => normalizeMapPresentationProfile(transport), /invalid_map_presentation_profile_fields/);
|
||||
});
|
||||
|
||||
test("legacy pin profiles normalize into the provider-neutral target contract", () => {
|
||||
const legacy = structuredClone(registry.profiles[0]);
|
||||
legacy.pin = legacy.target;
|
||||
delete legacy.target;
|
||||
const normalized = normalizeMapPresentationProfile(legacy);
|
||||
assert.equal(normalized.target.stemHeightMeters, 1500);
|
||||
assert.equal(Object.hasOwn(normalized, "pin"), false);
|
||||
});
|
||||
Reference in New Issue
Block a user