@geospatial-sdk/maplibre 0.0.5-dev.48 → 0.0.5-dev.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/helpers/map.helpers.d.ts +46 -12
- package/dist/helpers/map.helpers.d.ts.map +1 -1
- package/dist/helpers/map.helpers.js +153 -36
- package/dist/map/apply-context-diff.d.ts +12 -3
- package/dist/map/apply-context-diff.d.ts.map +1 -1
- package/dist/map/apply-context-diff.js +67 -13
- package/dist/map/create-map.d.ts +7 -3
- package/dist/map/create-map.d.ts.map +1 -1
- package/dist/map/create-map.js +63 -22
- package/dist/maplibre.models.d.ts +2 -1
- package/dist/maplibre.models.d.ts.map +1 -1
- package/lib/helpers/map.helpers.ts +188 -50
- package/lib/map/apply-context-diff.test.ts +476 -58
- package/lib/map/apply-context-diff.ts +95 -22
- package/lib/map/create-map.test.ts +158 -63
- package/lib/map/create-map.ts +70 -34
- package/lib/maplibre.models.ts +2 -1
- package/package.json +3 -3
|
@@ -1,13 +1,60 @@
|
|
|
1
|
-
import { MapContextDiff } from "@geospatial-sdk/core";
|
|
2
|
-
import { Map } from "maplibre-gl";
|
|
1
|
+
import { MapContextDiff, MapContextLayer } from "@geospatial-sdk/core";
|
|
2
|
+
import type { Map } from "maplibre-gl";
|
|
3
3
|
import { createLayer } from "./create-map.js";
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
canDoIncrementalUpdate,
|
|
6
|
+
getFirstLayerIdAtPosition,
|
|
7
7
|
getLayersAtPosition,
|
|
8
|
-
|
|
8
|
+
getLayersFromContextLayer,
|
|
9
|
+
updateLayerProperties,
|
|
9
10
|
} from "../helpers/map.helpers.js";
|
|
10
11
|
|
|
12
|
+
/**
|
|
13
|
+
* This will either update the layers in the map or recreate them;
|
|
14
|
+
* the returned promise resolves when the update is done
|
|
15
|
+
* @param map
|
|
16
|
+
* @param layerModel
|
|
17
|
+
* @param previousLayerModel
|
|
18
|
+
* @param layerPosition
|
|
19
|
+
*/
|
|
20
|
+
export async function updateLayerInMap(
|
|
21
|
+
map: Map,
|
|
22
|
+
layerModel: MapContextLayer,
|
|
23
|
+
previousLayerModel: MapContextLayer,
|
|
24
|
+
layerPosition: number,
|
|
25
|
+
): Promise<void> {
|
|
26
|
+
// if an incremental update is possible, do it to avoid costly layer recreation
|
|
27
|
+
if (canDoIncrementalUpdate(previousLayerModel, layerModel)) {
|
|
28
|
+
// we can find the existing layers by using the hash or id of the layerModel
|
|
29
|
+
const mlUpdatedLayers = getLayersFromContextLayer(map, layerModel);
|
|
30
|
+
for (const layer of mlUpdatedLayers) {
|
|
31
|
+
updateLayerProperties(map, layer, layerModel, previousLayerModel);
|
|
32
|
+
}
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const mlLayersToRemove = getLayersAtPosition(map, layerPosition);
|
|
37
|
+
const sourcesToRemove: string[] = [];
|
|
38
|
+
for (const layer of mlLayersToRemove) {
|
|
39
|
+
if (layer.source && !sourcesToRemove.includes(layer.source)) {
|
|
40
|
+
sourcesToRemove.push(layer.source);
|
|
41
|
+
}
|
|
42
|
+
map.removeLayer(layer.id);
|
|
43
|
+
}
|
|
44
|
+
for (const sourceId of sourcesToRemove) {
|
|
45
|
+
map.removeSource(sourceId);
|
|
46
|
+
}
|
|
47
|
+
const styleDiff = await createLayer(layerModel);
|
|
48
|
+
if (!styleDiff) return;
|
|
49
|
+
const beforeId = getFirstLayerIdAtPosition(map, layerPosition);
|
|
50
|
+
Object.keys(styleDiff.sources).forEach((sourceId) =>
|
|
51
|
+
map.addSource(sourceId, styleDiff.sources[sourceId]),
|
|
52
|
+
);
|
|
53
|
+
styleDiff.layers.map((layer) => {
|
|
54
|
+
map.addLayer(layer, beforeId);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
11
58
|
/**
|
|
12
59
|
* Apply a context diff to an MapLibre map
|
|
13
60
|
* @param map
|
|
@@ -16,14 +63,14 @@ import {
|
|
|
16
63
|
export async function applyContextDiffToMap(
|
|
17
64
|
map: Map,
|
|
18
65
|
contextDiff: MapContextDiff,
|
|
19
|
-
): Promise<
|
|
66
|
+
): Promise<Map> {
|
|
20
67
|
// removed layers (sorted by descending position)
|
|
21
68
|
if (contextDiff.layersRemoved.length > 0) {
|
|
22
69
|
const removed = contextDiff.layersRemoved.sort(
|
|
23
70
|
(a, b) => b.position - a.position,
|
|
24
71
|
);
|
|
25
72
|
for (const layerRemoved of removed) {
|
|
26
|
-
const mlLayers =
|
|
73
|
+
const mlLayers = getLayersFromContextLayer(map, layerRemoved.layer);
|
|
27
74
|
if (mlLayers.length === 0) {
|
|
28
75
|
console.warn(
|
|
29
76
|
`[Warning] applyContextDiffToMap: no layer found at position ${layerRemoved.position} to remove.`,
|
|
@@ -40,32 +87,56 @@ export async function applyContextDiffToMap(
|
|
|
40
87
|
|
|
41
88
|
// insert added layers
|
|
42
89
|
const newLayers = await Promise.all(
|
|
43
|
-
contextDiff.layersAdded.map((layerAdded) =>
|
|
44
|
-
createLayer(layerAdded.layer, layerAdded.position),
|
|
45
|
-
),
|
|
90
|
+
contextDiff.layersAdded.map((layerAdded) => createLayer(layerAdded.layer)),
|
|
46
91
|
);
|
|
47
|
-
newLayers.forEach((style
|
|
92
|
+
newLayers.forEach((style, index) => {
|
|
93
|
+
if (!style) return;
|
|
48
94
|
const position = contextDiff.layersAdded[index].position;
|
|
49
|
-
const beforeId =
|
|
95
|
+
const beforeId = getFirstLayerIdAtPosition(map, position);
|
|
50
96
|
Object.keys(style.sources).forEach((sourceId) =>
|
|
51
97
|
map.addSource(sourceId, style.sources[sourceId]),
|
|
52
98
|
);
|
|
53
|
-
style.layers.map((layer
|
|
99
|
+
style.layers.map((layer) => {
|
|
54
100
|
map.addLayer(layer, beforeId);
|
|
55
101
|
});
|
|
56
102
|
});
|
|
57
103
|
|
|
104
|
+
// handle reordered layers (sorted by ascending new position)
|
|
105
|
+
if (contextDiff.layersReordered.length > 0) {
|
|
106
|
+
const reordered = contextDiff.layersReordered.sort(
|
|
107
|
+
(a, b) => a.newPosition - b.newPosition,
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
// collect all layers to be moved
|
|
111
|
+
const mlLayersToMove = reordered.map((layerReordered) =>
|
|
112
|
+
getLayersFromContextLayer(map, layerReordered.layer),
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
// move layers
|
|
116
|
+
for (let i = 0; i < reordered.length; i++) {
|
|
117
|
+
const layerReordered = reordered[i];
|
|
118
|
+
const mlLayers = mlLayersToMove[i];
|
|
119
|
+
const beforeId = getFirstLayerIdAtPosition(
|
|
120
|
+
map,
|
|
121
|
+
layerReordered.newPosition + 1,
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
if (mlLayers[0].id === beforeId) {
|
|
125
|
+
// layer is already at the right position
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// then we add the moved the layer to its new position
|
|
130
|
+
for (const layer of mlLayers) {
|
|
131
|
+
map.moveLayer(layer.id, beforeId);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
58
136
|
// recreate changed layers
|
|
59
137
|
for (const layerChanged of contextDiff.layersChanged) {
|
|
60
|
-
const { layer, position } = layerChanged;
|
|
61
|
-
|
|
62
|
-
removeLayersFromSource(map, sourceId);
|
|
63
|
-
const beforeId = getBeforeId(map, position);
|
|
64
|
-
createLayer(layer, position).then((styleDiff) => {
|
|
65
|
-
styleDiff.layers.map((layer: any) => {
|
|
66
|
-
map.addLayer(layer, beforeId);
|
|
67
|
-
});
|
|
68
|
-
});
|
|
138
|
+
const { layer, previousLayer, position } = layerChanged;
|
|
139
|
+
await updateLayerInMap(map, layer, previousLayer, position);
|
|
69
140
|
}
|
|
70
141
|
|
|
71
142
|
if (typeof contextDiff.viewChanges !== "undefined") {
|
|
@@ -86,4 +157,6 @@ export async function applyContextDiffToMap(
|
|
|
86
157
|
);
|
|
87
158
|
}
|
|
88
159
|
}
|
|
160
|
+
|
|
161
|
+
return map;
|
|
89
162
|
}
|
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
MAP_CTX_LAYER_OGCAPI_FIXTURE,
|
|
6
6
|
MAP_CTX_LAYER_WFS_FIXTURE,
|
|
7
7
|
MAP_CTX_LAYER_WMS_FIXTURE,
|
|
8
|
+
MAP_CTX_LAYER_WMTS_FIXTURE,
|
|
9
|
+
MAP_CTX_LAYER_XYZ_FIXTURE,
|
|
8
10
|
} from "@geospatial-sdk/core/fixtures/map-context.fixtures.js";
|
|
9
11
|
import { LayerGeojsonWithData, MapContextLayer } from "@geospatial-sdk/core";
|
|
10
12
|
import { createLayer } from "./create-map.js";
|
|
@@ -13,14 +15,13 @@ import {
|
|
|
13
15
|
GeoJSONSourceSpecification,
|
|
14
16
|
RasterLayerSpecification,
|
|
15
17
|
} from "@maplibre/maplibre-gl-style-spec";
|
|
18
|
+
import { FEATURE_COLLECTION_POLYGON_FIXTURE_4326 } from "@geospatial-sdk/core/fixtures/geojson.fixtures.js";
|
|
16
19
|
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
} from "
|
|
20
|
-
import { PartialStyleSpecification } from "../maplibre.models.js";
|
|
20
|
+
LayerMetadataSpecification,
|
|
21
|
+
PartialStyleSpecification,
|
|
22
|
+
} from "../maplibre.models.js";
|
|
21
23
|
import {
|
|
22
24
|
CircleLayerSpecification,
|
|
23
|
-
LayerSpecification,
|
|
24
25
|
LineLayerSpecification,
|
|
25
26
|
RasterSourceSpecification,
|
|
26
27
|
} from "maplibre-gl";
|
|
@@ -29,10 +30,15 @@ describe("MapContextService", () => {
|
|
|
29
30
|
describe("#createLayer", () => {
|
|
30
31
|
let layerModel: MapContextLayer, style: PartialStyleSpecification;
|
|
31
32
|
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
// This makes it so that every layerId/sourceId will be "123456"
|
|
35
|
+
vi.spyOn(Math, "random").mockReturnValue(0.123456);
|
|
36
|
+
});
|
|
37
|
+
|
|
32
38
|
describe("WMS", () => {
|
|
33
39
|
beforeEach(async () => {
|
|
34
|
-
|
|
35
|
-
|
|
40
|
+
layerModel = MAP_CTX_LAYER_WMS_FIXTURE;
|
|
41
|
+
style = (await createLayer(layerModel)) as PartialStyleSpecification;
|
|
36
42
|
});
|
|
37
43
|
it("create a tile layer", () => {
|
|
38
44
|
expect(style).toBeTruthy();
|
|
@@ -42,7 +48,7 @@ describe("MapContextService", () => {
|
|
|
42
48
|
expect(sourcesIds.length).toBe(1);
|
|
43
49
|
const id = sourcesIds[0];
|
|
44
50
|
const source = style.sources[id] as RasterSourceSpecification;
|
|
45
|
-
expect(id).toBe("
|
|
51
|
+
expect(id).toBe("123456");
|
|
46
52
|
expect(source.tiles).toEqual([
|
|
47
53
|
"https://www.datagrandest.fr/geoserver/region-grand-est/ows?REQUEST=GetMap&SERVICE=WMS&layers=commune_actuelle_3857&styles=&format=image%2Fpng&transparent=true&version=1.1.1&height=256&width=256&srs=EPSG%3A3857&BBOX={bbox-epsg-3857}",
|
|
48
54
|
]);
|
|
@@ -52,17 +58,36 @@ describe("MapContextService", () => {
|
|
|
52
58
|
expect(style.layers.length).toBe(1);
|
|
53
59
|
|
|
54
60
|
const layer = style.layers[0] as RasterLayerSpecification;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
expect(layer.
|
|
61
|
+
const metadata = layer.metadata as LayerMetadataSpecification;
|
|
62
|
+
|
|
63
|
+
expect(layer.id).toBe("123456");
|
|
64
|
+
expect(layer.type).toBe("raster");
|
|
65
|
+
expect(layer.source).toBe(layer.id);
|
|
66
|
+
expect(metadata.layerId).toBeUndefined();
|
|
67
|
+
expect(metadata.layerHash).toBeTypeOf("string");
|
|
68
|
+
expect(layer.paint?.["raster-opacity"]).toBe(0.5);
|
|
69
|
+
expect(layer.layout?.visibility).toBe("none");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
describe("with an id", () => {
|
|
73
|
+
beforeEach(async () => {
|
|
74
|
+
layerModel = { ...MAP_CTX_LAYER_WMS_FIXTURE, id: "my-test-layer" };
|
|
75
|
+
style = (await createLayer(layerModel)) as PartialStyleSpecification;
|
|
76
|
+
});
|
|
77
|
+
it("create a layer with layer id in metadata", () => {
|
|
78
|
+
const layer = style.layers[0] as RasterLayerSpecification;
|
|
79
|
+
const metadata = layer.metadata as LayerMetadataSpecification;
|
|
80
|
+
expect(metadata.layerHash).toBeUndefined();
|
|
81
|
+
expect(metadata.layerId).toBe("my-test-layer");
|
|
82
|
+
});
|
|
58
83
|
});
|
|
59
84
|
});
|
|
85
|
+
|
|
60
86
|
describe("GEOJSON", () => {
|
|
61
87
|
describe("with inline data", () => {
|
|
62
88
|
beforeEach(async () => {
|
|
63
89
|
layerModel = MAP_CTX_LAYER_GEOJSON_FIXTURE;
|
|
64
|
-
style = await createLayer(layerModel
|
|
65
|
-
Math.random = vi.fn(() => 0.027404);
|
|
90
|
+
style = (await createLayer(layerModel)) as PartialStyleSpecification;
|
|
66
91
|
});
|
|
67
92
|
it("create a VectorLayer", () => {
|
|
68
93
|
expect(style).toBeTruthy();
|
|
@@ -70,23 +95,35 @@ describe("MapContextService", () => {
|
|
|
70
95
|
it("create a source", () => {
|
|
71
96
|
const sourcesIds = Object.keys(style.sources);
|
|
72
97
|
expect(sourcesIds.length).toBe(1);
|
|
73
|
-
expect(sourcesIds[0]).toBe("
|
|
98
|
+
expect(sourcesIds[0]).toBe("123456");
|
|
74
99
|
});
|
|
75
100
|
it("create 3 layers", () => {
|
|
76
101
|
expect(style.layers).toBeTruthy();
|
|
77
102
|
expect(style.layers.length).toBe(3);
|
|
78
103
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
104
|
+
const sourceId = "123456";
|
|
105
|
+
const fillLayer = style.layers[0] as FillLayerSpecification;
|
|
106
|
+
const metadata = fillLayer.metadata as LayerMetadataSpecification;
|
|
82
107
|
|
|
83
|
-
|
|
84
|
-
expect(
|
|
85
|
-
expect(
|
|
108
|
+
expect(fillLayer.id).toBe(`${sourceId}-fill`);
|
|
109
|
+
expect(fillLayer.source).toBe(sourceId);
|
|
110
|
+
expect(metadata.layerId).toBeUndefined();
|
|
111
|
+
expect(metadata.layerHash).toBeTypeOf("string");
|
|
112
|
+
expect(fillLayer.paint?.["fill-opacity"]).toBe(0.8);
|
|
113
|
+
expect(fillLayer.layout?.visibility).toBe("visible");
|
|
86
114
|
|
|
87
|
-
|
|
88
|
-
expect(
|
|
89
|
-
expect(
|
|
115
|
+
const lineLayer = style.layers[1] as LineLayerSpecification;
|
|
116
|
+
expect(lineLayer.id).toBe(`${sourceId}-line`);
|
|
117
|
+
expect(lineLayer.source).toBe(sourceId);
|
|
118
|
+
expect(lineLayer.paint?.["line-opacity"]).toBe(0.8);
|
|
119
|
+
expect(lineLayer.layout?.visibility).toBe("visible");
|
|
120
|
+
|
|
121
|
+
const circleLayer = style.layers[2] as CircleLayerSpecification;
|
|
122
|
+
expect(circleLayer.id).toBe(`${sourceId}-circle`);
|
|
123
|
+
expect(circleLayer.source).toBe(sourceId);
|
|
124
|
+
expect(circleLayer.paint?.["circle-opacity"]).toBe(0.8);
|
|
125
|
+
expect(circleLayer.paint?.["circle-stroke-opacity"]).toBe(0.8);
|
|
126
|
+
expect(circleLayer.layout?.visibility).toBe("visible");
|
|
90
127
|
});
|
|
91
128
|
|
|
92
129
|
it("set correct source properties", () => {
|
|
@@ -100,14 +137,15 @@ describe("MapContextService", () => {
|
|
|
100
137
|
it("set correct layer properties", () => {
|
|
101
138
|
const layer = style.layers[0] as FillLayerSpecification;
|
|
102
139
|
expect(layer.type).toBe(`fill`);
|
|
103
|
-
expect(layer.paint["fill-color"]).toBe("rgba(255,255,255,0.4)");
|
|
140
|
+
expect(layer.paint?.["fill-color"]).toBe("rgba(255,255,255,0.4)");
|
|
141
|
+
expect(layer.paint?.["fill-opacity"]).toBe(0.8);
|
|
104
142
|
});
|
|
105
143
|
});
|
|
106
144
|
describe("with inline data as string", () => {
|
|
107
145
|
beforeEach(async () => {
|
|
108
146
|
layerModel = { ...MAP_CTX_LAYER_GEOJSON_FIXTURE };
|
|
109
147
|
layerModel.data = JSON.stringify(layerModel.data);
|
|
110
|
-
style = await createLayer(layerModel
|
|
148
|
+
style = (await createLayer(layerModel)) as PartialStyleSpecification;
|
|
111
149
|
});
|
|
112
150
|
it("create a VectorLayer", () => {
|
|
113
151
|
expect(style).toBeTruthy();
|
|
@@ -133,8 +171,9 @@ describe("MapContextService", () => {
|
|
|
133
171
|
it("set correct layer properties", () => {
|
|
134
172
|
const layer = style.layers[0] as FillLayerSpecification;
|
|
135
173
|
expect(layer.type).toBe(`fill`);
|
|
136
|
-
expect(layer.paint["fill-color"]).toBe("rgba(255,255,255,0.4)");
|
|
137
|
-
expect(layer.paint["fill-opacity"]).
|
|
174
|
+
expect(layer.paint?.["fill-color"]).toBe("rgba(255,255,255,0.4)");
|
|
175
|
+
expect(layer.paint?.["fill-opacity"]).toBe(0.8);
|
|
176
|
+
expect(layer.layout?.visibility).toBe("visible");
|
|
138
177
|
});
|
|
139
178
|
});
|
|
140
179
|
describe("with invalid inline data as string", () => {
|
|
@@ -146,7 +185,7 @@ describe("MapContextService", () => {
|
|
|
146
185
|
url: undefined,
|
|
147
186
|
data: "blargz",
|
|
148
187
|
} as LayerGeojsonWithData;
|
|
149
|
-
style = await createLayer(layerModel
|
|
188
|
+
style = (await createLayer(layerModel)) as PartialStyleSpecification;
|
|
150
189
|
});
|
|
151
190
|
it("create a VectorLayer", () => {
|
|
152
191
|
expect(style).toBeTruthy();
|
|
@@ -156,7 +195,7 @@ describe("MapContextService", () => {
|
|
|
156
195
|
});
|
|
157
196
|
it("create an empty VectorSource source", () => {
|
|
158
197
|
expect(style.sources).toEqual({
|
|
159
|
-
"
|
|
198
|
+
"123456": {
|
|
160
199
|
data: {
|
|
161
200
|
features: [],
|
|
162
201
|
type: "FeatureCollection",
|
|
@@ -173,9 +212,9 @@ describe("MapContextService", () => {
|
|
|
173
212
|
ok: true,
|
|
174
213
|
json: () =>
|
|
175
214
|
Promise.resolve(FEATURE_COLLECTION_POLYGON_FIXTURE_4326),
|
|
176
|
-
}),
|
|
215
|
+
} as Response),
|
|
177
216
|
);
|
|
178
|
-
style = await createLayer(layerModel
|
|
217
|
+
style = (await createLayer(layerModel))!;
|
|
179
218
|
});
|
|
180
219
|
it("create a VectorLayer", () => {
|
|
181
220
|
expect(style).toBeTruthy();
|
|
@@ -183,6 +222,7 @@ describe("MapContextService", () => {
|
|
|
183
222
|
it("create a source", () => {
|
|
184
223
|
const sourcesIds = Object.keys(style.sources);
|
|
185
224
|
expect(sourcesIds.length).toBe(1);
|
|
225
|
+
expect(sourcesIds[0]).toBe("123456");
|
|
186
226
|
});
|
|
187
227
|
it("create 3 layers", () => {
|
|
188
228
|
expect(style.layers).toBeTruthy();
|
|
@@ -203,16 +243,18 @@ describe("MapContextService", () => {
|
|
|
203
243
|
it("set correct layer properties", () => {
|
|
204
244
|
const layer = style.layers[0] as FillLayerSpecification;
|
|
205
245
|
expect(layer.type).toBe(`fill`);
|
|
206
|
-
expect(layer.paint["fill-color"]).toBe("rgba(255,255,255,0.4)");
|
|
207
|
-
expect(layer.paint["fill-opacity"]).
|
|
246
|
+
expect(layer.paint?.["fill-color"]).toBe("rgba(255,255,255,0.4)");
|
|
247
|
+
expect(layer.paint?.["fill-opacity"]).toBe(1);
|
|
248
|
+
expect(layer.layout?.visibility).toBe("visible");
|
|
208
249
|
});
|
|
209
250
|
});
|
|
210
251
|
});
|
|
211
252
|
});
|
|
253
|
+
|
|
212
254
|
describe("WFS", () => {
|
|
213
255
|
beforeEach(async () => {
|
|
214
|
-
|
|
215
|
-
|
|
256
|
+
layerModel = MAP_CTX_LAYER_WFS_FIXTURE;
|
|
257
|
+
style = (await createLayer(layerModel)) as PartialStyleSpecification;
|
|
216
258
|
});
|
|
217
259
|
it("create a vector layer", () => {
|
|
218
260
|
expect(style).toBeTruthy();
|
|
@@ -222,7 +264,7 @@ describe("MapContextService", () => {
|
|
|
222
264
|
expect(sourcesIds.length).toBe(1);
|
|
223
265
|
const id = sourcesIds[0];
|
|
224
266
|
const source = style.sources[id] as GeoJSONSourceSpecification;
|
|
225
|
-
expect(id).toBe("
|
|
267
|
+
expect(id).toBe("123456");
|
|
226
268
|
expect(source.data).toEqual(
|
|
227
269
|
"https://www.datagrandest.fr/geoserver/region-grand-est/ows?service=WFS&version=1.1.0&request=GetFeature&outputFormat=application%2Fjson&typename=ms%3Acommune_actuelle_3857&srsname=EPSG%3A3857&bbox=10%2C20%2C30%2C40%2CEPSG%3A3857&maxFeatures=10000",
|
|
228
270
|
);
|
|
@@ -231,35 +273,36 @@ describe("MapContextService", () => {
|
|
|
231
273
|
expect(style.layers).toBeTruthy();
|
|
232
274
|
expect(style.layers.length).toBe(3);
|
|
233
275
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
expect(layer.source).toBe("985400327");
|
|
238
|
-
expect(layer.metadata.sourcePosition).toBe(1);
|
|
276
|
+
const sourceId = "123456";
|
|
277
|
+
const fillLayer = style.layers[0] as FillLayerSpecification;
|
|
278
|
+
const metadata = fillLayer.metadata as LayerMetadataSpecification;
|
|
239
279
|
|
|
240
|
-
|
|
241
|
-
expect(
|
|
242
|
-
expect(
|
|
243
|
-
expect(
|
|
280
|
+
expect(fillLayer.id).toBe(`${sourceId}-fill`);
|
|
281
|
+
expect(fillLayer.source).toBe(sourceId);
|
|
282
|
+
expect(metadata.layerId).toBeUndefined();
|
|
283
|
+
expect(metadata.layerHash).toBeTypeOf("string");
|
|
284
|
+
expect(fillLayer.paint?.["fill-opacity"]).toBe(0.5);
|
|
285
|
+
expect(fillLayer.layout?.visibility).toBe("visible");
|
|
244
286
|
|
|
245
|
-
|
|
246
|
-
expect(
|
|
247
|
-
expect(
|
|
248
|
-
expect(
|
|
287
|
+
const lineLayer = style.layers[1] as LineLayerSpecification;
|
|
288
|
+
expect(lineLayer.id).toBe(`${sourceId}-line`);
|
|
289
|
+
expect(lineLayer.source).toBe(sourceId);
|
|
290
|
+
expect(lineLayer.paint?.["line-opacity"]).toBe(0.5);
|
|
291
|
+
expect(lineLayer.layout?.visibility).toBe("visible");
|
|
292
|
+
|
|
293
|
+
const circleLayer = style.layers[2] as CircleLayerSpecification;
|
|
294
|
+
expect(circleLayer.id).toBe(`${sourceId}-circle`);
|
|
295
|
+
expect(circleLayer.source).toBe(sourceId);
|
|
296
|
+
expect(circleLayer.paint?.["circle-opacity"]).toBe(0.5);
|
|
297
|
+
expect(circleLayer.paint?.["circle-stroke-opacity"]).toBe(0.5);
|
|
298
|
+
expect(circleLayer.layout?.visibility).toBe("visible");
|
|
249
299
|
});
|
|
250
300
|
});
|
|
301
|
+
|
|
251
302
|
describe("OGCAPI", () => {
|
|
252
303
|
beforeEach(async () => {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
ok: true,
|
|
256
|
-
json: () =>
|
|
257
|
-
Promise.resolve(FEATURE_COLLECTION_LINESTRING_FIXTURE_4326),
|
|
258
|
-
}),
|
|
259
|
-
);
|
|
260
|
-
|
|
261
|
-
(layerModel = MAP_CTX_LAYER_OGCAPI_FIXTURE),
|
|
262
|
-
(style = await createLayer(layerModel, 0));
|
|
304
|
+
layerModel = MAP_CTX_LAYER_OGCAPI_FIXTURE;
|
|
305
|
+
style = (await createLayer(layerModel)) as PartialStyleSpecification;
|
|
263
306
|
});
|
|
264
307
|
it("create a vector layer", () => {
|
|
265
308
|
expect(style).toBeTruthy();
|
|
@@ -269,7 +312,7 @@ describe("MapContextService", () => {
|
|
|
269
312
|
expect(sourcesIds.length).toBe(1);
|
|
270
313
|
const id = sourcesIds[0];
|
|
271
314
|
const source = style.sources[id] as GeoJSONSourceSpecification;
|
|
272
|
-
expect(id).toBe("
|
|
315
|
+
expect(id).toBe("123456");
|
|
273
316
|
expect(source.data).toEqual(
|
|
274
317
|
"https://demo.ldproxy.net/zoomstack/collections/airports/items?f=json",
|
|
275
318
|
);
|
|
@@ -277,10 +320,62 @@ describe("MapContextService", () => {
|
|
|
277
320
|
it("create 3 layers", () => {
|
|
278
321
|
expect(style.layers).toBeTruthy();
|
|
279
322
|
expect(style.layers.length).toBe(3);
|
|
323
|
+
|
|
324
|
+
const sourceId = "123456";
|
|
280
325
|
const layer = style.layers[0] as FillLayerSpecification;
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
expect(layer.
|
|
326
|
+
const metadata = layer.metadata as LayerMetadataSpecification;
|
|
327
|
+
|
|
328
|
+
expect(layer.id).toBe(`${sourceId}-fill`);
|
|
329
|
+
expect(layer.source).toBe(sourceId);
|
|
330
|
+
expect(metadata.layerId).toBeUndefined();
|
|
331
|
+
expect(metadata.layerHash).toBeTypeOf("string");
|
|
332
|
+
expect(layer.paint?.["fill-opacity"]).toBe(1);
|
|
333
|
+
expect(layer.layout?.visibility).toBe("visible");
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
describe("XYZ", () => {
|
|
338
|
+
beforeEach(async () => {
|
|
339
|
+
layerModel = MAP_CTX_LAYER_XYZ_FIXTURE;
|
|
340
|
+
style = (await createLayer(layerModel)) as PartialStyleSpecification;
|
|
341
|
+
});
|
|
342
|
+
it("create a layer and source", () => {
|
|
343
|
+
const sourceId = "123456";
|
|
344
|
+
|
|
345
|
+
expect(style).toEqual({
|
|
346
|
+
layers: [
|
|
347
|
+
{
|
|
348
|
+
id: sourceId,
|
|
349
|
+
layout: {
|
|
350
|
+
visibility: "visible",
|
|
351
|
+
},
|
|
352
|
+
metadata: {
|
|
353
|
+
layerHash: "3863171382",
|
|
354
|
+
},
|
|
355
|
+
paint: {
|
|
356
|
+
"raster-opacity": 1,
|
|
357
|
+
},
|
|
358
|
+
source: sourceId,
|
|
359
|
+
type: "raster",
|
|
360
|
+
},
|
|
361
|
+
],
|
|
362
|
+
sources: {
|
|
363
|
+
[sourceId]: {
|
|
364
|
+
tileSize: 256,
|
|
365
|
+
tiles: ["https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png"],
|
|
366
|
+
type: "raster",
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
});
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
describe("WMTS", () => {
|
|
374
|
+
beforeEach(async () => {
|
|
375
|
+
layerModel = MAP_CTX_LAYER_WMTS_FIXTURE;
|
|
376
|
+
});
|
|
377
|
+
it("does not support this layer type", async () => {
|
|
378
|
+
expect(await createLayer(layerModel)).toBe(null);
|
|
284
379
|
});
|
|
285
380
|
});
|
|
286
381
|
});
|