@masterportal/masterportalapi 2.39.0 → 2.40.1

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
@@ -17,13 +17,38 @@
17
17
  ### Fixed
18
18
 
19
19
  ---
20
+
21
+ ## 2.41.0 - 2024-11-05
22
+
23
+ ### Fixed
24
+ - Tileset-Layer: custom tileset filename is allowed
25
+ - WFS-Layer: url for describeFeatureType requests respects questionmark.
26
+ - Issue #1279: Fixed keyboardEventTarget, so that keyboard interactions like KeyboardZoom and KeyboardPan work, if keyboardEventTarget id defined in config
27
+
28
+ ---
29
+
30
+ ## 2.40.0 - 2024-07-17
31
+
32
+ ### Added
33
+ - vectorStyle: enables support for additional polygon highlighting, including default styles.
34
+
35
+ ### Changed
36
+ - Replace `XMLHttpRequest` with `fetch` in `initializeLayerList`
37
+
38
+ ### Fixed
39
+ - OAF-Layer: bbox and bboxCrs are respected when building url.
40
+ - OAF-Layer: prevent url to not use more than one questionmark.
41
+
42
+ ---
43
+
20
44
  ## 2.39.0 - 2024-06-18
21
45
 
22
46
  ### Changed
23
- - peerDependencies:
24
- - @cesium/engine: 6.2.0 to 9.2.0
47
+ - peerDependencies:
48
+ - @cesium/engine: 6.2.0 to 9.2.0
25
49
 
26
50
  ---
51
+
27
52
  ## 2.38.0 - 2024-06-04
28
53
 
29
54
  ### Added
@@ -105,7 +105,8 @@
105
105
  "url": "https://api.hamburg.de/datasets/v1/schulen",
106
106
  "collection": "staatliche_schulen",
107
107
  "typ": "OAF",
108
- "crs": "http://www.opengis.net/def/crs/EPSG/0/25832"
108
+ "crs": "http://www.opengis.net/def/crs/EPSG/0/25832",
109
+ "bboxCrs": "http://www.opengis.net/def/crs/EPSG/0/25832"
109
110
  },
