@open-pioneer/map-test-utils 1.5.0-dev.20260911123645 → 1.5.0-dev.20260917081843

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/CHANGELOG.md CHANGED
@@ -1,10 +1,17 @@
1
1
  # @open-pioneer/map-test-utils
2
2
 
3
- ## 1.5.0-dev.20260911123645
3
+ ## 1.5.0-dev.20260917081843
4
4
 
5
5
  ### Minor Changes
6
6
 
7
7
  - f790fda: Update to Chakra 3.37.0
8
+ - 0d9a9d0: The map initialization has been adjusted to fix the map view initialization if initial view is configured with extent.
9
+ This change affects the order and timing of the map's initialization.
10
+
11
+ The timing changes might affect early map interactions or tests:
12
+ To wait until the map is actually being rendered (and thus fully initialized), you can use the map model's existing `whenDisplayed()` method.
13
+ The new test helper function `waitForMapRender` is provided from (`@open-pioneer/map-test-utils`) to wait in tests for the map view to be completely initialized.
14
+
8
15
  - ebda251: Add new properties for topmost layers and base layers in `MapConfig`.
9
16
 
10
17
  - With `MapConfig.topmostLayers` topmost layers can now be defined in the initial map setup.
@@ -41,6 +48,7 @@
41
48
  ### Patch Changes
42
49
 
43
50
  - 09ec7c7: Updated dependencies
51
+ - 0d9a9d0: Do not mock layer rendering when vitest browser mode is detected.
44
52
 
45
53
  ## 1.4.0
46
54
 
package/index.d.ts CHANGED
@@ -58,7 +58,18 @@ export interface SimpleMapOptions {
58
58
  * Use `false` to test the async loading behavior of the registry.
59
59
  */
60
60
  returnMap?: boolean;
61
+ /**
62
+ * If true, the map is rendered in a dummy div instead of the real OpenLayers canvas.
63
+ * This is useful for tests that need the map's view to be initialized, but don't need to actually render the map.
64
+ *
65
+ * False by default.
66
+ */
67
+ mockMapRender?: boolean;
61
68
  }
69
+ /**
70
+ * Waits until the OpenLayers map is initialized/displayed and is visible in the DOM.
71
+ */
72
+ export declare function waitForMapRender(map: MapModel): Promise<void>;
62
73
  /**
63
74
  * Waits until the OpenLayers map has been mounted in the parent with the given id.
64
75
  */
