277 lines
9.8 KiB
TypeScript
277 lines
9.8 KiB
TypeScript
import type { Map as MapLibreMap } from "maplibre-gl";
|
|
import { describe, expect, it } from "vitest";
|
|
import { waterNetworkLayers } from "./layers";
|
|
import { MAP_STYLE_TOKENS } from "./map-colors";
|
|
import {
|
|
BASE_LAYER_OPTIONS,
|
|
INITIAL_LAYER_VISIBILITY,
|
|
MAP_LEGEND_ITEMS,
|
|
applyBaseLayerVisibility,
|
|
createLayerControlItems,
|
|
createVisibleMapLegendItems,
|
|
getWorkbenchLayerIds
|
|
} from "./map-control-config";
|
|
|
|
describe("workbench supply layer controls", () => {
|
|
it("switches Tianditu basemaps as base and annotation layer pairs", () => {
|
|
const visibility = new Map<string, string>();
|
|
const map = {
|
|
getLayer: () => ({}),
|
|
setLayoutProperty: (layerId: string, _property: string, value: string) => {
|
|
visibility.set(layerId, value);
|
|
}
|
|
} as unknown as MapLibreMap;
|
|
|
|
expect(BASE_LAYER_OPTIONS.map((option) => option.id)).toEqual([
|
|
"mapbox-light",
|
|
"mapbox-satellite",
|
|
"tianditu-vector",
|
|
"tianditu-image",
|
|
"none"
|
|
]);
|
|
|
|
applyBaseLayerVisibility(map, "tianditu-image");
|
|
|
|
expect(visibility.get("tianditu-image")).toBe("visible");
|
|
expect(visibility.get("tianditu-image-annotation")).toBe("visible");
|
|
expect(visibility.get("tianditu-vector")).toBe("none");
|
|
expect(visibility.get("tianditu-vector-annotation")).toBe("none");
|
|
expect(visibility.get("mapbox-light")).toBe("none");
|
|
expect(visibility.get("mapbox-satellite")).toBe("none");
|
|
});
|
|
|
|
it("creates controls only for available supply system sources", () => {
|
|
const items = createLayerControlItems(INITIAL_LAYER_VISIBILITY, undefined, {
|
|
fx_20200423_pipes: 215_797,
|
|
fx_20200811_dn100_pipes: 122_686
|
|
});
|
|
|
|
expect(items.map((item) => item.id)).toEqual(
|
|
expect.arrayContaining([
|
|
"pipes",
|
|
"junctions",
|
|
"scada-pressure",
|
|
"scada-flow",
|
|
"water_quality_monitoring_points",
|
|
"fx_20200423_pipes",
|
|
"fx_20200811_dn100_pipes"
|
|
])
|
|
);
|
|
expect(items.find((item) => item.id === "fx_20200423_pipes")).toMatchObject({
|
|
group: "source-gis",
|
|
groupLabel: "GIS 原始数据",
|
|
groupDescription: "源数据快照与专项台账",
|
|
groupDefaultOpen: false,
|
|
collection: "fx-water-assets-20200423",
|
|
collectionLabel: "2020-04-23 · 全网除头桥快照",
|
|
featureCount: 215_797,
|
|
minZoom: 8.5,
|
|
visible: false
|
|
});
|
|
expect(items.find((item) => item.id === "fx_20200811_dn100_pipes")).toMatchObject({
|
|
minZoom: 8.5,
|
|
collection: "fx-pipe-inventory-20200811",
|
|
featureCount: 122_686,
|
|
visual: { kind: "line", dashed: true }
|
|
});
|
|
expect(items.find((item) => item.id === "water_quality_monitoring_points")).toMatchObject({
|
|
group: "monitoring",
|
|
groupLabel: "监测点",
|
|
minZoom: 11,
|
|
visual: { kind: "image", imageSrc: "/map/water-quality-monitoring.svg" },
|
|
visible: true
|
|
});
|
|
expect(items.find((item) => item.id === "fx_20200423_flow_meters")).toMatchObject({ minZoom: 11 });
|
|
for (const id of ["fx_20200423_hydrants", "fx_20200423_service_connections",
|
|
"fx_20200423_customer_meters", "fx_20200423_non_residential_meters"]) {
|
|
expect(items.find((item) => item.id === id)).toMatchObject({ minZoom: 12 });
|
|
}
|
|
});
|
|
|
|
it("omits data-dependent controls when their GeoServer layers are empty", () => {
|
|
const items = createLayerControlItems(INITIAL_LAYER_VISIBILITY, [
|
|
"pipes",
|
|
"junctions",
|
|
"valves",
|
|
"reservoirs",
|
|
"scada"
|
|
]);
|
|
|
|
expect(items.map((item) => item.id)).toEqual([
|
|
"pipes",
|
|
"junctions",
|
|
"valves",
|
|
"reservoirs",
|
|
"scada-pressure",
|
|
"scada-flow"
|
|
]);
|
|
});
|
|
|
|
it("lists actual presentation overlays with their visibility and removes cleared entries", () => {
|
|
const overlays = [
|
|
{ id: "presentation:investigation:area", title: "爆管影响范围", description: "Agent 调查 · 空间范围", featureCount: 1, visible: true },
|
|
{ id: "presentation:chat:area", title: "投诉点热力", description: "Agent 对话 · 热力分布", featureCount: 8, visible: false }
|
|
];
|
|
const items = createLayerControlItems(INITIAL_LAYER_VISIBILITY, undefined, {}, overlays);
|
|
|
|
expect(items.filter((item) => item.group === "analysis")).toMatchObject([
|
|
{ id: overlays[0].id, label: "爆管影响范围", visible: true, featureCount: 1 },
|
|
{ id: overlays[1].id, label: "投诉点热力", visible: false, featureCount: 8 }
|
|
]);
|
|
expect(createVisibleMapLegendItems(items).filter((item) => item.group === "analysis")).toMatchObject([
|
|
{ label: "爆管影响范围", layerControlId: overlays[0].id, shape: "area" }
|
|
]);
|
|
const cleared = createLayerControlItems(INITIAL_LAYER_VISIBILITY);
|
|
expect(cleared.filter((item) => item.group === "analysis")).toEqual([]);
|
|
expect(createVisibleMapLegendItems(cleared).filter((item) => item.group === "analysis")).toEqual([]);
|
|
});
|
|
|
|
it("defines map-matched symbols for model and source GIS layers", () => {
|
|
expect(MAP_LEGEND_ITEMS.map((item) => item.id)).toEqual([
|
|
"major-pipe",
|
|
"medium-pipe",
|
|
"minor-pipe",
|
|
"inactive-pipe",
|
|
"junction",
|
|
"valve",
|
|
"reservoir",
|
|
"pump",
|
|
"tank",
|
|
"scada-flow",
|
|
"scada-pressure",
|
|
"water-quality-monitoring",
|
|
"source-major-pipe",
|
|
"source-medium-pipe",
|
|
"source-minor-pipe",
|
|
"source-unknown-pipe",
|
|
"source-inventory-pipe",
|
|
"source-valve",
|
|
"source-drain-valve",
|
|
"source-flow-meter",
|
|
"source-hydrant",
|
|
"source-connection",
|
|
"source-customer-meter",
|
|
"source-non-residential-meter"
|
|
]);
|
|
expect(MAP_LEGEND_ITEMS.find((item) => item.id === "valve")).toMatchObject({
|
|
imageSrc: "/map/valve.png"
|
|
});
|
|
expect(MAP_LEGEND_ITEMS.find((item) => item.id === "reservoir")).toMatchObject({
|
|
label: "水库",
|
|
imageSrc: "/map/reservoir.png"
|
|
});
|
|
expect(MAP_LEGEND_ITEMS.find((item) => item.id === "pump")).toMatchObject({
|
|
imageSrc: "/map/pump.png"
|
|
});
|
|
expect(MAP_LEGEND_ITEMS.find((item) => item.id === "tank")).toMatchObject({
|
|
imageSrc: "/map/tank.png"
|
|
});
|
|
expect(MAP_LEGEND_ITEMS.find((item) => item.id === "scada-flow")).toMatchObject({
|
|
imageSrc: "/map/scada-flow.png"
|
|
});
|
|
expect(MAP_LEGEND_ITEMS.find((item) => item.id === "scada-pressure")).toMatchObject({
|
|
imageSrc: "/map/scada-pressure.png"
|
|
});
|
|
expect(MAP_LEGEND_ITEMS.find((item) => item.id === "inactive-pipe")).toMatchObject({
|
|
color: MAP_STYLE_TOKENS.state.inactive,
|
|
lineWidth: 2.5,
|
|
shape: "dashed-line"
|
|
});
|
|
expect(MAP_LEGEND_ITEMS.find((item) => item.id === "source-inventory-pipe")).toMatchObject({
|
|
color: MAP_STYLE_TOKENS.supply.sourcePipeInventory,
|
|
groupLabel: "原始 GIS 管线 · 2020-08-11",
|
|
layerControlId: "fx_20200811_dn100_pipes",
|
|
shape: "dashed-line"
|
|
});
|
|
expect(MAP_LEGEND_ITEMS.find((item) => item.id === "source-unknown-pipe")).toMatchObject({
|
|
label: "未标注口径",
|
|
color: MAP_STYLE_TOKENS.state.inactive,
|
|
groupLabel: "原始 GIS 管线 · 2020-04-23",
|
|
layerControlId: "fx_20200423_pipes",
|
|
shape: "line"
|
|
});
|
|
expect(MAP_LEGEND_ITEMS.find((item) => item.id === "source-valve")).toMatchObject({
|
|
imageSrc: "/map/gis-valve.svg",
|
|
groupLabel: "原始 GIS 设施"
|
|
});
|
|
expect(MAP_LEGEND_ITEMS.find((item) => item.id === "source-hydrant")).toMatchObject({
|
|
imageSrc: "/map/gis-hydrant.svg"
|
|
});
|
|
expect(
|
|
MAP_LEGEND_ITEMS.find((item) => item.id === "source-non-residential-meter")
|
|
).toMatchObject({
|
|
imageSrc: "/map/gis-non-residential-meter.svg"
|
|
});
|
|
});
|
|
|
|
it("keeps the legend synchronized with visible layer controls", () => {
|
|
const initialItems = createLayerControlItems(INITIAL_LAYER_VISIBILITY);
|
|
const initialLegendIds = createVisibleMapLegendItems(initialItems).map((item) => item.id);
|
|
|
|
expect(initialLegendIds).toEqual(
|
|
expect.arrayContaining(["major-pipe", "valve", "scada-flow", "water-quality-monitoring"])
|
|
);
|
|
expect(initialLegendIds).not.toEqual(
|
|
expect.arrayContaining(["source-major-pipe", "source-inventory-pipe", "impact-area"])
|
|
);
|
|
|
|
const sourcePipeItems = createLayerControlItems({
|
|
...INITIAL_LAYER_VISIBILITY,
|
|
fx_20200423_pipes: true
|
|
});
|
|
const sourcePipeLegendIds = createVisibleMapLegendItems(sourcePipeItems).map((item) => item.id);
|
|
|
|
expect(sourcePipeLegendIds).toEqual(
|
|
expect.arrayContaining([
|
|
"source-major-pipe",
|
|
"source-medium-pipe",
|
|
"source-minor-pipe",
|
|
"source-unknown-pipe"
|
|
])
|
|
);
|
|
expect(sourcePipeLegendIds).not.toContain("source-inventory-pipe");
|
|
|
|
const reducedItems = createLayerControlItems({
|
|
...INITIAL_LAYER_VISIBILITY,
|
|
valves: false
|
|
});
|
|
const reducedLegendIds = createVisibleMapLegendItems(reducedItems).map((item) => item.id);
|
|
|
|
expect(reducedLegendIds).not.toContain("valve");
|
|
expect(reducedLegendIds).not.toContain("impact-area");
|
|
});
|
|
|
|
it("finds every rendered layer that uses a source", () => {
|
|
const map = {
|
|
getLayer: (id: string) => waterNetworkLayers.some((layer) => layer.id === id),
|
|
getStyle: () => ({ version: 8, sources: {}, layers: waterNetworkLayers })
|
|
} as unknown as Pick<MapLibreMap, "getLayer" | "getStyle">;
|
|
|
|
expect(getWorkbenchLayerIds(map, "valves")).toEqual([
|
|
"valves-casing",
|
|
"valves",
|
|
"valves-symbol",
|
|
"valves-hover",
|
|
"valves-selected-outer",
|
|
"valves-selected",
|
|
"valves-hit"
|
|
]);
|
|
expect(getWorkbenchLayerIds(map, "reservoirs")).toEqual([
|
|
"reservoirs-halo",
|
|
"reservoirs",
|
|
"reservoirs-symbol",
|
|
"reservoirs-hover",
|
|
"reservoirs-selected-outer",
|
|
"reservoirs-selected",
|
|
"reservoirs-hit"
|
|
]);
|
|
expect(getWorkbenchLayerIds(map, "pumps")).toEqual([
|
|
"pumps-symbol",
|
|
"pumps-hover",
|
|
"pumps-selected-outer",
|
|
"pumps-selected",
|
|
"pumps-hit"
|
|
]);
|
|
});
|
|
});
|