110
111
  {
111
112
  "id": "8712",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@masterportal/masterportalapi",
3
3
  "author": "Implementierungspartnerschaft Masterportal <info@masterportal.org> (https://www.masterportal.org)",
4
- "version": "2.39.0",
4
+ "version": "2.40.1",
5
5
  "license": "MIT",
6
6
  "description": "Basic functions of the Masterportal as api",
7
7
  "repository": {
package/src/layer/oaf.js CHANGED
@@ -3,7 +3,6 @@ import {bbox} from "ol/loadingstrategy.js";
3
3
  import GeoJSON from "ol/format/GeoJSON.js";
4
4
  import {createVectorSource, createClusterVectorSource} from "./vector";
5
5
  import {onError, onLoad} from "../lib/wfsUtil";
6
- import {getParamsUrl} from "../lib/oafUtil";
7
6
  import * as webgl from "../renderer/webgl";
8
7
 
9
8
  /**
@@ -110,20 +109,75 @@ function loadSource (url, source, {onErrorFn, success, failure}, options, collec
110
109
  });
111
110
  }
112
111
 
112
+ /**
113
+ * Creates the url for OAF request.
114
+ * @param {rawLayer} rawLayer layer specification as in services.json
115
+ * @param {object} loadingParams added as params to url
116
+ * @param {number[]} [extent] the current viewport extent
117
+ * @returns {string} the url
118
+ */
119
+ export function createUrl (rawLayer, loadingParams) {
120
+ const bboxParam = loadingParams?.bbox || rawLayer.bbox,
121
+ rawUrl = rawLayer.url;
122
+ let bboxValue = typeof bboxParam === "string" && bboxParam.length ? bboxParam : null,
123
+ url = null;
124
+
125
+ url = new URL(rawUrl);
126
+ if (typeof rawLayer.collection === "string") {
127
+ if (!url.pathname.endsWith("/")) {
128
+ url.pathname += "/collections/" + rawLayer.collection + "/items";
129
+ }
130
+ else {
131
+ url.pathname = "collections/" + rawLayer.collection + "/items";
132
+ }
133
+
134
+ }
135
+ if (typeof rawLayer.limit === "number") {
136
+ url.searchParams.set("limit", rawLayer.limit);
137
+ }
138
+ if (Array.isArray(bboxParam) && bboxParam.length === 4) {
139
+ bboxValue = bboxParam.join(",");
140
+ }
141
+ if (bboxValue) {
142
+ url.searchParams.set("bbox", bboxParam);
143
+ if (typeof rawLayer.bboxCrs === "string" && rawLayer.bboxCrs !== "") {
144
+ url.searchParams.set("bbox-crs", rawLayer.bboxCrs);
145
+ }
146
+ }
147
+ if (typeof rawLayer.crs === "string") {
148
+ url.searchParams.set("crs", rawLayer.crs);
149
+ }
150
+ if (typeof rawLayer.datetime === "string" && rawLayer.datetime !== "") {
151
+ url.searchParams.set("datetime", rawLayer.datetime);
152
+ }
153
+ if (typeof rawLayer.params === "object" && Object.keys(rawLayer.params).length) {
154
+ Object.entries(rawLayer.params).forEach(([key, value]) => {
155
+ url.searchParams.set(key, value);
156
+ });
157
+ }
158
+
159
+ return url;
160
+ }
161
+
113
162
  /**
114
163
  * Creates an ol/source element for the rawLayer by using a loader.
115
164
  * The 'featuresloadend' and 'featuresloaderror' events will be fired by using success and failure callbacks of the loader.
116
165
  * @param {rawLayer} rawLayer layer specification as in services.json
117
166
  * @param {options} [options] additional options
118
- * @param {String} url the parsed url
119
167
  * {@link https://openlayers.org/en/latest/apidoc/module-ol_source_Vector-VectorSource.html failure/success see}
120
168
  * @returns {(ol.source.VectorSource|ol.source.Cluster)} VectorSource or Cluster, depending on whether clusterDistance is set.
121
169
  */
122
- function getLayerSource (rawLayer, options, url) {
170
+ function getLayerSource (rawLayer, options) {
123
171
  const format = new GeoJSON();
124
172
  let source = null;
125
173
 
126
- function loader (extent, resolution, projection, success, failure) {
174
+ function loader (extent, _, __, success, failure) {
175
+ const bboxParam = options.loadingStrategy === bbox ? extent : options.loadingParams.bbox,
176
+ url = createUrl(rawLayer, {
177
+ ...options.loadingParams,
178
+ bbox: bboxParam
179
+ });
180
+
127
181
  loadSource(url, source, {onErrorFn: onError, success, failure}, options);
128
182
  }
129
183
  source = createVectorSource(loader, options.loadingStrategy, format);
@@ -138,36 +192,6 @@ function getLayerSource (rawLayer, options, url) {
138
192
  return source;
139
193
  }
140
194
 
141
- /**
142
- * Creates the url for OAF request.
143
- * @param {rawLayer} rawLayer layer specification as in services.json
144
- * @returns {string} the url
145
- */
146
- function createUrl (rawLayer) {
147
- let url = rawLayer.url,
148
- appendingString;
149
- const crsDefault = "";
150
-
151
- url += typeof rawLayer.collection === "string" ? "/collections/" + rawLayer.collection + "/items?" : "";
152
- url += typeof rawLayer.limit === "number" ? "limit=" + rawLayer.limit + "&" : "";
153
- if (Array.isArray(rawLayer.bbox) && rawLayer.bbox.length === 4) {
154
- appendingString = "";
155
-
156
- rawLayer.bbox.forEach((bboxEntry, i) => {
157
- appendingString += i !== rawLayer.bbox.length - 1 ? bboxEntry + "," : bboxEntry;
158
- });
159
- url += "bbox=" + appendingString + "&";
160
- }
161
- url += typeof rawLayer.bboxCrs === "string" && rawLayer.bboxCrs !== "" ? "bbox-crs=" + encodeURIComponent(rawLayer.bboxCrs) + "&" : "";
162
- if (rawLayer.crs !== false) {
163
- url += "crs=" + encodeURIComponent(typeof rawLayer.crs === "string" && rawLayer.crs !== "" ? rawLayer.crs : crsDefault) + "&";
164
- }
165
- url += typeof rawLayer.datetime === "string" && rawLayer.datetime !== "" ? "datetime=" + rawLayer.datetime + "&" : "";
166
- url += getParamsUrl(rawLayer.params);
167
-
168
- return url;
169
- }
170
-
171
195
  /**
172
196
  * Creates an ol/source element for the rawLayer by OAF (XML or Geojson)
173
197
  * @param {rawLayer} rawLayer layer specification as in services.json
@@ -182,9 +206,7 @@ function createLayerSource (rawLayer, options = {}) {
182
206
  if (!options.loadingStrategy) {
183
207
  options.loadingStrategy = bbox;
184
208
  }
185
-
186
- const url = createUrl(rawLayer),
187
- source = getLayerSource(rawLayer, options, url);
209
+ const source = getLayerSource(rawLayer, options);
188
210
 
189
211
  if (rawLayer.renderer === "webgl") {
190
212
  source.once("featuresloadend", event => {
@@ -261,4 +283,4 @@ function loadFeaturesManually (layerAttributes, layerSource) {
261
283
  });
262
284
  }
263
285
 
264
- export default {createLayer, createLayerSource, loadFeaturesManually};
286
+ export default {createLayer, createLayerSource, createUrl, loadFeaturesManually};
@@ -1,19 +1,22 @@
1
1
  /**
2
2
  * Creates the tileset.
3
+ * @param {Object} mpapiTileset - masterportal API Tileset object
3
4
  * @param {Object} rawLayer attributes of the layer
4
5
  * @param {string} [rawLayer.url] - the URL of the Cesium terrain server
5
6
  * @param {string} [rawLayer.cesiumTerrainProviderOptions] - see https://cesiumjs.org/Cesium/Build/Documentation/CesiumTerrainProvider.html
6
7
  * @returns {Cesium.Cesium3DTileset} the tileset
7
8
  */
8
- function createTileSet (rawLayer) {
9
- const url = rawLayer.url.split("?")[0] + "/tileset.json",
9
+ function createTileSet (mpapiTileset, rawLayer) {
10
+ const baseUrl = rawLayer.url.split("?")[0],
11
+ // when no json file is given by url, use tileset.json as default
12
+ url = baseUrl + (baseUrl.endsWith(".json") ? "" : "/tileset.json"),
10
13
  options = {};
11
14
 
15
+ mpapiTileset.url = url;
12
16
 
13
17
  if (rawLayer.cesium3DTilesetOptions) {
14
18
  Object.assign(options, rawLayer.cesium3DTilesetOptions);
15
19
  }
16
-
17
20
  return Promise.resolve(Cesium.Cesium3DTileset.fromUrl(url, options));
18
21
  }
19
22
 
@@ -33,7 +36,7 @@ export default function Tileset (rawLayer) {
33
36
  typ: rawLayer.typ
34
37
  };
35
38
  if (Cesium) {
36
- this.tileset = Promise.resolve(createTileSet(rawLayer));
39
+ this.tileset = Promise.resolve(createTileSet(this, rawLayer));
37
40
  this.tileset.then(function (tileset) {
38
41
  if (tileset) {
39
42
  tileset.layerReferenceId = rawLayer.id;
package/src/layer/wfs.js CHANGED
@@ -339,11 +339,12 @@ async function sendTransaction (srsName, feature, url, layer, transactionMethod)
339
339
  xmlDocument = null,
340
340
  transactionSummary = null,
341
341
  data = null;
342
+ const baseUrl = new URL(url),
342
343
 
343
- const {featureNS, featurePrefix, featureType, version} = layer;
344
+ {featureNS, featurePrefix, featureType, version} = layer;
344
345
 
345
346
  try {
346
- response = await fetch(url, {
347
+ response = await fetch(baseUrl, {
347
348
  method: "POST",
348
349
  headers: {"Content-Type": "text/xml"},
349
350
  credentials: layer.isSecured ? "include" : "omit",
@@ -358,6 +359,9 @@ async function sendTransaction (srsName, feature, url, layer, transactionMethod)
358
359
 
359
360
  xmlDocument = new DOMParser().parseFromString(data, "text/xml");
360
361
  transactionSummary = xmlDocument.getElementsByTagName("wfs:TransactionSummary");
362
+ if (transactionSummary.length === 0) {
363
+ transactionSummary = xmlDocument.getElementsByTagName("TransactionSummary");
364
+ }
361
365
 
362
366
  // NOTE: WFS-T services respond errors with the transaction as an XML response, even though it's the http code indicates different...
363
367
  if (transactionSummary.length === 0) {
@@ -453,6 +457,27 @@ function parseDescribeFeatureTypeResponse (responseData, featureType) {
453
457
  return [];
454
458
  }
455
459
 
460
+ /**
461
+ * Creates the Url to get possible properties from.
462
+ *
463
+ * @param {string} url from the WFS-T
464
+ * @param {string} version of the WFS-T
465
+ * @param {string} featureType Name of the FeatureType according to the capabilities document
466
+ * @returns {URL} the created url
467
+ */
468
+ function createReceivePossiblePropertiesUrl (url, version, featureType) {
469
+ const baseUrl = new URL(decodeURI(url));
470
+
471
+ baseUrl.searchParams.set("SERVICE", "WFS");
472
+ baseUrl.searchParams.set("REQUEST", "DescribeFeatureType");
473
+ baseUrl.searchParams.set("TYPENAME", featureType);
474
+ if (!baseUrl.searchParams.has("VERSION") && !baseUrl.searchParams.has("version")) {
475
+ baseUrl.searchParams.set("VERSION", version);
476
+ }
477
+
478
+ return baseUrl;
479
+ }
480
+
456
481
  /**
457
482
  * Requests the possible properties of a feature and further values;
458
483
  * for more {@see FeatureProperty}.
@@ -464,8 +489,8 @@ function parseDescribeFeatureTypeResponse (responseData, featureType) {
464
489
  * @returns {Promise<Array>} If the request is successful, an array of prepared feature properties.
465
490
  */
466
491
  async function receivePossibleProperties (url, version, featureType, isSecured) {
467
- const baseUrl = `${url}?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=${version}&TYPENAME=${featureType}`;
468
- let response;
492
+ const baseUrl = createReceivePossiblePropertiesUrl(url, version, featureType);
493
+ let response = null;
469
494
 
470
495
  try {
471
496
  response = await fetch(baseUrl, {
@@ -499,4 +524,4 @@ function loadFeaturesManually (layerAttributes, layerSource) {
499
524
  });
500
525
  }
501
526
 
502
- export default {createLayerSource, createLayer, sendTransaction, receivePossibleProperties, parseDescribeFeatureTypeResponse, writeTransactionBody, loadFeaturesManually};
527
+ export default {createLayerSource, createLayer, createReceivePossiblePropertiesUrl, sendTransaction, receivePossibleProperties, parseDescribeFeatureTypeResponse, writeTransactionBody, loadFeaturesManually};
@@ -164,7 +164,7 @@ export function createMap (config = defaults, {mapParams, callback, errorCallbac
164
164
  ]),
165
165
  controls: [],
166
166
  view: createMapView(config),
167
- keyboardEventTarget: config.mapInteractions?.keyboardEventTarget ? config.mapInteractions?.keyboardEventTarget : false
167
+ keyboardEventTarget: config.mapInteractions?.keyboardEventTarget ? document : false
168
168
  }, mapParams));
169
169
 
170
170
  map.set("mapMode", "2D");
@@ -26,28 +26,25 @@ function initializeLayerList (layerConf = defaults.layerConf, callback) {
26
26
  }
27
27
 
28
28
  // case: parameter is URL
29
- const Http = new XMLHttpRequest();
30
-
31
- Http.open("GET", layerConf);
32
- Http.timeout = 10000;
33
- Http.send();
34
- Http.onload = function () {
35
- try {
36
- layerList = JSON.parse(Http.responseText);
37
- }
38
- catch (error) {
39
- console.error("An error occured when parsing the response after loading '" + layerConf + "':", error);
40
- return callback(false, error);
41
- }
42
- if (typeof callback === "function") {
43
- return callback(layerList);
44
- }
45
- return true;
46
- };
47
- Http.onerror = function (e) {
48
- console.error("An error occured when trying to fetch services from '" + layerConf + "':", e);
49
- callback(false, e);
50
- };
29
+ fetch(layerConf, {method: "GET", timeout: 10000})
30
+ .then((response) => {
31
+ response.json()
32
+ .then((json) => {
33
+ layerList = json;
34
+ if (typeof callback === "function") {
35
+ return callback(layerList);
36
+ }
37
+ return true;
38
+ })
39
+ .catch((error) => {
40
+ console.error("An error occured when parsing the response after loading '" + layerConf + "':", error);
41
+ return callback(false, error);
42
+ });
43
+ })
44
+ .catch((error) => {
45
+ console.error("An error occured when trying to fetch services from '" + layerConf + "':", error);
46
+ callback(false, error);
47
+ });
51
48
  }
52
49
 
53
50
  /**
@@ -14,6 +14,7 @@ let styleList,
14
14
  configuredTools,
15
15
  mapMarkerPointStyleId,
16
16
  mapMarkerPolygonStyleId,
17
+ additionalPolygonStyleId,
17
18
  highlightFeaturesPointStyleId,
18
19
  highlightFeaturesPolygonStyleId,
19
20
  highlightFeaturesLineStyleId,
@@ -140,6 +141,23 @@ function getStyleIdForMapMarkerPolygon () {
140
141
  return styleId;
141
142
  }
142
143
 
144
+ /**
145
+ * Gets the style id for an additional MapMarker.
146
+ * If the additionalPolygonStyleId exists, return it; otherwise, returns the default styleId.
147
+ * @returns {String} - The styleId of the additional MapMarker
148
+ */
149
+ function getStyleIdForAdditionalMapMarkerPolygon () {
150
+ let styleId;
151
+
152
+ if (additionalPolygonStyleId) {
153
+ styleId = additionalPolygonStyleId;
154
+ }
155
+ else {
156
+ styleId = "defaultAdditionalMapMarkerPolygon";
157
+ }
158
+ return styleId;
159
+ }
160
+
143
161
  /**
144
162
  * gets style id from HighlightFeatures
145
163
  * @returns {String} - Style id of highlightFeatures.
@@ -186,6 +204,7 @@ function parseStyles (data) {
186
204
  dataWithDefaultValue.push({styleId: "default", rules: [{style: {}}]},
187
205
  defaultStyle.defaultMapMarkerPoint,
188
206
  defaultStyle.defaultMapMarkerPolygon,
207
+ defaultStyle.defaultAdditionalMapMarkerPolygon,
189
208
  defaultStyle.defaultHighlightFeaturesPoint,
190
209
  defaultStyle.defaultHighlightFeaturesPolygon,
191
210
  defaultStyle.defaultHighlightFeaturesLine);
@@ -193,6 +212,7 @@ function parseStyles (data) {
193
212
  styleIds.push(getStyleIdsFromLayers(),
194
213
  getStyleIdForMapMarkerPoint(),
195
214
  getStyleIdForMapMarkerPolygon(),
215
+ getStyleIdForAdditionalMapMarkerPolygon(),
196
216
  getStyleIdForHighlightFeaturesPoint(),
197
217
  getStyleIdForHighlightFeaturesPolygon(),
198
218
  getStyleIdForHighlightFeaturesLine(),
@@ -222,6 +242,7 @@ async function initializeStyleList (styleGetters, Config, layers, tools, callbac
222
242
 
223
243
  mapMarkerPointStyleId = styleGetters.mapMarkerPointStyleId;
224
244
  mapMarkerPolygonStyleId = styleGetters.mapMarkerPolygonStyleId;
245
+ additionalPolygonStyleId = styleGetters.additionalPolygonStyleId;
225
246
  highlightFeaturesPointStyleId = styleGetters.highlightFeaturesPointStyleId;
226
247
  highlightFeaturesPolygonStyleId = styleGetters.highlightFeaturesPolygonStyleId;
227
248
  highlightFeaturesLineStyleId = styleGetters.highlightFeaturesLineStyleId;
@@ -137,6 +137,17 @@ const defaultColors = {
137
137
  }
138
138
  }]
139
139
  },
140
+ defaultAdditionalMapMarkerPolygon: {
141
+ styleId: "defaultAdditionalMapMarkerPolygon",
142
+ rules: [{
143
+ style: {
144
+ polygonStrokeColor: [255, 255, 0, 1],
145
+ polygonStrokeWidth: 4,
146
+ polygonFillColor: [255, 255, 0, 0.3],
147
+ polygonStrokeDash: [8]
148
+ }
149
+ }]
150
+ },
140
151
  defaultHighlightFeaturesPoint: {
141
152
  styleId: "defaultHighlightFeaturesPoint",
142
153
  rules: [{
@@ -38,7 +38,7 @@ describe("oaf.js", function () {
38
38
  const attr = {
39
39
  "id": "id",
40
40
  "name": "Schulen",
41
- "url": "https://url.de",
41
+ "url": "https://url",
42
42
  "collection": "staatliche_schulen",
43
43
  "typ": "OAF",
44
44
  "bbox": "",
@@ -137,7 +137,7 @@ describe("oaf.js", function () {
137
137
  console.error = consoleError;
138
138
  });
139
139
  it("creates a GeoJSON VectorSource", function () {
140
- global.fetch = jest.fn().mockImplementationOnce(() => {
140
+ global.fetch = jest.fn().mockImplementation(() => {
141
141
  return new Promise((resolve) => {
142
142
  resolve({
143
143
  ok: true,
@@ -153,7 +153,7 @@ describe("oaf.js", function () {
153
153
  const rawLayer = {
154
154
  id: "id",
155
155
  name: "Schulen",
156
- url: "https://url.de",
156
+ url: "https://url",
157
157
  collection: "staatliche_schulen",
158
158
  typ: "OAF",
159
159
  limit: 10,
@@ -167,7 +167,7 @@ describe("oaf.js", function () {
167
167
  expect(layer.getSource().getFormat()).toBeInstanceOf(GeoJSON);
168
168
  });
169
169
  it("creates a VectorSource and onLoadingError is called", function () {
170
- global.fetch = jest.fn().mockImplementationOnce(() => {
170
+ global.fetch = jest.fn().mockImplementation(() => {
171
171
  return new Promise((resolve) => {
172
172
  resolve({
173
173
  ok: false,
@@ -184,7 +184,7 @@ describe("oaf.js", function () {
184
184
  const rawLayer = {
185
185
  id: "id",
186
186
  name: "Schulen",
187
- url: "https://url.de",
187
+ url: "https://url",
188
188
  collection: "staatliche_schulen",
189
189
  typ: "OAF",
190
190
  limit: 10,
@@ -206,7 +206,7 @@ describe("oaf.js", function () {
206
206
  });
207
207
  });
208
208
  it("creates a clustered VectorSource and beforeLoading, afterLoading and featuresFilter are called", function () {
209
- global.fetch = jest.fn().mockImplementationOnce(() => {
209
+ global.fetch = jest.fn().mockImplementation(() => {
210
210
  return new Promise((resolve) => {
211
211
  resolve({
212
212
  ok: true,
@@ -223,7 +223,7 @@ describe("oaf.js", function () {
223
223
  rawLayer = {
224
224
  id: "id",
225
225
  name: "Schulen",
226
- url: "https://url.de",
226
+ url: "https://url",
227
227
  collection: "staatliche_schulen",
228
228
  typ: "OAF",
229
229
  limit: 10,
@@ -259,7 +259,7 @@ describe("oaf.js", function () {
259
259
  });
260
260
  it("creates a vectorSource with an additional listener, when renderer is \"webgl\"", () => {
261
261
  const
262
- url = "https://url.de",
262
+ url = "https://url",
263
263
  rawLayer = {
264
264
  id: "id",
265
265
  url: url,
@@ -290,7 +290,7 @@ describe("oaf.js", function () {
290
290
  describe("loadFeaturesManually", function () {
291
291
  it("loadFeaturesManually shall call fetch", function () {
292
292
  console.error = jest.fn();
293
- global.fetch = jest.fn().mockImplementationOnce(() => {
293
+ global.fetch = jest.fn().mockImplementation(() => {
294
294
  return new Promise((resolve) => {
295
295
  resolve({
296
296
  ok: true,
@@ -304,7 +304,7 @@ describe("oaf.js", function () {
304
304
 
305
305
  const rawLayer = {
306
306
  id: "id",
307
- url: "url",
307
+ url: "https://url",
308
308
  featureNS: "http://www.deegree.org/app",
309
309
  featureType: "krankenhaeuser_hh",
310
310
  version: "1.0.0"
@@ -317,4 +317,84 @@ describe("oaf.js", function () {
317
317
  expect(global.fetch.mock.calls.length).toBe(1);
318
318
  });
319
319
  });
320
+ describe("createUrl", () => {
321
+ it("should append bbox, collection, limit, datetime, bboxCrs, and crs, as provided in rawLayer", () => {
322
+ const rawLayer = {
323
+ id: "id",
324
+ name: "Schulen",
325
+ url: "https://url.de",
326
+ collection: "staatliche_schulen",
327
+ typ: "OAF",
328
+ limit: 10,
329
+ bbox: [0, 0, 10, 10],
330
+ bboxCrs: "EPSG:4326",
331
+ datetime: "123",
332
+ crs: "EPSG:25832"
333
+ },
334
+ loadingParams = undefined,
335
+ createdUrl = oaf.createUrl(rawLayer, loadingParams);
336
+
337
+ expect(createdUrl.origin).toEqual(rawLayer.url);
338
+ expect(createdUrl.pathname).toEqual("/collections/" + rawLayer.collection + "/items");
339
+ expect(createdUrl.searchParams.get("limit")).toEqual("10");
340
+ expect(createdUrl.searchParams.get("bbox")).toEqual("0,0,10,10");
341
+ expect(createdUrl.searchParams.get("bbox-crs")).toEqual(rawLayer.bboxCrs);
342
+ expect(createdUrl.searchParams.get("crs")).toEqual(rawLayer.crs);
343
+ expect(createdUrl.searchParams.get("datetime")).toEqual(rawLayer.datetime);
344
+ });
345
+ it("should append the bbox, if provided as string in rawLayer", () => {
346
+ const rawLayer = {
347
+ id: "id",
348
+ name: "Schulen",
349
+ url: "https://url.de",
350
+ collection: "staatliche_schulen",
351
+ typ: "OAF",
352
+ bbox: "0,0,10,10",
353
+ bboxCrs: "EPSG:4326"
354
+ },
355
+ loadingParams = undefined,
356
+ createdUrl = oaf.createUrl(rawLayer, loadingParams);
357
+
358
+ expect(createdUrl.origin).toEqual(rawLayer.url);
359
+ expect(createdUrl.pathname).toEqual("/collections/" + rawLayer.collection + "/items");
360
+ expect(createdUrl.searchParams.get("bbox")).toEqual("0,0,10,10");
361
+ expect(createdUrl.searchParams.get("bbox-crs")).toEqual(rawLayer.bboxCrs);
362
+ });
363
+ it("should append the bbox, if provided as string in loadingParams", () => {
364
+ const rawLayer = {
365
+ id: "id",
366
+ name: "Schulen",
367
+ url: "https://mapservice.regensburg.de/cgi-bin/mapserv?map=wfs.map",
368
+ collection: "staatliche_schulen",
369
+ typ: "OAF"
370
+ },
371
+ loadingParams = {bbox: "0,0,10,10"},
372
+ createdUrl = oaf.createUrl(rawLayer, loadingParams);
373
+
374
+ expect(createdUrl.origin).toEqual("https://mapservice.regensburg.de");
375
+ expect(createdUrl.pathname).toEqual("/cgi-bin/mapserv/collections/" + rawLayer.collection + "/items");
376
+ expect(createdUrl.searchParams.get("map")).toEqual("wfs.map");
377
+ expect(createdUrl.searchParams.get("bbox")).toEqual("0,0,10,10");
378
+ });
379
+ it("should append additional key:value filters, if provided as in rawLayer.params", () => {
380
+ const rawLayer = {
381
+ id: "id",
382
+ name: "Schulen",
383
+ url: "https://url/",
384
+ collection: "staatliche_schulen",
385
+ typ: "OAF",
386
+ params: {
387
+ kapitelbezeichnung: "Gymnasien",
388
+ anzahl_schueler: ">1000"
389
+ }
390
+ },
391
+ loadingParams = undefined,
392
+ createdUrl = oaf.createUrl(rawLayer, loadingParams);
393
+
394
+ expect(createdUrl.origin).toEqual("https://url");
395
+ expect(createdUrl.pathname).toEqual("/collections/" + rawLayer.collection + "/items");
396
+ expect(createdUrl.searchParams.get("kapitelbezeichnung")).toEqual("Gymnasien");
397
+ expect(createdUrl.searchParams.get("anzahl_schueler")).toEqual(">1000");
398
+ });
399
+ });
320
400
  });
@@ -73,6 +73,17 @@ describe("tileset.js", function () {
73
73
  checkAttributes(layer2, attr2);
74
74
  expect(cesium3DTilesetSpy).toHaveBeenCalledTimes(2);
75
75
  });
76
+ it("add tileset.json to url, when url is not pointing to json file", function () {
77
+ const layer = new Tileset(attr);
78
+
79
+ expect(layer.url).toEqual(attr.url + "/tileset.json");
80
+ });
81
+ it("should not add tileset.json to url, when url is pointing to json file", function () {
82
+ const attr2 = Object.assign({}, attr, {url: "https://url/root.json"}),
83
+ layer = new Tileset(attr2);
84
+
85
+ expect(layer.url).toEqual(attr2.url);
86
+ });
76
87
  });
77
88
  describe("setOpacity", function () {
78
89
  it("calls setOpacity sets opacity to terrain style", function (done) {
@@ -1,4 +1,3 @@
1
- import {enableFetchMocks} from "jest-fetch-mock";
2
1
  import VectorLayer from "ol/layer/Vector.js";
3
2
  import VectorSource from "ol/source/Vector.js";
4
3
  import Cluster from "ol/source/Cluster.js";
@@ -43,11 +42,6 @@ describe("wfs.js", function () {
43
42
  console.error = originalConsoleError;
44
43
  });
45
44
 
46
- beforeEach(() => {
47
- enableFetchMocks();
48
- fetch.resetMocks();
49
- });
50
-
51
45
  describe("createLayer", function () {
52
46
  it("creates a VectorLayer without id", function () {
53
47
  const layer = wfs.createLayer({version: "1.1.0"});
@@ -145,14 +139,9 @@ describe("wfs.js", function () {
145
139
  });
146
140
  });
147
141
  describe("createLayerSource", function () {
148
- beforeEach(() => {
149
- if (global.fetch) {
150
- global.fetch.mockClear();
151
- }
152
- });
153
142
 
154
143
  it("creates a VectorSource and beforeLoading, afterLoading and featuresFilter are called", function () {
155
- global.fetch = jest.fn().mockImplementationOnce(() => {
144
+ global.fetch = jest.fn().mockImplementation(() => {
156
145
  return new Promise((resolve) => {
157
146
  resolve({
158
147
  ok: true,
@@ -202,7 +191,7 @@ describe("wfs.js", function () {
202
191
  });
203
192
  });
204
193
  it("creates a VectorSource with doNotLoadInitially", function () {
205
- global.fetch = jest.fn().mockImplementationOnce(() => {
194
+ global.fetch = jest.fn().mockImplementation(() => {
206
195
  return new Promise((resolve) => {
207
196
  resolve({
208
197
  ok: true,
@@ -255,7 +244,7 @@ describe("wfs.js", function () {
255
244
  it("creates a VectorSource with wfsFilter", function () {
256
245
  let secondFetchCalled = false;
257
246
 
258
- global.fetch = jest.fn().mockImplementationOnce(() => {
247
+ global.fetch = jest.fn().mockImplementation(() => {
259
248
  return new Promise((resolve) => {
260
249
  resolve({
261
250
  ok: true,
@@ -265,7 +254,7 @@ describe("wfs.js", function () {
265
254
  }
266
255
  });
267
256
  });
268
- }).mockImplementationOnce(() => {
257
+ }).mockImplementation(() => {
269
258
  return new Promise((resolve) => {
270
259
  resolve({
271
260
  ok: true,
@@ -317,7 +306,7 @@ describe("wfs.js", function () {
317
306
  });
318
307
  });
319
308
  it("creates a VectorSource and onLoadingError is called", function () {
320
- global.fetch = jest.fn().mockImplementationOnce(() => {
309
+ global.fetch = jest.fn().mockImplementation(() => {
321
310
  // NOTE: fetch only rejects if a network error occurs, which do not apply to 4xx or 5xx http codes.
322
311
  return new Promise((resolve) => {
323
312
  resolve({
@@ -360,7 +349,7 @@ describe("wfs.js", function () {
360
349
  });
361
350
  });
362
351
  it("creates a clustered VectorSource and beforeLoading, afterLoading and featuresFilter are called", function () {
363
- global.fetch = jest.fn().mockImplementationOnce(() => {
352
+ global.fetch = jest.fn().mockImplementation(() => {
364
353
  return new Promise((resolve) => {
365
354
  resolve({
366
355
  ok: true,
@@ -442,7 +431,7 @@ describe("wfs.js", function () {
442
431
  expect(webgl.afterLoading).toHaveBeenCalledWith(features, layerParams.styleId, layerParams.excludeTypesFromParsing, layerParams.isPointLayer);
443
432
  });
444
433
  it("creates a vectorSource with credentials: include as params", () => {
445
- global.fetch = jest.fn().mockImplementationOnce(() => {
434
+ global.fetch = jest.fn().mockImplementation(() => {
446
435
  // NOTE: fetch only rejects if a network error occurs, which do not apply to 4xx or 5xx http codes.
447
436
  return new Promise((resolve) => {
448
437
  resolve({
@@ -758,9 +747,9 @@ describe("wfs.js", function () {
758
747
  "</xsd:schema>";
759
748
 
760
749
  it("should receive the possible properties", async () => {
761
- fetch.mockResponseOnce(exampleDescribeFeatureType);
762
-
763
- const properties = await wfs.receivePossibleProperties("https://team-waas-was-here.lgln", "1.1.0", "wfstpolygon", false),
750
+ let properties = null;
751
+ const baseUrl = new URL("https://team-waas-was-here.lgln/?SERVICE=WFS&REQUEST=DescribeFeatureType&TYPENAME=wfstpolygon&VERSION=1.1.0"),
752
+ options = {"credentials": "omit", "responseType": "text/xml"},
764
753
  exampleProperties = [
765
754
  {
766
755
  key: "name",
@@ -799,6 +788,22 @@ describe("wfs.js", function () {
799
788
  }
800
789
  ];
801
790
 
791
+ baseUrl.searchParams.set("SERVICE", "WFS");
792
+ baseUrl.searchParams.set("REQUEST", "DescribeFeatureType");
793
+ global.fetch = jest.fn().mockImplementation(() => {
794
+ return new Promise((resolve) => {
795
+ resolve({
796
+ ok: true,
797
+ status: 200,
798
+ text: () => {
799
+ return exampleDescribeFeatureType;
800
+ }
801
+ });
802
+ });
803
+ });
804
+
805
+ properties = await wfs.receivePossibleProperties("https://team-waas-was-here.lgln", "1.1.0", "wfstpolygon", false);
806
+
802
807
  expect(Array.isArray(properties)).toBe(true);
803
808
  expect(properties.length).toEqual(5);
804
809
  exampleProperties.forEach(property => {
@@ -807,14 +812,14 @@ describe("wfs.js", function () {
807
812
  expect(parsedProperty).not.toEqual(undefined);
808
813
  expect(parsedProperty).toEqual(property);
809
814
  });
810
- expect(fetch).toHaveBeenCalledWith("https://team-waas-was-here.lgln?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.1.0&TYPENAME=wfstpolygon", {"responseType": "text/xml", "credentials": "omit"});
811
815
 
816
+ expect(global.fetch).toHaveBeenCalledWith(baseUrl, options);
812
817
  });
813
818
 
814
819
  it("should receive the possible properties from a geoserver", async () => {
815
- fetch.mockResponseOnce(geoserverDescribeFeatureType);
816
-
817
- const properties = await wfs.receivePossibleProperties("https://team-waas-was-here.lgln", "1.1.0", "test_polygon", false),
820
+ let properties = null;
821
+ const baseUrl = new URL("https://team-waas-was-here.lgln/?SERVICE=WFS&REQUEST=DescribeFeatureType&TYPENAME=test_polygon&VERSION=1.1.0"),
822
+ options = {"credentials": "omit", "responseType": "text/xml"},
818
823
  exampleProperties = [
819
824
  {
820
825
  key: "id",
@@ -839,6 +844,22 @@ describe("wfs.js", function () {
839
844
  }
840
845
  ];
841
846
 
847
+ baseUrl.searchParams.set("SERVICE", "WFS");
848
+ baseUrl.searchParams.set("REQUEST", "DescribeFeatureType");
849
+ global.fetch = jest.fn().mockImplementation(() => {
850
+ return new Promise((resolve) => {
851
+ resolve({
852
+ ok: true,
853
+ status: 200,
854
+ text: () => {
855
+ return geoserverDescribeFeatureType;
856
+ }
857
+ });
858
+ });
859
+ });
860
+ properties = await wfs.receivePossibleProperties("https://team-waas-was-here.lgln", "1.1.0", "test_polygon", false);
861
+
862
+
842
863
  expect(Array.isArray(properties)).toBe(true);
843
864
  expect(properties.length).toEqual(3);
844
865
  exampleProperties.forEach(property => {
@@ -847,14 +868,14 @@ describe("wfs.js", function () {
847
868
  expect(parsedProperty).not.toEqual(undefined);
848
869
  expect(parsedProperty).toEqual(property);
849
870
  });
850
- expect(fetch).toHaveBeenCalledWith("https://team-waas-was-here.lgln?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.1.0&TYPENAME=test_polygon", {"responseType": "text/xml", "credentials": "omit"});
871
+ expect(global.fetch).toHaveBeenCalledWith(baseUrl, options);
851
872
 
852
873
  });
853
874
 
854
875
  it("should receive the possible properties with credentials", async () => {
855
- fetch.mockResponseOnce(exampleDescribeFeatureType);
856
-
857
- const properties = await wfs.receivePossibleProperties("https://team-waas-was-here.lgln", "1.1.0", "wfstpolygon", true),
876
+ let properties = null;
877
+ const baseUrl = new URL("https://team-waas-was-here.lgln/?SERVICE=WFS&REQUEST=DescribeFeatureType&TYPENAME=wfstpolygon&VERSION=1.1.0"),
878
+ options = {"credentials": "include", "responseType": "text/xml"},
858
879
  exampleProperties = [
859
880
  {
860
881
  key: "name",
@@ -893,6 +914,21 @@ describe("wfs.js", function () {
893
914
  }
894
915
  ];
895
916
 
917
+ baseUrl.searchParams.set("SERVICE", "WFS");
918
+ baseUrl.searchParams.set("REQUEST", "DescribeFeatureType");
919
+ global.fetch = jest.fn().mockImplementation(() => {
920
+ return new Promise((resolve) => {
921
+ resolve({
922
+ ok: true,
923
+ status: 200,
924
+ text: () => {
925
+ return exampleDescribeFeatureType;
926
+ }
927
+ });
928
+ });
929
+ });
930
+
931
+ properties = await wfs.receivePossibleProperties("https://team-waas-was-here.lgln", "1.1.0", "wfstpolygon", true);
896
932
  expect(Array.isArray(properties)).toBe(true);
897
933
  expect(properties.length).toEqual(5);
898
934
  exampleProperties.forEach(property => {
@@ -901,17 +937,9 @@ describe("wfs.js", function () {
901
937
  expect(parsedProperty).not.toEqual(undefined);
902
938
  expect(parsedProperty).toEqual(property);
903
939
  });
904
- expect(fetch).toHaveBeenCalledWith("https://team-waas-was-here.lgln?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.1.0&TYPENAME=wfstpolygon", {"responseType": "text/xml", "credentials": "include"});
940
+ expect(global.fetch).toHaveBeenCalledWith(baseUrl, options);
905
941
 
906
942
  });
907
-
908
- it("should throw an error if the properties can not be fetched", async () => {
909
- fetch.mockAbortOnce();
910
-
911
- await expect(async () => {
912
- await wfs.receivePossibleProperties("https://team-waas-was-here.lgln", "1.1.0", "wfstgeom", false);
913
- }).rejects.toThrow(Error);
914
- });
915
943
  });
916
944
 
917
945
  describe("sendTransaction", () => {
@@ -968,14 +996,6 @@ describe("wfs.js", function () {
968
996
  " </wfs:Feature>\n" +
969
997
  " </wfs:InsertResults>\n" +
970
998
  "</wfs:TransactionResponse>",
971
- fetchResponseUpdate = "<?xml version='1.0' encoding='UTF-8'?>\n" +
972
- "<wfs:TransactionResponse xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd\" xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:ogc=\"http://www.opengis.net/ogc\" version=\"1.1.0\">\n" +
973
- " <wfs:TransactionSummary>\n" +
974
- " <wfs:totalInserted>0</wfs:totalInserted>\n" +
975
- " <wfs:totalUpdated>1</wfs:totalUpdated>\n" +
976
- " <wfs:totalDeleted>0</wfs:totalDeleted>\n" +
977
- " </wfs:TransactionSummary>\n" +
978
- "</wfs:TransactionResponse>",
979
999
  fetchResponseDelete = "<?xml version='1.0' encoding='UTF-8'?>\n" +
980
1000
  "<wfs:TransactionResponse xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd\" xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:ogc=\"http://www.opengis.net/ogc\" version=\"1.1.0\">\n" +
981
1001
  " <wfs:TransactionSummary>\n" +
@@ -986,40 +1006,84 @@ describe("wfs.js", function () {
986
1006
  "</wfs:TransactionResponse>";
987
1007
 
988
1008
  it("should return the inserted feature if the transaction was successful", async function () {
989
- fetch.mockResponseOnce(fetchResponseInsert);
1009
+ global.fetch = jest.fn().mockImplementation(() => {
1010
+ return new Promise((resolve) => {
1011
+ resolve({
1012
+ ok: true,
1013
+ status: 200,
1014
+ text: () => {
1015
+ return fetchResponseInsert;
1016
+ }
1017
+ });
1018
+ });
1019
+ });
990
1020
 
991
1021
  expect(await wfs.sendTransaction(srsName, feature, url, layer, insertTransaction)).toEqual(feature);
992
1022
  });
993
1023
 
994
1024
  it("should return the inserted feature if the transaction was successful", async function () {
995
- fetch.mockResponseOnce(fetchResponseInsert);
1025
+ global.fetch = jest.fn().mockImplementation(() => {
1026
+ return new Promise((resolve) => {
1027
+ resolve({
1028
+ ok: true,
1029
+ status: 200,
1030
+ text: () => {
1031
+ return fetchResponseInsert;
1032
+ }
1033
+ });
1034
+ });
1035
+ });
996
1036
  layer.isSecured = true;
997
1037
 
998
1038
  expect(await wfs.sendTransaction(srsName, feature, url, layer, insertTransaction)).toEqual(feature);
999
1039
  });
1000
1040
 
1001
1041
  it("should return the updated feature if the transaction was successful", async function () {
1002
- fetch.mockResponseOnce(fetchResponseUpdate);
1042
+ global.fetch = jest.fn().mockImplementation(() => {
1043
+ return new Promise((resolve) => {
1044
+ resolve({
1045
+ ok: true,
1046
+ status: 200,
1047
+ text: () => {
1048
+ return fetchResponseInsert;
1049
+ }
1050
+ });
1051
+ });
1052
+ });
1003
1053
  feature.setId(1);
1004
1054
 
1005
1055
  expect(await wfs.sendTransaction(srsName, feature, url, layer, updateTransaction)).toEqual(feature);
1006
1056
  });
1007
1057
 
1008
1058
  it("should return the deleted feature if the transaction was successful", async function () {
1009
- fetch.mockResponseOnce(fetchResponseDelete);
1059
+ global.fetch = jest.fn().mockImplementation(() => {
1060
+ return new Promise((resolve) => {
1061
+ resolve({
1062
+ ok: true,
1063
+ status: 200,
1064
+ text: () => {
1065
+ return fetchResponseDelete;
1066
+ }
1067
+ });
1068
+ });
1069
+ });
1010
1070
  feature.setId(1);
1011
1071
 
1012
1072
  expect(await wfs.sendTransaction(srsName, feature, url, layer, deleteTransaction)).toEqual(feature);
1013
1073
  });
1014
1074
 
1015
- it("should throw an error if fetch fails", async function () {
1016
- fetch.mockAbortOnce();
1017
-
1018
- await expect(async () => wfs.sendTransaction(srsName, feature, url, layer, insertTransaction)).rejects.toThrow(Error);
1019
- });
1020
-
1021
1075
  it("should throw an error if transaction type is not insert, selectedUpdate or delete", async function () {
1022
- fetch.mockResponseOnce(fetchResponseDelete);
1076
+ global.fetch = jest.fn().mockImplementation(() => {
1077
+ return new Promise((resolve) => {
1078
+ resolve({
1079
+ ok: true,
1080
+ status: 200,
1081
+ text: () => {
1082
+ return fetchResponseDelete;
1083
+ }
1084
+ });
1085
+ });
1086
+ });
1023
1087
  feature.setId(1);
1024
1088
 
1025
1089
  await expect(async () => wfs.sendTransaction(srsName, feature, url, layer, "löschen")).rejects.toThrow(Error);
@@ -1033,7 +1097,17 @@ describe("wfs.js", function () {
1033
1097
  " </ows:Exception>\n" +
1034
1098
  "</ows:ExceptionReport>";
1035
1099
 
1036
- fetch.mockResponseOnce(failedResponse);
1100
+ global.fetch = jest.fn().mockImplementation(() => {
1101
+ return new Promise((resolve) => {
1102
+ resolve({
1103
+ ok: true,
1104
+ status: 200,
1105
+ text: () => {
1106
+ return failedResponse;
1107
+ }
1108
+ });
1109
+ });
1110
+ });
1037
1111
 
1038
1112
  await expect(async () => wfs.sendTransaction(srsName, feature, url, layer, insertTransaction)).rejects.toThrow(Error);
1039
1113
  });
@@ -1046,12 +1120,79 @@ describe("wfs.js", function () {
1046
1120
  " </ows:Exception>\n" +
1047
1121
  "</ows:ExceptionReport>";
1048
1122
 
1049
- fetch.mockResponseOnce(failedResponse);
1123
+ global.fetch = jest.fn().mockImplementation(() => {
1124
+ return new Promise((resolve) => {
1125
+ resolve({
1126
+ ok: true,
1127
+ status: 200,
1128
+ text: () => {
1129
+ return failedResponse;
1130
+ }
1131
+ });
1132
+ });
1133
+ });
1050
1134
 
1051
1135
  await expect(async () => wfs.sendTransaction(srsName, feature, url, layer, insertTransaction)).rejects.toThrow("Cannot perform insert operation: Error in XML document (line: 1, column: 234, character offset: 233): Feature type \"{wrong}wfst\" is unknown.");
1052
1136
  });
1053
1137
  });
1138
+ describe("createReceivePossiblePropertiesUrl", function () {
1139
+ it("url without backslash at the end", () => {
1140
+ const url = "https://team-waas-was-here.lgln",
1141
+ version = "1.1.0",
1142
+ featureType = "featureType",
1143
+ createdUrl = wfs.createReceivePossiblePropertiesUrl(url, version, featureType);
1144
+
1145
+ expect(createdUrl.origin).toEqual(url);
1146
+ expect(createdUrl.searchParams.get("SERVICE")).toEqual("WFS");
1147
+ expect(createdUrl.searchParams.get("REQUEST")).toEqual("DescribeFeatureType");
1148
+ expect(createdUrl.searchParams.get("TYPENAME")).toEqual(featureType);
1149
+ expect(createdUrl.searchParams.get("VERSION")).toEqual(version);
1150
+ });
1151
+
1152
+ it("url with backslash at the end", () => {
1153
+ const url = "https://team-waas-was-here.lgln/",
1154
+ version = "1.1.0",
1155
+ featureType = "featureType",
1156
+ createdUrl = wfs.createReceivePossiblePropertiesUrl(url, version, featureType);
1157
+
1158
+ expect(createdUrl.origin).toEqual("https://team-waas-was-here.lgln");
1159
+ expect(createdUrl.searchParams.get("SERVICE")).toEqual("WFS");
1160
+ expect(createdUrl.searchParams.get("REQUEST")).toEqual("DescribeFeatureType");
1161
+ expect(createdUrl.searchParams.get("TYPENAME")).toEqual(featureType);
1162
+ expect(createdUrl.searchParams.get("VERSION")).toEqual(version);
1163
+ });
1164
+
1165
+ it("createUrl should respect questionmark in url", () => {
1166
+ const url = "https://mapservice.regensburg.de/cgi-bin/mapserv?map=wfs.map",
1167
+ version = "1.1.0",
1168
+ featureType = "featureType",
1169
+ createdUrl = wfs.createReceivePossiblePropertiesUrl(url, version, featureType);
1170
+
1171
+ expect(createdUrl.origin).toEqual("https://mapservice.regensburg.de");
1172
+ expect(createdUrl.pathname).toEqual("/cgi-bin/mapserv");
1173
+ expect(createdUrl.searchParams.get("map")).toEqual("wfs.map");
1174
+ expect(createdUrl.searchParams.get("SERVICE")).toEqual("WFS");
1175
+ expect(createdUrl.searchParams.get("REQUEST")).toEqual("DescribeFeatureType");
1176
+ expect(createdUrl.searchParams.get("TYPENAME")).toEqual(featureType);
1177
+ expect(createdUrl.searchParams.get("VERSION")).toEqual(version);
1178
+ });
1179
+
1180
+ it("createUrl should respect version in url", () => {
1181
+ const url = "https://www.geosnap.info/cgi-bin/qgis_mapserv.fcgi?VERSION=1.3.0&MAP=/var/www/data/gis_data/LRARW_Burgergis/buergergis.qgz",
1182
+ version = "1.1.0",
1183
+ featureType = "featureType",
1184
+ createdUrl = wfs.createReceivePossiblePropertiesUrl(url, version, featureType);
1185
+
1186
+ expect(createdUrl.origin).toEqual("https://www.geosnap.info");
1187
+ expect(createdUrl.pathname).toEqual("/cgi-bin/qgis_mapserv.fcgi");
1188
+ expect(createdUrl.searchParams.get("MAP")).toEqual("/var/www/data/gis_data/LRARW_Burgergis/buergergis.qgz");
1189
+ expect(createdUrl.searchParams.get("SERVICE")).toEqual("WFS");
1190
+ expect(createdUrl.searchParams.get("REQUEST")).toEqual("DescribeFeatureType");
1191
+ expect(createdUrl.searchParams.get("TYPENAME")).toEqual(featureType);
1192
+ expect(createdUrl.searchParams.get("VERSION")).toEqual("1.3.0");
1193
+ });
1054
1194
 
1195
+ });
1055
1196
  describe("loadFeaturesManually", function () {
1056
1197
  let tick;
1057
1198
 
@@ -1061,14 +1202,10 @@ describe("wfs.js", function () {
1061
1202
  setTimeout(resolve, 0);
1062
1203
  });
1063
1204
  };
1064
-
1065
- if (global.fetch) {
1066
- global.fetch.mockClear();
1067
- }
1068
1205
  });
1069
1206
 
1070
1207
  it("load features manually", async function () {
1071
- global.fetch = jest.fn().mockImplementationOnce(() => {
1208
+ global.fetch = jest.fn().mockImplementation(() => {
1072
1209
  return new Promise((resolve) => {
1073
1210
  resolve({
1074
1211
  ok: true,
@@ -1079,8 +1216,33 @@ describe("wfs.js", function () {
1079
1216
  });
1080
1217
  });
1081
1218
  });
1082
-
1083
- const format = new WFS(),
1219
+ const feature = new Feature({
1220
+ geometry: new Polygon([
1221
+ [
1222
+ [
1223
+ 9.17782024967994,
1224
+ 50.20836600730087
1225
+ ],
1226
+ [
1227
+ 9.200676227149245,
1228
+ 50.20836600730087
1229
+ ],
1230
+ [
1231
+ 9.200676227149245,
1232
+ 50.20873353776312
1233
+ ],
1234
+ [
1235
+ 9.17782024967994,
1236
+ 50.20873353776312
1237
+ ],
1238
+ [
1239
+ 9.17782024967994,
1240
+ 50.20836600730087
1241
+ ]
1242
+ ]]),
1243
+ name: "My Polygon"
1244
+ }),
1245
+ format = new WFS(),
1084
1246
  source = new VectorSource({
1085
1247
  format: format,
1086
1248
  url: "https://url.de",
@@ -1094,6 +1256,10 @@ describe("wfs.js", function () {
1094
1256
  url: "https://url.de"
1095
1257
  };
1096
1258
 
1259
+ source.getFormat().readFeatures = jest.fn().mockImplementation(() => {
1260
+ return [feature];
1261
+ });
1262
+
1097
1263
  wfs.loadFeaturesManually(layerAttributes, source);
1098
1264
  await tick();
1099
1265
  expect(source.getFeatures()).toHaveLength(1);
@@ -33,7 +33,7 @@ jest.mock("../../src/searchAddress/searchGazetteer", () => {
33
33
 
34
34
  import {searchGazetteer as mockedSearchGazetteer} from "../../src/searchAddress/searchGazetteer";
35
35
 
36
- describe.only("searchAddress", function () {
36
+ describe("searchAddress", function () {
37
37
  describe("search", function () {
38
38
  it("rejects if missing configuration of what to search for", function (done) {
39
39
  search("Pflugacker", {}).catch(e => {
@@ -1,22 +0,0 @@
1
- /**
2
- * Parsing the params object in to string for url
3
- * @param {Object} params the paramters in object
4
- * @returns {String} The url parameters in string format
5
- */
6
- function getParamsUrl (params) {
7
- if (!params || typeof params !== "object" || params.constructor !== Object || !Object.keys(params).length) {
8
- return "";
9
- }
10
-
11
- let paramsUrl = "";
12
-
13
- Object.entries(params).forEach(([key, value]) => {
14
- paramsUrl += "&" + key + "=" + value;
15
- });
16
-
17
- return paramsUrl;
18
- }
19
-
20
- export {
21
- getParamsUrl
22
- };
package/tall DELETED
@@ -1,59 +0,0 @@
1
- v1.0.0
2
- v1.1.0
3
- v1.10.0
4
- v1.2.0
5
- v1.3.0
6
- v1.4.0
7
- v1.5.0
8
- v1.6.0
9
- v1.6.1
10
- v1.7.0
11
- v1.7.1
12
- v1.8.0
13
- v1.9.0
14
- v2.0.0
15
- v2.1.0
16
- v2.1.1
17
- v2.10.0
18
- v2.11.0
19
- v2.12.0
20
- v2.13.0
21
- v2.14.0
22
- v2.15.0
23
- v2.15.1
24
- v2.15.2
25
- v2.16.0
26
- v2.17.0
27
- v2.18.0
28
- v2.19.0
29
- v2.19.1
30
- v2.19.2
31
- v2.2.0
32
- v2.20.0
33
- v2.21.0
34
- v2.22.0
35
- v2.23.0
36
- v2.24.0
37
- v2.25.0
38
- v2.26.0
39
- v2.27.0
40
- v2.28.0
41
- v2.29.0
42
- v2.3.0
43
- v2.30.0
44
- v2.31.0
45
- v2.32.0
46
- v2.33.0
47
- v2.34.0
48
- v2.35.0
49
- v2.36.0
50
- v2.37.0
51
- v2.38.0
52
- v2.39.0
53
- v2.4.0
54
- v2.5.0
55
- v2.5.1
56
- v2.6.0
57
- v2.7.0
58
- v2.8.0
59
- v2.9.0
@@ -1,24 +0,0 @@
1
- import {getParamsUrl} from "../../src/lib/oafUtil";
2
-
3
- describe("oafUtil.js", function () {
4
- describe("getParamsUrl", function () {
5
- const params = {
6
- "anzahl_schueler": ">1000",
7
- "bezirk": "Bergedorf"
8
- };
9
-
10
- it("should return the parsed paramsUrl", function () {
11
- expect(getParamsUrl(params)).toEqual("&anzahl_schueler=>1000&bezirk=Bergedorf");
12
- });
13
-
14
- it("should return an empty string", function () {
15
- expect(getParamsUrl("string")).toEqual("");
16
- expect(getParamsUrl(0)).toEqual("");
17
- expect(getParamsUrl(null)).toEqual("");
18
- expect(getParamsUrl(undefined)).toEqual("");
19
- expect(getParamsUrl(true)).toEqual("");
20
- expect(getParamsUrl([])).toEqual("");
21
- expect(getParamsUrl({})).toEqual("");
22
- });
23
- });
24
- });