163 lines
7.0 KiB
TypeScript
163 lines
7.0 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
INTERACTIVE_HIT_LAYER_IDS,
|
|
waterNetworkLayers
|
|
} from "./layers";
|
|
import {
|
|
DRAINAGE_SELECTED_OUTLINE_COLORS,
|
|
DRAINAGE_SOURCE_COLORS
|
|
} from "./map-colors";
|
|
import { DRAINAGE_LAYER_VISUALS, MAP_MAX_ZOOM } from "./map-layer-visuals";
|
|
|
|
describe("drainage network interaction layers", () => {
|
|
it("adds one invisible hit layer for every interactive source", () => {
|
|
expect(INTERACTIVE_HIT_LAYER_IDS).toEqual([
|
|
"conduits-hit",
|
|
"junctions-hit",
|
|
"orifices-hit",
|
|
"pumps-hit",
|
|
"outfalls-hit"
|
|
]);
|
|
|
|
const hitLayers = INTERACTIVE_HIT_LAYER_IDS.map((layerId) => {
|
|
const layer = waterNetworkLayers.find((candidate) => candidate.id === layerId);
|
|
expect(layer).toBeDefined();
|
|
return layer!;
|
|
});
|
|
|
|
expect(hitLayers.map((layer) => "source" in layer ? layer.source : null)).toEqual([
|
|
"conduits",
|
|
"junctions",
|
|
"orifices",
|
|
"pumps",
|
|
"outfalls"
|
|
]);
|
|
|
|
hitLayers.forEach((layer) => {
|
|
if (layer.type === "line") {
|
|
expect(layer.paint?.["line-width"]).toBe(DRAINAGE_LAYER_VISUALS.conduits.hitWidth);
|
|
expect(layer.paint?.["line-opacity"]).toBe(0);
|
|
} else if (layer.type === "circle") {
|
|
expect(layer.paint?.["circle-radius"]).toBe(DRAINAGE_LAYER_VISUALS.junctions.hitRadius);
|
|
expect(layer.paint?.["circle-opacity"]).toBe(0);
|
|
} else {
|
|
throw new Error(`Unexpected hit layer type: ${layer.type}`);
|
|
}
|
|
});
|
|
});
|
|
|
|
it("orders smaller facilities above conduits for overlapping hits", () => {
|
|
const layerIds = waterNetworkLayers.map((layer) => layer.id);
|
|
const hitLayerIndexes = INTERACTIVE_HIT_LAYER_IDS.map((layerId) => layerIds.indexOf(layerId));
|
|
|
|
expect(hitLayerIndexes).toEqual([...hitLayerIndexes].sort((first, second) => first - second));
|
|
expect(hitLayerIndexes.every((index) => index >= 0)).toBe(true);
|
|
});
|
|
|
|
it("provides persistent selected layers for every source", () => {
|
|
const selectedLayerIds = [
|
|
"pipes-selected-halo",
|
|
"pipes-selected-outline",
|
|
"pipes-selected",
|
|
"junctions-selected-halo",
|
|
"junctions-selected",
|
|
"orifices-selected-halo",
|
|
"orifices-selected-outline",
|
|
"orifices-selected",
|
|
"pumps-selected-halo",
|
|
"pumps-selected-outline",
|
|
"pumps-selected",
|
|
"outfalls-selected-halo",
|
|
"outfalls-selected"
|
|
];
|
|
|
|
selectedLayerIds.forEach((layerId) => {
|
|
const layer = waterNetworkLayers.find((candidate) => candidate.id === layerId);
|
|
expect(layer && "filter" in layer ? layer.filter : undefined).toEqual(["==", ["get", "id"], ""]);
|
|
expect(layer && "minzoom" in layer ? layer.minzoom : undefined).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
it("renders selected features as a halo, complementary outline, and source-color core", () => {
|
|
const expectedSelectedColors = [
|
|
["pipes-selected-outline", "line-color", DRAINAGE_SELECTED_OUTLINE_COLORS.conduits],
|
|
["pipes-selected", "line-color", DRAINAGE_SOURCE_COLORS.conduits],
|
|
["junctions-selected", "circle-stroke-color", DRAINAGE_SELECTED_OUTLINE_COLORS.junctions],
|
|
["junctions-selected", "circle-color", DRAINAGE_SOURCE_COLORS.junctions],
|
|
["orifices-selected-outline", "line-color", DRAINAGE_SELECTED_OUTLINE_COLORS.orifices],
|
|
["orifices-selected", "line-color", DRAINAGE_SOURCE_COLORS.orifices],
|
|
["pumps-selected-outline", "line-color", DRAINAGE_SELECTED_OUTLINE_COLORS.pumps],
|
|
["pumps-selected", "line-color", DRAINAGE_SOURCE_COLORS.pumps],
|
|
["outfalls-selected", "circle-stroke-color", DRAINAGE_SELECTED_OUTLINE_COLORS.outfalls],
|
|
["outfalls-selected", "circle-color", DRAINAGE_SOURCE_COLORS.outfalls]
|
|
] as const;
|
|
|
|
expectedSelectedColors.forEach(([layerId, paintProperty, color]) => {
|
|
const layer = waterNetworkLayers.find((candidate) => candidate.id === layerId);
|
|
const paint = layer?.paint as Record<string, unknown> | undefined;
|
|
expect(paint?.[paintProperty]).toBe(color);
|
|
});
|
|
|
|
const layerIds = waterNetworkLayers.map((layer) => layer.id);
|
|
["pipes", "orifices", "pumps"].forEach((prefix) => {
|
|
expect(layerIds.indexOf(`${prefix}-selected-halo`)).toBeLessThan(
|
|
layerIds.indexOf(`${prefix}-selected-outline`)
|
|
);
|
|
expect(layerIds.indexOf(`${prefix}-selected-outline`)).toBeLessThan(
|
|
layerIds.indexOf(`${prefix}-selected`)
|
|
);
|
|
});
|
|
["junctions", "outfalls"].forEach((prefix) => {
|
|
expect(layerIds.indexOf(`${prefix}-selected-halo`)).toBeLessThan(
|
|
layerIds.indexOf(`${prefix}-selected`)
|
|
);
|
|
});
|
|
});
|
|
|
|
it("keeps source geometry readable through zoom level 24", () => {
|
|
expect(MAP_MAX_ZOOM).toBe(24);
|
|
expect(DRAINAGE_LAYER_VISUALS.junctions.minzoom).toBe(12);
|
|
expect(DRAINAGE_LAYER_VISUALS.junctions.radius).toEqual([
|
|
"interpolate", ["linear"], ["zoom"], 12, 1, 16, 3, 20, 5.5, 24, 8
|
|
]);
|
|
expect(DRAINAGE_LAYER_VISUALS.outfalls.radius).toEqual([
|
|
"interpolate", ["linear"], ["zoom"], 11, 3, 16, 5, 20, 7, 24, 9
|
|
]);
|
|
expect(DRAINAGE_LAYER_VISUALS.orifices.width).toEqual([
|
|
"interpolate", ["linear"], ["zoom"], 11, 1.6, 17, 4.5, 22, 6, 24, 7
|
|
]);
|
|
expect(DRAINAGE_LAYER_VISUALS.pumps.width).toEqual([
|
|
"interpolate", ["linear"], ["zoom"], 11, 2.4, 17, 6.2, 22, 8, 24, 9
|
|
]);
|
|
expect((DRAINAGE_LAYER_VISUALS.conduits.width as unknown[]).at(-2)).toBe(24);
|
|
expect((DRAINAGE_LAYER_VISUALS.conduits.hitWidth as unknown[]).at(-1)).toBe(24);
|
|
expect((DRAINAGE_LAYER_VISUALS.junctions.hitRadius as unknown[]).at(-1)).toBe(14);
|
|
});
|
|
|
|
it("uses the centralized geometry tokens in rendered layers", () => {
|
|
const expectedGeometry = [
|
|
["pipes-flow", "line-width", DRAINAGE_LAYER_VISUALS.conduits.width],
|
|
["pipes-selected-halo", "line-width", DRAINAGE_LAYER_VISUALS.conduits.selectedHaloWidth],
|
|
["junctions", "circle-radius", DRAINAGE_LAYER_VISUALS.junctions.radius],
|
|
["junctions-selected-halo", "circle-radius", DRAINAGE_LAYER_VISUALS.junctions.selectedHaloRadius],
|
|
["orifices", "line-width", DRAINAGE_LAYER_VISUALS.orifices.width],
|
|
["orifices-selected", "line-width", DRAINAGE_LAYER_VISUALS.orifices.selectedWidth],
|
|
["pumps", "line-width", DRAINAGE_LAYER_VISUALS.pumps.width],
|
|
["pumps-selected", "line-width", DRAINAGE_LAYER_VISUALS.pumps.selectedWidth],
|
|
["outfalls", "circle-radius", DRAINAGE_LAYER_VISUALS.outfalls.radius],
|
|
["outfalls-selected-halo", "circle-radius", DRAINAGE_LAYER_VISUALS.outfalls.selectedHaloRadius]
|
|
] as const;
|
|
|
|
expectedGeometry.forEach(([layerId, paintProperty, visualToken]) => {
|
|
const layer = waterNetworkLayers.find((candidate) => candidate.id === layerId);
|
|
const paint = layer?.paint as Record<string, unknown> | undefined;
|
|
expect(paint?.[paintProperty]).toBe(visualToken);
|
|
});
|
|
|
|
["junctions-halo", "junctions", "junctions-hover", "junctions-hit"].forEach((layerId) => {
|
|
const layer = waterNetworkLayers.find((candidate) => candidate.id === layerId);
|
|
expect(layer && "minzoom" in layer ? layer.minzoom : undefined).toBe(12);
|
|
});
|
|
});
|
|
});
|