@@ -82,13 +93,31 @@ export interface SetupMapResult {
82
93
  */
83
94
  export declare function setupMap(options?: SimpleMapOptions & {
84
95
  returnMap?: true;
96
+ mockMapRender?: boolean;
85
97
  }): Promise<SetupMapResult & {
86
98
  map: MapModel;
87
99
  }>;
88
100
  export declare function setupMap(options?: SimpleMapOptions): Promise<SetupMapResult>;
101
+ /**
102
+ * Renders an OL map into a pseudo (non-visible) div so the map's view gets initialized.
103
+ */
104
+ export declare function mockMapRender(map: MapModel): void;
89
105
  /** Creates an new layer of the specified type for testing. */
90
106
  export declare function createTestLayer<LayerType extends Layer, Config extends MapPackageLayerConfig>(config: LayerCreateOptions<LayerType, Config>, mapOptions?: Pick<SimpleMapOptions, "fetch">): LayerType;
91
- /** Creates a new, basic SimpleLayer for testing. */
107
+ /**
108
+ *
109
+ * Creates a new, basic SimpleLayer for testing.
110
+ *
111
+ * For example:
112
+ *
113
+ * ```ts
114
+ * const layer1 = createTestLayer();
115
+ * const layer2 = createTestLayer({
116
+ * title: "My test layer",
117
+ * olLayer: ...
118
+ * })
119
+ * ```
120
+ **/
92
121
  export declare function createTestLayer(config?: SimpleLayerConfig, mapOptions?: Pick<SimpleMapOptions, "fetch">): SimpleLayer;
93
122
  /**
94
123
  * Returns a simple, empty OpenLayers layer object.
package/index.js CHANGED
@@ -14,6 +14,15 @@ const DUMMY_HTTP_SERVICE = {
14
14
  }
15
15
  };
16
16
  const DUMMY_LAYER_FACTORY = createLayerFactory();
17
+ async function waitForMapRender(map) {
18
+ await map.whenDisplayed();
19
+ await waitFor(async () => {
20
+ const container = map.container?.querySelector(".ol-viewport");
21
+ if (!container) {
22
+ throw new Error("map not mounted");
23
+ }
24
+ });
25
+ }
17
26
  async function waitForMapMount(parentTestId = "base") {
18
27
  return await waitFor(async () => {
19
28
  const domElement = await screen.findByTestId(parentTestId);
@@ -78,13 +87,24 @@ async function setupMap(options) {
78
87
  });
79
88
  let map;
80
89
  const promise = registry.createMapModel(mapId, mapConfig);
81
- if (options?.returnMap !== false) {
90
+ if (options?.returnMap !== false || options?.mockMapRender) {
82
91
  map = await promise;
92
+ if (options?.mockMapRender) {
93
+ mockMapRender(map);
94
+ }
83
95
  } else {
84
96
  promise.catch(() => void 0);
85
97
  }
86
98
  return { mapId, registry, layerFactory, map };
87
99
  }
100
+ function mockMapRender(map) {
101
+ const dummyContainer = document.createElement("div");
102
+ dummyContainer.style.width = "100px";
103
+ dummyContainer.style.height = "100px";
104
+ dummyContainer.setAttribute("data-testid", "map");
105
+ document.body.appendChild(dummyContainer);
106
+ map.olMap.setTarget(dummyContainer);
107
+ }
88
108
  function getInitialView(options) {
89
109
  if (options?.extent) {
90
110
  return {
@@ -129,16 +149,21 @@ function createLayerFactory(httpService) {
129
149
  referencesMeta: { httpService: { serviceId: "http.HttpService" } }
130
150
  });
131
151
  }
132
- function mockVectorLayer() {
152
+ function mockLayers() {
133
153
  const div = document.createElement("div");
134
154
  VectorLayer.prototype.render = () => {
135
155
  return div;
136
156
  };
157
+ TileLayer.prototype.render = () => {
158
+ return div;
159
+ };
137
160
  }
138
161
  function useOrCreateLayer(config) {
139
162
  return "map" in config ? config : createTestLayer({ type: SimpleLayer, ...config });
140
163
  }
141
- mockVectorLayer();
164
+ if (!globalThis.__vitest_browser__) {
165
+ mockLayers();
166
+ }
142
167
 
143
- export { createServiceOptions, createTestLayer, createTestOlLayer, setupMap, waitForInitialExtent, waitForMapMount };
168
+ export { createServiceOptions, createTestLayer, createTestOlLayer, mockMapRender, setupMap, waitForInitialExtent, waitForMapMount, waitForMapRender };
144
169
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["index.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { constant, watch } from \"@conterra/reactivity-core\";\nimport { HttpService, HttpServiceRequestInit } from \"@open-pioneer/http\";\nimport {\n ExtentConfig,\n InitialViewConfig,\n Layer,\n LayerCreateOptions,\n LayerFactory,\n MapConfig,\n MapModel,\n LayerConfig as MapPackageLayerConfig,\n MapRegistry,\n OlMapOptions,\n SimpleLayer,\n SimpleLayerConfig\n} from \"@open-pioneer/map\";\nimport {\n LayerFactory as LayerFactoryImpl,\n MapRegistry as MapRegistryImpl\n} from \"@open-pioneer/map/internalTestSupport\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport { createService } from \"@open-pioneer/test-utils/services\";\nimport { screen, waitFor } from \"@testing-library/react\";\nimport TileLayer from \"ol/layer/Tile\";\nimport VectorLayer from \"ol/layer/Vector\";\n\nexport type LayerConfig = SimpleLayerConfig | Layer;\n\nexport interface SimpleMapOptions {\n /** ID of the map.\n * Defaults to \"test\". */\n mapId?: string;\n\n /** Center coordinates for the map. */\n center?: { x: number; y: number };\n\n /** Zoom level of the map. */\n zoom?: number;\n\n /**\n * Initial extent (don't mix with center / zoom).\n */\n extent?: ExtentConfig;\n\n /**\n * The map's projection.\n */\n projection?: string;\n\n /**\n * Layers used by the map.\n */\n layers?: LayerConfig[];\n\n /**\n * Base layers for the map.\n */\n baseLayers?: LayerConfig[];\n\n /**\n * Layers that are displayed on top of all other layers.\n */\n topmostLayers?: LayerConfig[];\n\n /** See {@link MapConfig.showAttributions} */\n showAttributions?: boolean;\n\n /**\n * Overrides fetching of network resources (such as service capabilities).\n */\n fetch?: (resource: URL, init: HttpServiceRequestInit | undefined) => Promise<Response>;\n\n /**\n * Passed to the open layers map constructor.\n */\n advanced?: OlMapOptions;\n\n /**\n * Disables the initial view when set to true.\n */\n noInitialView?: boolean;\n\n /**\n * Disables the default projection when set to true.\n */\n noProjection?: boolean;\n\n /**\n * Also returns the map object in the return value.\n * True by default.\n *\n * Use `false` to test the async loading behavior of the registry.\n */\n returnMap?: boolean;\n}\nconst DUMMY_HTTP_SERVICE = {\n async fetch() {\n throw new Error(\n \"Network requests are not implemented (override fetch via map test utils if your test requires network access).\"\n );\n }\n} satisfies Partial<HttpService> as HttpService;\nconst DUMMY_LAYER_FACTORY = createLayerFactory();\n\n/**\n * Waits until the OpenLayers map has been mounted in the parent with the given id.\n */\nexport async function waitForMapMount(parentTestId = \"base\") {\n return await waitFor(async () => {\n const domElement = await screen.findByTestId(parentTestId);\n const container = domElement.querySelector(\".ol-viewport\");\n if (!container) {\n throw new Error(\"map not mounted\");\n }\n return domElement;\n });\n}\n\n/**\n * Waits until the model has an initial extent.\n */\nexport async function waitForInitialExtent(model: MapModel) {\n if (model.initialExtent) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const resource = watch(\n () => [model.initialExtent],\n ([extent]) => {\n resource.destroy();\n if (extent) {\n resolve();\n } else {\n reject(new Error(\"Expected a valid initial extent\"));\n }\n }\n );\n });\n}\n\nexport interface SetupMapResult {\n mapId: string;\n registry: MapRegistry;\n layerFactory: LayerFactory;\n}\n\n/**\n * Creates a simple map registry service with exactly one map configuration.\n *\n * The map is configured by using the `options` parameter.\n * If `options.returnMap` is `true` (the default), the map model is also returned.\n *\n * Returns the map registry and the id of the configured map.\n */\nexport async function setupMap(\n options?: SimpleMapOptions & { returnMap?: true }\n): Promise<SetupMapResult & { map: MapModel }>;\nexport async function setupMap(options?: SimpleMapOptions): Promise<SetupMapResult>;\nexport async function setupMap(\n options?: SimpleMapOptions\n): Promise<SetupMapResult & { map: MapModel | undefined }> {\n const mapId = options?.mapId ?? \"test\";\n const mapConfig: MapConfig = {\n initialView: options?.noInitialView ? undefined : getInitialView(options),\n projection: options?.noProjection ? undefined : (options?.projection ?? \"EPSG:3857\"),\n layers: options?.layers?.map((config) => useOrCreateLayer(config)) ?? [createTestLayer()],\n baseLayers: options?.baseLayers?.map((config) => useOrCreateLayer(config)) ?? [],\n topmostLayers: options?.topmostLayers?.map((config) => useOrCreateLayer(config)) ?? [],\n showAttributions: options?.showAttributions,\n advanced: options?.advanced\n };\n\n const httpService = {\n async fetch(resource, init) {\n if (options?.fetch) {\n const url = new URL(resource, \"http://localhost:1234\");\n return options.fetch(url, init);\n }\n throw new Error(\n \"Network requests are not implemented (override fetch via map test utils if your test requires network access).\"\n );\n }\n } satisfies Partial<HttpService> as HttpService;\n\n const layerFactory = await createService(LayerFactoryImpl, {\n references: {\n httpService\n }\n });\n\n const registry = await createService(MapRegistryImpl, {\n references: {\n providers: [],\n httpService,\n layerFactory\n }\n });\n\n let map: MapModel | undefined;\n const promise = registry.createMapModel(mapId, mapConfig);\n if (options?.returnMap !== false) {\n map = await promise;\n } else {\n // Ignore error on this promise (prevents unhandled error in tests)\n promise.catch(() => undefined);\n }\n return { mapId, registry, layerFactory, map };\n}\n\nfunction getInitialView(options: SimpleMapOptions | undefined): InitialViewConfig {\n if (options?.extent) {\n return {\n kind: \"extent\",\n extent: options.extent\n };\n }\n return {\n kind: \"position\",\n center: options?.center ?? { x: 847541, y: 6793584 },\n zoom: options?.zoom ?? 10\n };\n}\n\n/** Creates an new layer of the specified type for testing. */\nexport function createTestLayer<LayerType extends Layer, Config extends MapPackageLayerConfig>(\n config: LayerCreateOptions<LayerType, Config>,\n mapOptions?: Pick<SimpleMapOptions, \"fetch\">\n): LayerType;\n\n/** Creates a new, basic SimpleLayer for testing. */\nexport function createTestLayer(\n config?: SimpleLayerConfig,\n mapOptions?: Pick<SimpleMapOptions, \"fetch\">\n): SimpleLayer;\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nexport function createTestLayer(config?: any, mapOptions?: Pick<SimpleMapOptions, \"fetch\">): Layer {\n // Basic case: If no config is given, use SimpleLayer\n if (!config) {\n config = {\n type: SimpleLayer,\n title: \"Test layer\",\n olLayer: new VectorLayer()\n } as LayerCreateOptions<SimpleLayer, SimpleLayerConfig>;\n } else if (!config.type) {\n config.type = SimpleLayer;\n }\n\n const factory = mapOptions?.fetch\n ? createLayerFactory({ fetch: mapOptions.fetch })\n : DUMMY_LAYER_FACTORY;\n return factory.create(config);\n}\n\n/**\n * Returns a simple, empty OpenLayers layer object.\n *\n * Use this if you need any kind of `olLayer` in your test.\n */\nexport function createTestOlLayer(): TileLayer {\n return new TileLayer();\n}\n\n/**\n * Creates (service name, service implementation)-pairs suitable for the `services`\n * option of the `PackageContextProvider`.\n *\n * This helper method can be used to avoid hard-coding service names used in the implementation.\n *\n * @deprecated This function is no longer needed, since most widgets no longer depend on the registry\n * and accept the `map` directly.\n */\nexport function createServiceOptions(services: { registry: MapRegistry }): Record<string, unknown> {\n return {\n \"map.MapRegistry\": services.registry\n };\n}\n\nfunction createLayerFactory(httpService?: HttpService): LayerFactory {\n const intl = {} satisfies Partial<PackageIntl> as PackageIntl;\n return new LayerFactoryImpl({\n intl,\n currentIntl: constant(intl),\n references: { httpService: httpService ?? DUMMY_HTTP_SERVICE },\n properties: {},\n referencesMeta: { httpService: { serviceId: \"http.HttpService\" } }\n });\n}\n\nfunction mockVectorLayer() {\n // Overwrite render so it doesn't actually do anything during tests.\n // Would otherwise error because <canvas /> is not fully implemented in happy dom.\n const div = document.createElement(\"div\");\n VectorLayer.prototype.render = () => {\n return div;\n };\n}\n\nfunction useOrCreateLayer(config: LayerConfig): Layer {\n return \"map\" in config\n ? config\n : createTestLayer({ type: SimpleLayer, ...(config as SimpleLayerConfig) });\n // using map as discriminator (no prototype for Layer)\n}\n\nmockVectorLayer();\n"],"names":["LayerFactoryImpl","MapRegistryImpl"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["index.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { constant, watch } from \"@conterra/reactivity-core\";\nimport { HttpService, HttpServiceRequestInit } from \"@open-pioneer/http\";\nimport {\n ExtentConfig,\n InitialViewConfig,\n Layer,\n LayerCreateOptions,\n LayerFactory,\n MapConfig,\n MapModel,\n LayerConfig as MapPackageLayerConfig,\n MapRegistry,\n OlMapOptions,\n SimpleLayer,\n SimpleLayerConfig\n} from \"@open-pioneer/map\";\nimport {\n LayerFactory as LayerFactoryImpl,\n MapRegistry as MapRegistryImpl\n} from \"@open-pioneer/map/internalTestSupport\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport { createService } from \"@open-pioneer/test-utils/services\";\nimport { screen, waitFor } from \"@testing-library/react\";\nimport TileLayer from \"ol/layer/Tile\";\nimport VectorLayer from \"ol/layer/Vector\";\n\nexport type LayerConfig = SimpleLayerConfig | Layer;\n\nexport interface SimpleMapOptions {\n /** ID of the map.\n * Defaults to \"test\". */\n mapId?: string;\n\n /** Center coordinates for the map. */\n center?: { x: number; y: number };\n\n /** Zoom level of the map. */\n zoom?: number;\n\n /**\n * Initial extent (don't mix with center / zoom).\n */\n extent?: ExtentConfig;\n\n /**\n * The map's projection.\n */\n projection?: string;\n\n /**\n * Layers used by the map.\n */\n layers?: LayerConfig[];\n\n /**\n * Base layers for the map.\n */\n baseLayers?: LayerConfig[];\n\n /**\n * Layers that are displayed on top of all other layers.\n */\n topmostLayers?: LayerConfig[];\n\n /** See {@link MapConfig.showAttributions} */\n showAttributions?: boolean;\n\n /**\n * Overrides fetching of network resources (such as service capabilities).\n */\n fetch?: (resource: URL, init: HttpServiceRequestInit | undefined) => Promise<Response>;\n\n /**\n * Passed to the open layers map constructor.\n */\n advanced?: OlMapOptions;\n\n /**\n * Disables the initial view when set to true.\n */\n noInitialView?: boolean;\n\n /**\n * Disables the default projection when set to true.\n */\n noProjection?: boolean;\n\n /**\n * Also returns the map object in the return value.\n * True by default.\n *\n * Use `false` to test the async loading behavior of the registry.\n */\n returnMap?: boolean;\n\n /**\n * If true, the map is rendered in a dummy div instead of the real OpenLayers canvas.\n * This is useful for tests that need the map's view to be initialized, but don't need to actually render the map.\n *\n * False by default.\n */\n mockMapRender?: boolean;\n}\nconst DUMMY_HTTP_SERVICE = {\n async fetch() {\n throw new Error(\n \"Network requests are not implemented (override fetch via map test utils if your test requires network access).\"\n );\n }\n} satisfies Partial<HttpService> as HttpService;\nconst DUMMY_LAYER_FACTORY = createLayerFactory();\n\n/**\n * Waits until the OpenLayers map is initialized/displayed and is visible in the DOM.\n */\nexport async function waitForMapRender(map: MapModel) {\n await map.whenDisplayed();\n await waitFor(async () => {\n const container = map.container?.querySelector(\".ol-viewport\");\n if (!container) {\n throw new Error(\"map not mounted\");\n }\n });\n}\n\n/**\n * Waits until the OpenLayers map has been mounted in the parent with the given id.\n */\nexport async function waitForMapMount(parentTestId = \"base\") {\n return await waitFor(async () => {\n const domElement = await screen.findByTestId(parentTestId);\n const container = domElement.querySelector(\".ol-viewport\");\n if (!container) {\n throw new Error(\"map not mounted\");\n }\n return domElement;\n });\n}\n\n/**\n * Waits until the model has an initial extent.\n */\nexport async function waitForInitialExtent(model: MapModel) {\n if (model.initialExtent) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const resource = watch(\n () => [model.initialExtent],\n ([extent]) => {\n resource.destroy();\n if (extent) {\n resolve();\n } else {\n reject(new Error(\"Expected a valid initial extent\"));\n }\n }\n );\n });\n}\n\nexport interface SetupMapResult {\n mapId: string;\n registry: MapRegistry;\n layerFactory: LayerFactory;\n}\n\n/**\n * Creates a simple map registry service with exactly one map configuration.\n *\n * The map is configured by using the `options` parameter.\n * If `options.returnMap` is `true` (the default), the map model is also returned.\n *\n * Returns the map registry and the id of the configured map.\n */\nexport async function setupMap(\n options?: SimpleMapOptions & { returnMap?: true; mockMapRender?: boolean }\n): Promise<SetupMapResult & { map: MapModel }>;\nexport async function setupMap(options?: SimpleMapOptions): Promise<SetupMapResult>;\nexport async function setupMap(\n options?: SimpleMapOptions\n): Promise<SetupMapResult & { map: MapModel | undefined }> {\n const mapId = options?.mapId ?? \"test\";\n const mapConfig: MapConfig = {\n initialView: options?.noInitialView ? undefined : getInitialView(options),\n projection: options?.noProjection ? undefined : (options?.projection ?? \"EPSG:3857\"),\n layers: options?.layers?.map((config) => useOrCreateLayer(config)) ?? [createTestLayer()],\n baseLayers: options?.baseLayers?.map((config) => useOrCreateLayer(config)) ?? [],\n topmostLayers: options?.topmostLayers?.map((config) => useOrCreateLayer(config)) ?? [],\n showAttributions: options?.showAttributions,\n advanced: options?.advanced\n };\n\n const httpService = {\n async fetch(resource, init) {\n if (options?.fetch) {\n const url = new URL(resource, \"http://localhost:1234\");\n return options.fetch(url, init);\n }\n throw new Error(\n \"Network requests are not implemented (override fetch via map test utils if your test requires network access).\"\n );\n }\n } satisfies Partial<HttpService> as HttpService;\n\n const layerFactory = await createService(LayerFactoryImpl, {\n references: {\n httpService\n }\n });\n\n const registry = await createService(MapRegistryImpl, {\n references: {\n providers: [],\n httpService,\n layerFactory\n }\n });\n\n let map: MapModel | undefined;\n const promise = registry.createMapModel(mapId, mapConfig);\n if (options?.returnMap !== false || options?.mockMapRender) {\n map = await promise;\n\n if (options?.mockMapRender) {\n mockMapRender(map);\n }\n } else {\n // Ignore error on this promise (prevents unhandled error in tests)\n promise.catch(() => undefined);\n }\n return { mapId, registry, layerFactory, map };\n}\n\n/**\n * Renders an OL map into a pseudo (non-visible) div so the map's view gets initialized.\n */\nexport function mockMapRender(map: MapModel) {\n const dummyContainer = document.createElement(\"div\");\n dummyContainer.style.width = \"100px\";\n dummyContainer.style.height = \"100px\";\n dummyContainer.setAttribute(\"data-testid\", \"map\");\n document.body.appendChild(dummyContainer);\n map.olMap.setTarget(dummyContainer);\n}\n\nfunction getInitialView(options: SimpleMapOptions | undefined): InitialViewConfig {\n if (options?.extent) {\n return {\n kind: \"extent\",\n extent: options.extent\n };\n }\n return {\n kind: \"position\",\n center: options?.center ?? { x: 847541, y: 6793584 },\n zoom: options?.zoom ?? 10\n };\n}\n\n/** Creates an new layer of the specified type for testing. */\nexport function createTestLayer<LayerType extends Layer, Config extends MapPackageLayerConfig>(\n config: LayerCreateOptions<LayerType, Config>,\n mapOptions?: Pick<SimpleMapOptions, \"fetch\">\n): LayerType;\n\n/**\n *\n * Creates a new, basic SimpleLayer for testing.\n *\n * For example:\n *\n * ```ts\n * const layer1 = createTestLayer();\n * const layer2 = createTestLayer({\n * title: \"My test layer\",\n * olLayer: ...\n * })\n * ```\n **/\nexport function createTestLayer(\n config?: SimpleLayerConfig,\n mapOptions?: Pick<SimpleMapOptions, \"fetch\">\n): SimpleLayer;\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nexport function createTestLayer(config?: any, mapOptions?: Pick<SimpleMapOptions, \"fetch\">): Layer {\n // Basic case: If no config is given, use SimpleLayer\n if (!config) {\n config = {\n type: SimpleLayer,\n title: \"Test layer\",\n olLayer: new VectorLayer()\n } as LayerCreateOptions<SimpleLayer, SimpleLayerConfig>;\n } else if (!config.type) {\n config.type = SimpleLayer;\n }\n\n const factory = mapOptions?.fetch\n ? createLayerFactory({ fetch: mapOptions.fetch })\n : DUMMY_LAYER_FACTORY;\n return factory.create(config);\n}\n\n/**\n * Returns a simple, empty OpenLayers layer object.\n *\n * Use this if you need any kind of `olLayer` in your test.\n */\nexport function createTestOlLayer(): TileLayer {\n return new TileLayer();\n}\n\n/**\n * Creates (service name, service implementation)-pairs suitable for the `services`\n * option of the `PackageContextProvider`.\n *\n * This helper method can be used to avoid hard-coding service names used in the implementation.\n *\n * @deprecated This function is no longer needed, since most widgets no longer depend on the registry\n * and accept the `map` directly.\n */\nexport function createServiceOptions(services: { registry: MapRegistry }): Record<string, unknown> {\n return {\n \"map.MapRegistry\": services.registry\n };\n}\n\nfunction createLayerFactory(httpService?: HttpService): LayerFactory {\n const intl = {} satisfies Partial<PackageIntl> as PackageIntl;\n return new LayerFactoryImpl({\n intl,\n currentIntl: constant(intl),\n references: { httpService: httpService ?? DUMMY_HTTP_SERVICE },\n properties: {},\n referencesMeta: { httpService: { serviceId: \"http.HttpService\" } }\n });\n}\n\nfunction mockLayers() {\n // Overwrite render so it doesn't actually do anything during tests.\n // Would otherwise error because <canvas /> is not fully implemented in happy-dom.\n const div = document.createElement(\"div\");\n VectorLayer.prototype.render = () => {\n return div;\n };\n TileLayer.prototype.render = () => {\n return div;\n };\n}\n\nfunction useOrCreateLayer(config: LayerConfig): Layer {\n return \"map\" in config\n ? config\n : createTestLayer({ type: SimpleLayer, ...(config as SimpleLayerConfig) });\n // using map as discriminator (no prototype for Layer)\n}\n\n// Do not mock layer rendering when running in vitest's browser mode.\n// oxlint-disable-next-line typescript/no-explicit-any\nif (!(globalThis as any).__vitest_browser__) {\n mockLayers();\n}\n"],"names":["LayerFactoryImpl","MapRegistryImpl"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@open-pioneer/map-test-utils",
4
- "version": "1.5.0-dev.20260911123645",
4
+ "version": "1.5.0-dev.20260917081843",
5
5
  "description": "This package is an internal support package for testing map-related UI components.",
6
6
  "keywords": [
7
7
  "open-pioneer-trails"
@@ -15,7 +15,7 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "@conterra/reactivity-core": "^0.8.8",
18
- "@open-pioneer/map": "1.5.0-dev.20260911123645",
18
+ "@open-pioneer/map": "1.5.0-dev.20260917081843",
19
19
  "@open-pioneer/test-utils": "4.8.0-dev.20260910101405",
20
20
  "@testing-library/react": "^16.3.3",
21
21
  "ol": "^10.10.0"