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(); 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; 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" ]); }); });