@masterportal/masterportalapi 2.20.0 → 2.22.0

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.
@@ -1,3 +1,4 @@
1
+ import {enableFetchMocks} from "jest-fetch-mock";
1
2
  import VectorLayer from "ol/layer/Vector.js";
2
3
  import VectorSource from "ol/source/Vector.js";
3
4
  import Cluster from "ol/source/Cluster.js";
@@ -5,10 +6,13 @@ import {Style, Icon} from "ol/style.js";
5
6
  import map from "../../src/maps/map.js";
6
7
  import defaults from "../../src/defaults";
7
8
  import {WFS} from "ol/format.js";
8
- import * as wfs from "../../src/layer/wfs";
9
+ import wfs from "../../src/layer/wfs";
9
10
  import {featureCollection} from "./resources/wfsFeatures";
10
11
  import {wfsFilterQuery} from "./resources/wfsFilter";
11
12
  import * as webgl from "../../src/renderer/webgl.js";
13
+ import {Feature} from "ol";
14
+ import Polygon from "ol/geom/Polygon";
15
+
12
16
 
13
17
  jest.mock("../../src/rawLayerList.js", () => {
14
18
  const original = jest.requireActual("../../src/rawLayerList.js");
@@ -26,6 +30,22 @@ jest.mock("../../src/renderer/webgl.js", () => {
26
30
 
27
31
 
28
32
  describe("wfs.js", function () {
33
+
34
+ const originalConsoleError = console.error;
35
+
36
+ beforeAll(() => {
37
+ console.error = jest.fn();
38
+ });
39
+
40
+ afterAll(() => {
41
+ console.error = originalConsoleError;
42
+ });
43
+
44
+ beforeEach(() => {
45
+ enableFetchMocks();
46
+ fetch.resetMocks();
47
+ });
48
+
29
49
  describe("createLayer", function () {
30
50
  it("creates a VectorLayer without id", function () {
31
51
  const layer = wfs.createLayer({version: "1.1.0"});
@@ -123,17 +143,12 @@ describe("wfs.js", function () {
123
143
  });
124
144
  });
125
145
  describe("createLayerSource", function () {
126
- const consoleError = console.error;
127
-
128
146
  beforeEach(() => {
129
147
  if (global.fetch) {
130
148
  global.fetch.mockClear();
131
149
  }
132
150
  });
133
- // to reset show error on load in console
134
- afterEach(() => {
135
- console.error = consoleError;
136
- });
151
+
137
152
  it("creates a VectorSource and beforeLoading, afterLoading and featuresFilter are called", function () {
138
153
  global.fetch = jest.fn().mockImplementationOnce(() => {
139
154
  return new Promise((resolve) => {
@@ -312,8 +327,6 @@ describe("wfs.js", function () {
312
327
  });
313
328
  });
314
329
  });
315
- // to reset show error on load in console when testing 'onLoadingError'
316
- console.error = jest.fn();
317
330
 
318
331
  const map2D = map.createMap(defaults),
319
332
  url = "https://url.de",
@@ -413,9 +426,618 @@ describe("wfs.js", function () {
413
426
  source.getListeners("featuresloadend")[0]({features: []});
414
427
  expect(webgl.afterLoading).toHaveBeenCalled();
415
428
  });
429
+ it("creates a vectorSource with credentials: include as params", () => {
430
+ global.fetch = jest.fn().mockImplementationOnce(() => {
431
+ // NOTE: fetch only rejects if a network error occurs, which do not apply to 4xx or 5xx http codes.
432
+ return new Promise((resolve) => {
433
+ resolve({
434
+ ok: true,
435
+ status: 200,
436
+ text: () => {
437
+ return featureCollection;
438
+ }
439
+ });
440
+ });
441
+ });
442
+
443
+ const map2D = map.createMap(defaults),
444
+ url = "https://url.de",
445
+ rawLayer = {
446
+ id: "id",
447
+ url: url,
448
+ featureNS: "http://www.deegree.org/app",
449
+ featureType: "krankenhaeuser_hh",
450
+ version: "2.0.0"
451
+ },
452
+ options = {
453
+ loadingParams: {xhrParameters: {credentials: "include"}}
454
+ },
455
+ layer = wfs.createLayer(rawLayer, {options});
456
+
457
+ layer.getSource().loadFeatures([-10000, -10000, 10000, 10000],
458
+ 1,
459
+ map2D.getView().getProjection());
460
+
461
+ expect(fetch).toHaveBeenCalledWith("https://url.de/?service=WFS&version=2.0.0&request=GetFeature&srsName=EPSG%3A25832&typeNames=krankenhaeuser_hh&bbox=-10000,-10000,10000,10000,EPSG:25832", {"credentials": "include"});
462
+ });
463
+ });
464
+ describe("parseDescribeFeatureTypeResponse", () => {
465
+ const exampleDescribeFeatureType = "<?xml version='1.0' encoding='UTF-8'?>\n" +
466
+ "<schema xmlns=\"http://www.w3.org/2001/XMLSchema\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:app=\"http://www.deegree.org/app\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" targetNamespace=\"http://www.deegree.org/app\" elementFormDefault=\"qualified\" attributeFormDefault=\"unqualified\">\n" +
467
+ " <import namespace=\"http://www.opengis.net/gml\" schemaLocation=\"http://schemas.opengis.net/gml/3.1.1/base/gml.xsd\"/>\n" +
468
+ " <element name=\"wfstgeom\" substitutionGroup=\"gml:_Feature\">\n" +
469
+ " <complexType>\n" +
470
+ " <complexContent>\n" +
471
+ " <extension base=\"gml:AbstractFeatureType\">\n" +
472
+ " <sequence>\n" +
473
+ " <element name=\"name\" minOccurs=\"0\" type=\"string\"/>\n" +
474
+ " <element name=\"nummer\" minOccurs=\"0\" type=\"integer\"/>\n" +
475
+ " <element name=\"bemerkung\" minOccurs=\"0\" type=\"string\"/>\n" +
476
+ " <element name=\"datum\" minOccurs=\"0\" type=\"date\"/>\n" +
477
+ " <element name=\"geom\" minOccurs=\"0\" type=\"gml:GeometryPropertyType\"/>\n" +
478
+ " </sequence>\n" +
479
+ " </extension>\n" +
480
+ " </complexContent>\n" +
481
+ " </complexType>\n" +
482
+ " </element>\n" +
483
+ "</schema>",
484
+ exampleProperties = [
485
+ {
486
+ key: "name",
487
+ label: "name",
488
+ required: false,
489
+ type: "string",
490
+ value: null
491
+ },
492
+ {
493
+ key: "nummer",
494
+ label: "nummer",
495
+ required: false,
496
+ type: "integer",
497
+ value: null
498
+ },
499
+ {
500
+ key: "bemerkung",
501
+ label: "bemerkung",
502
+ required: false,
503
+ type: "string",
504
+ value: null
505
+ },
506
+ {
507
+ key: "datum",
508
+ label: "datum",
509
+ required: false,
510
+ type: "date",
511
+ value: null
512
+ },
513
+ {
514
+ key: "geom",
515
+ label: "geom",
516
+ required: false,
517
+ type: "geometry",
518
+ value: null
519
+ }
520
+ ],
521
+
522
+ exampleDescribeFeatureType2 = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
523
+ "<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:gml=\"http://www.opengis.net/gml/3.2\" xmlns:gsm_wfs=\"gsm_wfs\" xmlns:wfs=\"http://www.opengis.net/wfs/2.0\" elementFormDefault=\"qualified\" targetNamespace=\"gsm_wfs\">\n" +
524
+ "<xsd:import namespace=\"http://www.opengis.net/gml/3.2\" schemaLocation=\"https://geoportal-konfig.muenchen.de/geoserver/schemas/gml/3.2.1/gml.xsd\"/>\n" +
525
+ "<xsd:complexType name=\"wfstgeomType\">\n" +
526
+ "<xsd:complexContent>\n" +
527
+ "<xsd:extension base=\"gml:AbstractFeatureType\">\n" +
528
+ "<xsd:sequence>\n" +
529
+ "<xsd:element maxOccurs=\"1\" minOccurs=\"0\" name=\"name\" nillable=\"true\" type=\"xsd:string\"/>\n" +
530
+ "<xsd:element maxOccurs=\"1\" minOccurs=\"0\" name=\"nummer\" nillable=\"true\" type=\"xsd:double\"/>\n" +
531
+ "<xsd:element maxOccurs=\"1\" minOccurs=\"0\" name=\"shape\" nillable=\"true\" type=\"gml:GeometryPropertyType\"/>\n" +
532
+ "</xsd:sequence>\n" +
533
+ "</xsd:extension>\n" +
534
+ "</xsd:complexContent>\n" +
535
+ "</xsd:complexType>\n" +
536
+ "<xsd:element name=\"wfstgeom\" substitutionGroup=\"gml:AbstractFeature\" type=\"gsm_wfs:kultur_rbe1_museenType\"/>\n" +
537
+ "</xsd:schema>",
538
+
539
+ exampleProperties2 = [
540
+ {
541
+ key: "name",
542
+ label: "name",
543
+ required: false,
544
+ type: "string",
545
+ value: null
546
+ },
547
+ {
548
+ key: "nummer",
549
+ label: "nummer",
550
+ required: false,
551
+ type: "double",
552
+ value: null
553
+ },
554
+ {
555
+ key: "shape",
556
+ label: "shape",
557
+ required: false,
558
+ type: "geometry",
559
+ value: null
560
+ }
561
+ ];
562
+
563
+ let featureType;
564
+
565
+ it("should retrieve the element values (required, type, key) from the parsed XML string if an element with name = featureType can be found in the XML for Example 1", () => {
566
+ featureType = "wfstgeom";
567
+
568
+ const featureProperties = wfs.parseDescribeFeatureTypeResponse(exampleDescribeFeatureType, featureType);
569
+
570
+ expect(Array.isArray(featureProperties)).toBe(true);
571
+ expect(featureProperties.length).toEqual(5);
572
+ exampleProperties.forEach(property => {
573
+ const parsedProperty = featureProperties.find(({key}) => key === property.key);
574
+
575
+ expect(parsedProperty).not.toEqual(undefined);
576
+ expect(parsedProperty).toEqual(property);
577
+ });
578
+ });
579
+ it("should return an empty array if no element with name = featureType can be found in the XML Example 1", () => {
580
+ featureType = "myCoolType";
581
+
582
+ const featureProperties = wfs.parseDescribeFeatureTypeResponse(exampleDescribeFeatureType, featureType);
583
+
584
+ expect(Array.isArray(featureProperties)).toBe(true);
585
+ expect(featureProperties.length).toEqual(0);
586
+ });
587
+ it("should retrieve the element values (required, type, key) from the parsed XML string if an element with name = featureType can be found in the XML for Example 2", () => {
588
+ featureType = "wfstgeom";
589
+
590
+ const featureProperties = wfs.parseDescribeFeatureTypeResponse(exampleDescribeFeatureType2, featureType);
591
+
592
+ expect(Array.isArray(featureProperties)).toBe.true;
593
+ expect(featureProperties.length).toEqual(3);
594
+
595
+ exampleProperties2.forEach(property => {
596
+ const parsedProperty = featureProperties.find(({key}) => key === property.key);
597
+
598
+ expect(parsedProperty).not.toEqual(undefined);
599
+ expect(parsedProperty).toEqual(property);
600
+ });
601
+ });
602
+ it("should return an empty array if no element with name = featureType can be found in the XML Example 2", () => {
603
+ featureType = "myCoolType";
604
+
605
+ const featureProperties = wfs.parseDescribeFeatureTypeResponse(exampleDescribeFeatureType2, featureType);
606
+
607
+ expect(Array.isArray(featureProperties)).toBe(true);
608
+ expect(featureProperties.length).toEqual(0);
609
+ });
610
+
611
+ });
612
+ describe("writeTransactionBody", () => {
613
+ const feature = new Feature({
614
+ geometry: new Polygon([
615
+ [
616
+ [
617
+ 9.17782024967994,
618
+ 50.20836600730087
619
+ ],
620
+ [
621
+ 9.200676227149245,
622
+ 50.20836600730087
623
+ ],
624
+ [
625
+ 9.200676227149245,
626
+ 50.20873353776312
627
+ ],
628
+ [
629
+ 9.17782024967994,
630
+ 50.20873353776312
631
+ ],
632
+ [
633
+ 9.17782024967994,
634
+ 50.20836600730087
635
+ ]
636
+ ]]),
637
+ name: "My Polygon"
638
+ }),
639
+
640
+ transactionOptions = {
641
+ featureNS: "myNS",
642
+ featurePrefix: "myPrefix",
643
+ featureType: "Polygon",
644
+ srsName: "EPSG:4326"
645
+ };
646
+
647
+
648
+ it("should write a transaction body for inserting a feature", () => {
649
+ const transactionBody = wfs.writeTransactionBody(feature, transactionOptions, "insert"),
650
+ expectedBody = "<Transaction xmlns=\"http://www.opengis.net/wfs\" service=\"WFS\" version=\"1.1.0\" xmlns:ns1=\"http://www.w3.org/2001/XMLSchema-instance\" ns1:schemaLocation=\"http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd\"><Insert><Polygon xmlns=\"myNS\"><geometry><Polygon xmlns=\"http://www.opengis.net/gml\" srsName=\"EPSG:4326\"><exterior><LinearRing srsName=\"EPSG:4326\"><posList srsDimension=\"2\">50.20836600730087 9.17782024967994 50.20836600730087 9.200676227149245 50.20873353776312 9.200676227149245 50.20873353776312 9.17782024967994 50.20836600730087 9.17782024967994</posList></LinearRing></exterior></Polygon></geometry><name>My Polygon</name></Polygon></Insert></Transaction>";
651
+
652
+ expect(transactionBody).toEqual(expectedBody);
653
+ });
654
+
655
+ it("should write a transaction body for updating a feature", () => {
656
+ feature.setId(1);
657
+ const transactionBody = wfs.writeTransactionBody(feature, transactionOptions, "selectedUpdate"),
658
+ expectedBody = "<Transaction xmlns=\"http://www.opengis.net/wfs\" service=\"WFS\" version=\"1.1.0\" xmlns:ns1=\"http://www.w3.org/2001/XMLSchema-instance\" ns1:schemaLocation=\"http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd\"><Update typeName=\"myPrefix:Polygon\" xmlns:myPrefix=\"myNS\"><Property><Name>geometry</Name><Value><Polygon xmlns=\"http://www.opengis.net/gml\" srsName=\"EPSG:4326\"><exterior><LinearRing srsName=\"EPSG:4326\"><posList srsDimension=\"2\">50.20836600730087 9.17782024967994 50.20836600730087 9.200676227149245 50.20873353776312 9.200676227149245 50.20873353776312 9.17782024967994 50.20836600730087 9.17782024967994</posList></LinearRing></exterior></Polygon></Value></Property><Property><Name>name</Name><Value>My Polygon</Value></Property><Filter xmlns=\"http://www.opengis.net/ogc\"><FeatureId fid=\"1\"/></Filter></Update></Transaction>";
659
+
660
+ expect(transactionBody).toEqual(expectedBody);
661
+ });
662
+
663
+ it("should write a transaction body for deleting a feature", () => {
664
+ feature.setId(1);
665
+ const transactionBody = wfs.writeTransactionBody(feature, transactionOptions, "delete"),
666
+ expectedBody = "<Transaction xmlns=\"http://www.opengis.net/wfs\" service=\"WFS\" version=\"1.1.0\" xmlns:ns1=\"http://www.w3.org/2001/XMLSchema-instance\" ns1:schemaLocation=\"http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd\"><Delete typeName=\"myPrefix:Polygon\" xmlns:myPrefix=\"myNS\"><Filter xmlns=\"http://www.opengis.net/ogc\"><FeatureId fid=\"1\"/></Filter></Delete></Transaction>";
667
+
668
+ expect(transactionBody).toEqual(expectedBody);
669
+ });
670
+
671
+ it("should throw error if transactionMethod is invalid", () => {
672
+ expect(() => wfs.writeTransactionBody(feature, transactionOptions, "remove")).toThrow(Error);
673
+ expect(() => wfs.writeTransactionBody(feature, transactionOptions, "remove")).toThrow("transactionMethod has to be \"insert\", \"selectedUpdate\" or \"delete\".");
674
+ });
675
+ });
676
+
677
+ describe("receivePossibleProperties", () => {
678
+ const exampleDescribeFeatureType = "<?xml version='1.0' encoding='UTF-8'?>\n" +
679
+ "<schema xmlns=\"http://www.w3.org/2001/XMLSchema\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:sf=\"http://cite.opengeospatial.org/gmlsf\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" targetNamespace=\"http://cite.opengeospatial.org/gmlsf\" elementFormDefault=\"qualified\" attributeFormDefault=\"unqualified\">\n" +
680
+ " <import namespace=\"http://www.opengis.net/gml\" schemaLocation=\"http://schemas.opengis.net/gml/3.1.1/base/gml.xsd\"/>\n" +
681
+ " <element name=\"wfstpoint\" substitutionGroup=\"gml:_Feature\">\n" +
682
+ " <complexType>\n" +
683
+ " <complexContent>\n" +
684
+ " <extension base=\"gml:AbstractFeatureType\">\n" +
685
+ " <sequence>\n" +
686
+ " <element name=\"geometry\" minOccurs=\"0\" type=\"gml:PointPropertyType\"/>\n" +
687
+ " <element name=\"name\" minOccurs=\"0\" type=\"string\"/>\n" +
688
+ " <element name=\"baumnummer\" minOccurs=\"0\" type=\"integer\"/>\n" +
689
+ " <element name=\"bemerkung\" minOccurs=\"0\" type=\"string\"/>\n" +
690
+ " <element name=\"datum\" minOccurs=\"0\" type=\"date\"/>\n" +
691
+ " <element name=\"isNew\" minOccurs=\"0\" type=\"boolean\"/>\n" +
692
+ " <element name=\"isUpdate\" minOccurs=\"0\" type=\"boolean\"/>\n" +
693
+ " </sequence>\n" +
694
+ " </extension>\n" +
695
+ " </complexContent>\n" +
696
+ " </complexType>\n" +
697
+ " </element>\n" +
698
+ " <element name=\"wfstline\" substitutionGroup=\"gml:_Feature\">\n" +
699
+ " <complexType>\n" +
700
+ " <complexContent>\n" +
701
+ " <extension base=\"gml:AbstractFeatureType\">\n" +
702
+ " <sequence>\n" +
703
+ " <element name=\"geometry\" minOccurs=\"0\" type=\"gml:LineStringPropertyType\"/>\n" +
704
+ " <element name=\"name\" minOccurs=\"0\" type=\"string\"/>\n" +
705
+ " <element name=\"nummer\" minOccurs=\"0\" type=\"integer\"/>\n" +
706
+ " <element name=\"bemerkung\" minOccurs=\"0\" type=\"string\"/>\n" +
707
+ " <element name=\"datum\" minOccurs=\"0\" type=\"date\"/>\n" +
708
+ " </sequence>\n" +
709
+ " </extension>\n" +
710
+ " </complexContent>\n" +
711
+ " </complexType>\n" +
712
+ " </element>\n" +
713
+ " <element name=\"wfstpolygon\" substitutionGroup=\"gml:_Feature\">\n" +
714
+ " <complexType>\n" +
715
+ " <complexContent>\n" +
716
+ " <extension base=\"gml:AbstractFeatureType\">\n" +
717
+ " <sequence>\n" +
718
+ " <element name=\"name\" minOccurs=\"0\" type=\"string\"/>\n" +
719
+ " <element name=\"nummer\" minOccurs=\"0\" type=\"integer\"/>\n" +
720
+ " <element name=\"bemerkung\" minOccurs=\"0\" type=\"string\"/>\n" +
721
+ " <element name=\"datum\" minOccurs=\"0\" type=\"date\"/>\n" +
722
+ " <element name=\"geom\" minOccurs=\"0\" type=\"gml:GeometryPropertyType\"/>\n" +
723
+ " </sequence>\n" +
724
+ " </extension>\n" +
725
+ " </complexContent>\n" +
726
+ " </complexType>\n" +
727
+ " </element>\n" +
728
+ "</schema>",
729
+ geoserverDescribeFeatureType = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:gml=\"http://www.opengis.net/gml/3.2\" xmlns:test=\"http://opengeo.org/test\" xmlns:wfs=\"http://www.opengis.net/wfs/2.0\" elementFormDefault=\"qualified\" targetNamespace=\"http://opengeo.org/test\">\n" +
730
+ " <xsd:import namespace=\"http://www.opengis.net/gml/3.2\" schemaLocation=\"https://geoservice.norderstedt.de/geoserver/schemas/gml/3.2.1/gml.xsd\"/>\n" +
731
+ " <xsd:complexType name=\"test_polygonType\">\n" +
732
+ " <xsd:complexContent>\n" +
733
+ " <xsd:extension base=\"gml:AbstractFeatureType\">\n" +
734
+ " <xsd:sequence>\n" +
735
+ " <xsd:element maxOccurs=\"1\" minOccurs=\"0\" name=\"id\" nillable=\"true\" type=\"xsd:long\"/>\n" +
736
+ " <xsd:element maxOccurs=\"1\" minOccurs=\"0\" name=\"geom\" nillable=\"true\" type=\"gml:SurfacePropertyType\"/>\n" +
737
+ " <xsd:element maxOccurs=\"1\" minOccurs=\"0\" name=\"hochkomma\" nillable=\"true\" type=\"xsd:string\"/>\n" +
738
+ " </xsd:sequence>\n" +
739
+ " </xsd:extension>\n" +
740
+ " </xsd:complexContent>\n" +
741
+ " </xsd:complexType>\n" +
742
+ " <xsd:element name=\"test_polygon\" substitutionGroup=\"gml:AbstractFeature\" type=\"test:test_polygonType\"/>\n" +
743
+ "</xsd:schema>";
744
+
745
+ it("should receive the possible properties", async () => {
746
+ fetch.mockResponseOnce(exampleDescribeFeatureType);
747
+
748
+ const properties = await wfs.receivePossibleProperties("https://team-waas-was-here.lgln", "1.1.0", "wfstpolygon", false),
749
+ exampleProperties = [
750
+ {
751
+ key: "name",
752
+ label: "name",
753
+ required: false,
754
+ type: "string",
755
+ value: null
756
+ },
757
+ {
758
+ key: "nummer",
759
+ label: "nummer",
760
+ required: false,
761
+ type: "integer",
762
+ value: null
763
+ },
764
+ {
765
+ key: "bemerkung",
766
+ label: "bemerkung",
767
+ required: false,
768
+ type: "string",
769
+ value: null
770
+ },
771
+ {
772
+ key: "datum",
773
+ label: "datum",
774
+ required: false,
775
+ type: "date",
776
+ value: null
777
+ },
778
+ {
779
+ key: "geom",
780
+ label: "geom",
781
+ required: false,
782
+ type: "geometry",
783
+ value: null
784
+ }
785
+ ];
786
+
787
+ expect(Array.isArray(properties)).toBe(true);
788
+ expect(properties.length).toEqual(5);
789
+ exampleProperties.forEach(property => {
790
+ const parsedProperty = properties.find(({key}) => key === property.key);
791
+
792
+ expect(parsedProperty).not.toEqual(undefined);
793
+ expect(parsedProperty).toEqual(property);
794
+ });
795
+ expect(fetch).toHaveBeenCalledWith("https://team-waas-was-here.lgln?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.1.0&TYPENAME=wfstpolygon", {"responseType": "text/xml", "credentials": "omit"});
796
+
797
+ });
798
+
799
+ it("should receive the possible properties from a geoserver", async () => {
800
+ fetch.mockResponseOnce(geoserverDescribeFeatureType);
801
+
802
+ const properties = await wfs.receivePossibleProperties("https://team-waas-was-here.lgln", "1.1.0", "test_polygon", false),
803
+ exampleProperties = [
804
+ {
805
+ key: "id",
806
+ label: "id",
807
+ required: false,
808
+ type: "integer",
809
+ value: null
810
+ },
811
+ {
812
+ key: "geom",
813
+ label: "geom",
814
+ required: false,
815
+ type: "geometry",
816
+ value: null
817
+ },
818
+ {
819
+ key: "hochkomma",
820
+ label: "hochkomma",
821
+ required: false,
822
+ type: "string",
823
+ value: null
824
+ }
825
+ ];
826
+
827
+ expect(Array.isArray(properties)).toBe(true);
828
+ expect(properties.length).toEqual(3);
829
+ exampleProperties.forEach(property => {
830
+ const parsedProperty = properties.find(({key}) => key === property.key);
831
+
832
+ expect(parsedProperty).not.toEqual(undefined);
833
+ expect(parsedProperty).toEqual(property);
834
+ });
835
+ 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"});
836
+
837
+ });
838
+
839
+ it("should receive the possible properties with credentials", async () => {
840
+ fetch.mockResponseOnce(exampleDescribeFeatureType);
841
+
842
+ const properties = await wfs.receivePossibleProperties("https://team-waas-was-here.lgln", "1.1.0", "wfstpolygon", true),
843
+ exampleProperties = [
844
+ {
845
+ key: "name",
846
+ label: "name",
847
+ required: false,
848
+ type: "string",
849
+ value: null
850
+ },
851
+ {
852
+ key: "nummer",
853
+ label: "nummer",
854
+ required: false,
855
+ type: "integer",
856
+ value: null
857
+ },
858
+ {
859
+ key: "bemerkung",
860
+ label: "bemerkung",
861
+ required: false,
862
+ type: "string",
863
+ value: null
864
+ },
865
+ {
866
+ key: "datum",
867
+ label: "datum",
868
+ required: false,
869
+ type: "date",
870
+ value: null
871
+ },
872
+ {
873
+ key: "geom",
874
+ label: "geom",
875
+ required: false,
876
+ type: "geometry",
877
+ value: null
878
+ }
879
+ ];
880
+
881
+ expect(Array.isArray(properties)).toBe(true);
882
+ expect(properties.length).toEqual(5);
883
+ exampleProperties.forEach(property => {
884
+ const parsedProperty = properties.find(({key}) => key === property.key);
885
+
886
+ expect(parsedProperty).not.toEqual(undefined);
887
+ expect(parsedProperty).toEqual(property);
888
+ });
889
+ expect(fetch).toHaveBeenCalledWith("https://team-waas-was-here.lgln?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.1.0&TYPENAME=wfstpolygon", {"responseType": "text/xml", "credentials": "include"});
890
+
891
+ });
892
+
893
+ it("should throw an error if the properties can not be fetched", async () => {
894
+ fetch.mockAbortOnce();
895
+
896
+ await expect(async () => {
897
+ await wfs.receivePossibleProperties("https://team-waas-was-here.lgln", "1.1.0", "wfstgeom", false);
898
+ }).rejects.toThrow(Error);
899
+ });
900
+ });
901
+
902
+ describe("sendTransaction", () => {
903
+ const layer = {
904
+ id: Symbol("layerId"),
905
+ url: "some.good.url",
906
+ isSecured: false,
907
+ featureNS: "wfsgeom",
908
+ featurePrefix: "test",
909
+ featureType: "Polygon",
910
+ version: "1.1.0"
911
+ },
912
+ feature = new Feature({
913
+ geometry: new Polygon([
914
+ [
915
+ [
916
+ 9.17782024967994,
917
+ 50.20836600730087
918
+ ],
919
+ [
920
+ 9.200676227149245,
921
+ 50.20836600730087
922
+ ],
923
+ [
924
+ 9.200676227149245,
925
+ 50.20873353776312
926
+ ],
927
+ [
928
+ 9.17782024967994,
929
+ 50.20873353776312
930
+ ],
931
+ [
932
+ 9.17782024967994,
933
+ 50.20836600730087
934
+ ]
935
+ ]]),
936
+ name: "My Polygon"
937
+ }),
938
+ srsName = "EPSG:4326",
939
+ url = "https://team-waas-was-here.lgln",
940
+ insertTransaction = "insert",
941
+ updateTransaction = "selectedUpdate",
942
+ deleteTransaction = "delete",
943
+ fetchResponseInsert = "<?xml version='1.0' encoding='UTF-8'?>\n" +
944
+ "<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" +
945
+ " <wfs:TransactionSummary>\n" +
946
+ " <wfs:totalInserted>1</wfs:totalInserted>\n" +
947
+ " <wfs:totalUpdated>0</wfs:totalUpdated>\n" +
948
+ " <wfs:totalDeleted>0</wfs:totalDeleted>\n" +
949
+ " </wfs:TransactionSummary>\n" +
950
+ " <wfs:InsertResults>\n" +
951
+ " <wfs:Feature>\n" +
952
+ " <ogc:FeatureId fid=\"wfst.59\"/>\n" +
953
+ " </wfs:Feature>\n" +
954
+ " </wfs:InsertResults>\n" +
955
+ "</wfs:TransactionResponse>",
956
+ fetchResponseUpdate = "<?xml version='1.0' encoding='UTF-8'?>\n" +
957
+ "<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" +
958
+ " <wfs:TransactionSummary>\n" +
959
+ " <wfs:totalInserted>0</wfs:totalInserted>\n" +
960
+ " <wfs:totalUpdated>1</wfs:totalUpdated>\n" +
961
+ " <wfs:totalDeleted>0</wfs:totalDeleted>\n" +
962
+ " </wfs:TransactionSummary>\n" +
963
+ "</wfs:TransactionResponse>",
964
+ fetchResponseDelete = "<?xml version='1.0' encoding='UTF-8'?>\n" +
965
+ "<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" +
966
+ " <wfs:TransactionSummary>\n" +
967
+ " <wfs:totalInserted>0</wfs:totalInserted>\n" +
968
+ " <wfs:totalUpdated>0</wfs:totalUpdated>\n" +
969
+ " <wfs:totalDeleted>1</wfs:totalDeleted>\n" +
970
+ " </wfs:TransactionSummary>\n" +
971
+ "</wfs:TransactionResponse>";
972
+
973
+ it("should return the inserted feature if the transaction was successful", async function () {
974
+ fetch.mockResponseOnce(fetchResponseInsert);
975
+
976
+ expect(await wfs.sendTransaction(srsName, feature, url, layer, insertTransaction)).toEqual(feature);
977
+ });
978
+
979
+ it("should return the inserted feature if the transaction was successful", async function () {
980
+ fetch.mockResponseOnce(fetchResponseInsert);
981
+ layer.isSecured = true;
982
+
983
+ expect(await wfs.sendTransaction(srsName, feature, url, layer, insertTransaction)).toEqual(feature);
984
+ });
985
+
986
+ it("should return the updated feature if the transaction was successful", async function () {
987
+ fetch.mockResponseOnce(fetchResponseUpdate);
988
+ feature.setId(1);
989
+
990
+ expect(await wfs.sendTransaction(srsName, feature, url, layer, updateTransaction)).toEqual(feature);
991
+ });
992
+
993
+ it("should return the deleted feature if the transaction was successful", async function () {
994
+ fetch.mockResponseOnce(fetchResponseDelete);
995
+ feature.setId(1);
996
+
997
+ expect(await wfs.sendTransaction(srsName, feature, url, layer, deleteTransaction)).toEqual(feature);
998
+ });
999
+
1000
+ it("should throw an error if fetch fails", async function () {
1001
+ fetch.mockAbortOnce();
1002
+
1003
+ await expect(async () => wfs.sendTransaction(srsName, feature, url, layer, insertTransaction)).rejects.toThrow(Error);
1004
+ });
1005
+
1006
+ it("should throw an error if transaction type is not insert, selectedUpdate or delete", async function () {
1007
+ fetch.mockResponseOnce(fetchResponseDelete);
1008
+ feature.setId(1);
1009
+
1010
+ await expect(async () => wfs.sendTransaction(srsName, feature, url, layer, "löschen")).rejects.toThrow(Error);
1011
+ });
1012
+
1013
+ it("should send a request and show an alert with a generic error message if no transactionsSummary is present in the XML response", async () => {
1014
+ const failedResponse = "<?xml version='1.0' encoding='UTF-8'?>\n" +
1015
+ "<ows:ExceptionReport xmlns:ows=\"http://www.opengis.net/ows\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.opengis.net/ows http://schemas.opengis.net/ows/1.0.0/owsExceptionReport.xsd\" version=\"1.0.0\">\n" +
1016
+ " <ows:Exception" +
1017
+ " <ows:ExceptionText>Cannot perform insert operation: Error in XML document (line: 1, column: 234, character offset: 233): Feature type \"{wrong}wfst\" is unknown.</ows:ExceptionText>\n" +
1018
+ " </ows:Exception>\n" +
1019
+ "</ows:ExceptionReport>";
1020
+
1021
+ fetch.mockResponseOnce(failedResponse);
1022
+
1023
+ await expect(async () => wfs.sendTransaction(srsName, feature, url, layer, insertTransaction)).rejects.toThrow(Error);
1024
+ });
1025
+
1026
+ it("should send a request, show an alert with a generic error message if no transactionsSummary is present in the XML response and log an error if an exceptionText is present in the XML response", async () => {
1027
+ const failedResponse = "<?xml version='1.0' encoding='UTF-8'?>\n" +
1028
+ "<ows:ExceptionReport xmlns:ows=\"http://www.opengis.net/ows\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.opengis.net/ows http://schemas.opengis.net/ows/1.0.0/owsExceptionReport.xsd\" version=\"1.0.0\">\n" +
1029
+ " <ows:Exception>" +
1030
+ " <ows:ExceptionText>Cannot perform insert operation: Error in XML document (line: 1, column: 234, character offset: 233): Feature type \"{wrong}wfst\" is unknown.</ows:ExceptionText>\n" +
1031
+ " </ows:Exception>\n" +
1032
+ "</ows:ExceptionReport>";
1033
+
1034
+ fetch.mockResponseOnce(failedResponse);
1035
+
1036
+ 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.");
1037
+ });
416
1038
  });
1039
+
417
1040
  describe("loadFeaturesManually", function () {
418
- const consoleError = console.error;
419
1041
  let tick;
420
1042
 
421
1043
  beforeEach(() => {
@@ -429,10 +1051,6 @@ describe("wfs.js", function () {
429
1051
  global.fetch.mockClear();
430
1052
  }
431
1053
  });
432
- // to reset show error on load in console
433
- afterEach(() => {
434
- console.error = consoleError;
435
- });
436
1054
 
437
1055
  it("load features manually", async function () {
438
1056
  global.fetch = jest.fn().mockImplementationOnce(() => {
@@ -468,3 +1086,4 @@ describe("wfs.js", function () {
468
1086
  });
469
1087
  });
470
1088
 
1089
+