jest.mock("ol/layer/WebGLVectorTile", () => ({ __esModule: true, default: class WebGLVectorTileLayer {}, })); import { LayerStyleController } from "./layerStyleController"; describe("LayerStyleController", () => { it("rebuilds only when the structural signature changes", () => { const layer = { getSource: () => null, updateStyleVariables: jest.fn(), setStyle: jest.fn(), } as any; const controller = new LayerStyleController({ layer, defaultStyle: { "stroke-color": "gray" }, }); const base = { property: "pressure", classCount: 5, template: { "stroke-color": ["var", "tj_color_0"] } as any, variables: { tj_color_0: "red" }, }; controller.applyNative(base); controller.applyNative({ ...base, variables: { tj_color_0: "blue" } }); expect(layer.setStyle).toHaveBeenCalledTimes(1); expect(layer.updateStyleVariables).toHaveBeenCalledTimes(2); controller.applyNative({ ...base, classCount: 6 }); expect(layer.setStyle).toHaveBeenCalledTimes(2); }); it("isolates primary and comparison values on a shared vector source", () => { const properties: Record = { id: "J-1" }; const feature = { properties, properties_: properties, get: (key: string) => properties[key], }; const listeners = new Set<(event: any) => void>(); const source = { sourceTiles_: { loaded: { getFeatures: () => [feature] } }, on: (_type: string, listener: (event: any) => void) => listeners.add(listener), un: (_type: string, listener: (event: any) => void) => listeners.delete(listener), }; const createLayer = () => ({ getSource: () => source, on: jest.fn(), un: jest.fn(), getOpacity: () => 1, setOpacity: jest.fn(), setStyle: jest.fn(), updateStyleVariables: jest.fn(), }); const primary = new LayerStyleController({ layer: createLayer() as any, defaultStyle: { "circle-fill-color": "gray" }, stateNamespace: "primary", }); const compare = new LayerStyleController({ layer: createLayer() as any, defaultStyle: { "circle-fill-color": "gray" }, stateNamespace: "compare", }); const options = { property: "pressure", classCount: 5, template: { "circle-fill-color": ["get", "pressure"] } as any, variables: {}, }; primary.applyRuntime(options, new Map([["J-1", 0.25]])); compare.applyRuntime(options, new Map([["J-1", 0.75]])); expect(properties.primary_pressure).toBe(0.25); expect(properties.compare_pressure).toBe(0.75); expect(listeners.size).toBe(2); primary.dispose(); expect(listeners.size).toBe(1); expect(properties.compare_pressure).toBe(0.75); compare.dispose(); expect(listeners.size).toBe(0); }); });