|
| 1 | +import assert from "node:assert/strict"; |
| 2 | +import { beforeEach, describe, it } from "node:test"; |
| 3 | +import { useAppStore } from "@geolibre/core"; |
| 4 | +import { styleParamPatch } from "../apps/geolibre-desktop/src/lib/scripting/style-params"; |
| 5 | + |
| 6 | +// The notebook client's `add_geojson(gdf, **style)` always sends a `style` |
| 7 | +// object, so the scripting handler's `addGeoJsonLayer` decides — via |
| 8 | +// `styleParamPatch` — whether that payload is worth a store write at all. The |
| 9 | +// handler module itself pulls in the whole plugin/map stack (and its CSS), so |
| 10 | +// these tests exercise the decision helper directly and then replay what the |
| 11 | +// handler does with it against the real store. |
| 12 | + |
| 13 | +const FC = { |
| 14 | + type: "FeatureCollection" as const, |
| 15 | + features: [ |
| 16 | + { |
| 17 | + type: "Feature" as const, |
| 18 | + properties: {}, |
| 19 | + geometry: { type: "Point" as const, coordinates: [0, 0] }, |
| 20 | + }, |
| 21 | + ], |
| 22 | +}; |
| 23 | + |
| 24 | +describe("styleParamPatch", () => { |
| 25 | + it("keeps a non-empty style object", () => { |
| 26 | + const style = { fillColor: "#facc15", strokeWidth: 2 }; |
| 27 | + assert.deepEqual(styleParamPatch(style), style); |
| 28 | + }); |
| 29 | + |
| 30 | + it("rejects an empty object, so a style-less call writes nothing", () => { |
| 31 | + assert.equal(styleParamPatch({}), null); |
| 32 | + }); |
| 33 | + |
| 34 | + it("rejects missing and non-object payloads", () => { |
| 35 | + assert.equal(styleParamPatch(undefined), null); |
| 36 | + assert.equal(styleParamPatch(null), null); |
| 37 | + assert.equal(styleParamPatch("fillColor"), null); |
| 38 | + assert.equal(styleParamPatch(["fillColor"]), null); |
| 39 | + }); |
| 40 | +}); |
| 41 | + |
| 42 | +describe("addGeoJsonLayer command styling", () => { |
| 43 | + beforeEach(() => { |
| 44 | + useAppStore.getState().newProject({ name: "Scripting" }); |
| 45 | + useAppStore.temporal.getState().clear(); |
| 46 | + }); |
| 47 | + |
| 48 | + it("merges an inline style into the new layer", () => { |
| 49 | + const layerId = useAppStore.getState().addGeoJsonLayer("Styled", FC); |
| 50 | + const style = styleParamPatch({ fillColor: "#facc15", strokeColor: "#d97706" }); |
| 51 | + assert.ok(style); |
| 52 | + useAppStore.getState().setLayerStyle(layerId, style); |
| 53 | + |
| 54 | + const layer = useAppStore.getState().layers.find((item) => item.id === layerId); |
| 55 | + assert.equal(layer?.style?.fillColor, "#facc15"); |
| 56 | + assert.equal(layer?.style?.strokeColor, "#d97706"); |
| 57 | + }); |
| 58 | + |
| 59 | + it("costs a single undo step when no style kwargs were passed", () => { |
| 60 | + const layerId = useAppStore.getState().addGeoJsonLayer("Plain", FC); |
| 61 | + const style = styleParamPatch({}); |
| 62 | + if (style) useAppStore.getState().setLayerStyle(layerId, style); |
| 63 | + |
| 64 | + assert.equal(useAppStore.temporal.getState().pastStates.length, 1); |
| 65 | + useAppStore.temporal.getState().undo(); |
| 66 | + assert.equal( |
| 67 | + useAppStore.getState().layers.find((item) => item.id === layerId), |
| 68 | + undefined, |
| 69 | + ); |
| 70 | + }); |
| 71 | +}); |
0 commit comments