91 lines
3.9 KiB
TypeScript
91 lines
3.9 KiB
TypeScript
import type { FeatureCollection } from "geojson";
|
|
import { describe, expect, it } from "vitest";
|
|
import {
|
|
SCADA_ANALYSIS_LAYER_IDS,
|
|
SCADA_ANALYSIS_LEVEL_COLORS,
|
|
createScadaAnalysisCollection,
|
|
parseScadaAnalysisItems,
|
|
scadaAnalysisLayers
|
|
} from "./scada-analysis";
|
|
|
|
describe("SCADA analysis overlay", () => {
|
|
it("uses distinct semantic rings, status indicators, and legible priority labels", () => {
|
|
const casing = scadaAnalysisLayers.find((layer) => layer.id === SCADA_ANALYSIS_LAYER_IDS.casing);
|
|
const level = scadaAnalysisLayers.find((layer) => layer.id === SCADA_ANALYSIS_LAYER_IDS.level);
|
|
const indicator = scadaAnalysisLayers.find((layer) => layer.id === SCADA_ANALYSIS_LAYER_IDS.indicator);
|
|
const label = scadaAnalysisLayers.find((layer) => layer.id === SCADA_ANALYSIS_LAYER_IDS.label);
|
|
expect(SCADA_ANALYSIS_LEVEL_COLORS).toEqual({
|
|
high: "#F43F5E",
|
|
medium: "#F59E0B",
|
|
low: "#10B981",
|
|
unrated: "#8B5CF6"
|
|
});
|
|
expect(casing).toMatchObject({
|
|
type: "circle",
|
|
paint: { "circle-radius": 20, "circle-stroke-color": "#FFFFFF", "circle-stroke-width": 8 }
|
|
});
|
|
expect(JSON.stringify(level)).toContain(SCADA_ANALYSIS_LEVEL_COLORS.high);
|
|
expect(JSON.stringify(level)).toContain(SCADA_ANALYSIS_LEVEL_COLORS.medium);
|
|
expect(JSON.stringify(level)).toContain(SCADA_ANALYSIS_LEVEL_COLORS.low);
|
|
expect(JSON.stringify(level)).toContain(SCADA_ANALYSIS_LEVEL_COLORS.unrated);
|
|
expect(level).toMatchObject({ paint: { "circle-radius": 20, "circle-stroke-width": 5 } });
|
|
expect(indicator).toMatchObject({
|
|
type: "circle",
|
|
paint: {
|
|
"circle-radius": 6,
|
|
"circle-translate": [14, -14],
|
|
"circle-stroke-color": "#FFFFFF",
|
|
"circle-stroke-width": 2
|
|
}
|
|
});
|
|
expect(label).toMatchObject({
|
|
type: "symbol",
|
|
layout: {
|
|
"symbol-sort-key": ["get", "sort_priority"],
|
|
"text-field": ["get", "analysis_label"],
|
|
"text-size": 18,
|
|
"text-font": ["Noto Sans Regular"],
|
|
"text-allow-overlap": false
|
|
},
|
|
paint: { "text-halo-color": "#FFFFFF", "text-halo-width": 4, "text-halo-blur": 0.5 }
|
|
});
|
|
expect(JSON.stringify(label)).toContain("#991B1B");
|
|
expect(JSON.stringify(label)).toContain("#92400E");
|
|
expect(JSON.stringify(label)).toContain("#166534");
|
|
});
|
|
|
|
it("validates one to one hundred unique IDs and fixed levels", () => {
|
|
expect(parseScadaAnalysisItems([{ sensor_id: " MP01 ", level: "high" }])).toEqual([
|
|
{ sensor_id: "MP01", level: "high" }
|
|
]);
|
|
expect(parseScadaAnalysisItems([])).toBeNull();
|
|
expect(parseScadaAnalysisItems([{ sensor_id: "MP01", level: "high" }, { sensor_id: "MP01", level: "low" }])).toBeNull();
|
|
expect(parseScadaAnalysisItems([{ sensor_id: "MP01", level: "critical" }])).toBeNull();
|
|
});
|
|
|
|
it("uses trusted WFS sensor IDs for localized labels and reports partial misses", () => {
|
|
const result = createScadaAnalysisCollection(scadaCollection, [
|
|
{ sensor_id: "MP01", level: "high" },
|
|
{ sensor_id: "MP02", level: "medium" },
|
|
{ sensor_id: "MP404", level: "low" }
|
|
]);
|
|
expect(result.result).toEqual({
|
|
rendered_ids: ["MP01", "MP02"],
|
|
missing_ids: ["MP404"],
|
|
level_counts: { high: 1, medium: 1, low: 0, unrated: 0 }
|
|
});
|
|
expect(result.collection.features.map((feature) => feature.properties)).toEqual([
|
|
expect.objectContaining({ sensor_id: "MP01", analysis_label: "MP01 · 高", sort_priority: 0 }),
|
|
expect.objectContaining({ sensor_id: "MP02", analysis_label: "MP02 · 中", sort_priority: 1 })
|
|
]);
|
|
});
|
|
});
|
|
|
|
const scadaCollection: FeatureCollection = {
|
|
type: "FeatureCollection",
|
|
features: [
|
|
{ type: "Feature", geometry: { type: "Point", coordinates: [120.7, 28] }, properties: { sensor_id: "MP01" } },
|
|
{ type: "Feature", geometry: { type: "Point", coordinates: [120.72, 28.02] }, properties: { sensor_id: "MP02" } }
|
|
]
|
|
};
|