@masterportal/masterportalapi 2.13.0 → 2.15.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.
- package/.eslintrc +2 -1
- package/CHANGELOG.md +16 -7
- package/example/config/localGeoJSONPoints.js +2106 -0
- package/example/config/portal.json +47 -1
- package/example/config/services.json +20 -0
- package/example/index.js +50 -7
- package/jest.config.js +1 -1
- package/jest.setup.js +9 -1
- package/package.json +64 -62
- package/src/index.js +3 -1
- package/src/layer/geojson/index.js +55 -4
- package/src/layer/oaf.js +35 -5
- package/src/layer/vectorBase.js +20 -1
- package/src/layer/wfs.js +38 -7
- package/src/lib/attributeMapper.js +231 -0
- package/src/lib/getValueFromObjectByPath.js +73 -0
- package/src/lib/thousandsSeparator.js +23 -0
- package/src/maps/ol/olMap.js +4 -3
- package/src/renderer/webgl.js +250 -0
- package/src/vectorStyle/createStyle.js +259 -0
- package/src/vectorStyle/lib/colorConvertions.js +97 -0
- package/src/vectorStyle/lib/createLegendInfo.js +28 -0
- package/src/vectorStyle/lib/getGeometryTypeFromService.js +153 -0
- package/src/vectorStyle/lib/getRuleForIndex.js +62 -0
- package/src/vectorStyle/lib/valueOperations.js +172 -0
- package/src/vectorStyle/styleList.js +281 -0
- package/src/vectorStyle/styles/defaultStyles.js +177 -0
- package/src/vectorStyle/styles/point/stylePoint.js +108 -0
- package/src/vectorStyle/styles/point/stylePointCircle.js +29 -0
- package/src/vectorStyle/styles/point/stylePointIcon.js +79 -0
- package/src/vectorStyle/styles/point/stylePointInterval.js +124 -0
- package/src/vectorStyle/styles/point/stylePointNominal.js +232 -0
- package/src/vectorStyle/styles/point/stylePointRegularShape.js +39 -0
- package/src/vectorStyle/styles/polygon/polygonStyleHatch.js +160 -0
- package/src/vectorStyle/styles/polygon/stylePolygon.js +125 -0
- package/src/vectorStyle/styles/style.js +161 -0
- package/src/vectorStyle/styles/styleCesium.js +106 -0
- package/src/vectorStyle/styles/styleLine.js +51 -0
- package/src/vectorStyle/styles/styleText.js +143 -0
- package/test/layer/geojson/index.test.js +23 -0
- package/test/layer/oaf.test.js +30 -0
- package/test/layer/vectorBase.test.js +27 -7
- package/test/layer/wfs.test.js +30 -0
- package/test/lib/attributeMapper.test.js +290 -0
- package/test/lib/getValueFromObjectByPath.test.js +61 -0
- package/test/lib/thousandsSeparator.test.js +58 -0
- package/test/renderer/webgl.test.js +161 -0
- package/test/vectorStyle/createStyle.test.js +335 -0
- package/test/vectorStyle/lib/colorConvertions.test.js +42 -0
- package/test/vectorStyle/lib/getRuleForIndex.test.js +132 -0
- package/test/vectorStyle/lib/valueOperations.test.js +191 -0
- package/test/vectorStyle/styles/point/stylePoint.test.js +28 -0
- package/test/vectorStyle/styles/point/stylePointCircle.test.js +30 -0
- package/test/vectorStyle/styles/point/stylePointIcon.test.js +83 -0
- package/test/vectorStyle/styles/point/stylePointInterval.test.js +57 -0
- package/test/vectorStyle/styles/point/stylePointNominal.test.js +84 -0
- package/test/vectorStyle/styles/point/stylePointRegularShape.test.js +24 -0
- package/test/vectorStyle/styles/polygon/polygonStyleHatch.test.js +95 -0
- package/test/vectorStyle/styles/polygon/stylePolygon.test.js +61 -0
- package/test/vectorStyle/styles/styleLine.test.js +29 -0
- package/test/vectorStyle/styles/styleText.test.js +49 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import StyleClass from "./style";
|
|
2
|
+
import {Text, Fill, Stroke} from "ol/style.js";
|
|
3
|
+
import {mapAttributes} from "../../lib/attributeMapper";
|
|
4
|
+
import {prepareValue, isObjectPath} from "../../lib/attributeMapper";
|
|
5
|
+
import defaultStyle from "./defaultStyles";
|
|
6
|
+
|
|
7
|
+
class TextStyle extends StyleClass {
|
|
8
|
+
/**
|
|
9
|
+
* @description Class to create ol.style/Text
|
|
10
|
+
* @class TextStyle
|
|
11
|
+
* @constructor
|
|
12
|
+
* @extends StyleClass
|
|
13
|
+
* @memberof VectorStyle.Style
|
|
14
|
+
*/
|
|
15
|
+
constructor () {
|
|
16
|
+
super();
|
|
17
|
+
this.attributes = {...defaultStyle.text};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* This function initializes the styleText Object by setting or overwriting some attributes.
|
|
22
|
+
* @param {ol/feature} feature Feature to be styled.
|
|
23
|
+
* @param {object} styles styling properties to overwrite defaults
|
|
24
|
+
* @param {Boolean} isClustered Flag to show if feature is clustered.
|
|
25
|
+
* @returns {void}
|
|
26
|
+
*/
|
|
27
|
+
initialize (feature, styles, isClustered) {
|
|
28
|
+
this.setFeature(feature);
|
|
29
|
+
this.setIsClustered(isClustered);
|
|
30
|
+
this.overwriteStyling(styles);
|
|
31
|
+
this.setStyle(this.getStyle());
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* This function returns a style for each feature.
|
|
36
|
+
* @returns {ol/style} - The created style.
|
|
37
|
+
*/
|
|
38
|
+
getStyle () {
|
|
39
|
+
const isClustered = this.isClustered,
|
|
40
|
+
feature = this.feature,
|
|
41
|
+
labelField = this.labelField;
|
|
42
|
+
|
|
43
|
+
if (isClustered && feature.get("features")?.length > 1 && this.attributes.clusterTextType !== "none") {
|
|
44
|
+
return this.createClusteredTextStyle();
|
|
45
|
+
}
|
|
46
|
+
else if (labelField) {
|
|
47
|
+
return this.createLabeledTextStyle();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return new Text();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Returns the rotation value and its corresponding value according to style.json.
|
|
55
|
+
* @param {Object} rotation - The rotation object from the style.json
|
|
56
|
+
* @param {Object} featureValues - The values object from the feature
|
|
57
|
+
* @returns {number} - The rotation value in degrees or radiants.
|
|
58
|
+
*/
|
|
59
|
+
getRotationValue (rotation, featureValues) {
|
|
60
|
+
if (typeof rotation === "object") {
|
|
61
|
+
const {value, isDegree} = rotation;
|
|
62
|
+
|
|
63
|
+
if (isObjectPath(value) && featureValues !== undefined) {
|
|
64
|
+
const rotationValueFromService = parseInt(prepareValue(featureValues, value), 10);
|
|
65
|
+
|
|
66
|
+
return isDegree ? rotationValueFromService * Math.PI / 180 : rotationValueFromService;
|
|
67
|
+
}
|
|
68
|
+
return isDegree ? parseInt(value, 10) * Math.PI / 180 : parseInt(value, 10);
|
|
69
|
+
}
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Creates text style for clustered features. The text attribute is set according to "clusterTextType".
|
|
75
|
+
* "clusterTextType" === "counter" sets the number of clustered features.
|
|
76
|
+
* "clusterTextType" === "text" sets the value of "clusterText" or "undefined".
|
|
77
|
+
* @returns {ol/style/Text} - The created style.
|
|
78
|
+
*/
|
|
79
|
+
createClusteredTextStyle () {
|
|
80
|
+
const feature = this.feature;
|
|
81
|
+
let text;
|
|
82
|
+
|
|
83
|
+
if (this.attributes.clusterTextType === "counter") {
|
|
84
|
+
text = feature.get("features").length.toString();
|
|
85
|
+
}
|
|
86
|
+
else if (this.attributes.clusterTextType === "text" && typeof this.attributes.clusterText === "string") {
|
|
87
|
+
text = this.attributes.clusterText;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
text = "undefined";
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return new Text({
|
|
94
|
+
text: text,
|
|
95
|
+
textAlign: this.attributes.clusterTextAlign,
|
|
96
|
+
offsetX: this.attributes.clusterTextOffsetX,
|
|
97
|
+
offsetY: this.attributes.clusterTextOffsetY,
|
|
98
|
+
font: this.attributes.clusterTextFont,
|
|
99
|
+
scale: this.attributes.clusterTextScale,
|
|
100
|
+
fill: new Fill({
|
|
101
|
+
color: this.attributes.clusterTextFillColor
|
|
102
|
+
}),
|
|
103
|
+
stroke: new Stroke({
|
|
104
|
+
color: this.attributes.clusterTextStrokeColor,
|
|
105
|
+
width: this.attributes.clusterTextStrokeWidth
|
|
106
|
+
}),
|
|
107
|
+
rotation: this.getRotationValue(this.attributes.rotation, feature.getProperties())
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Creates text style for simple features. The text attribute is set using "labelField".
|
|
113
|
+
* @returns {ol/style/Text} - The created style.
|
|
114
|
+
*/
|
|
115
|
+
createLabeledTextStyle () {
|
|
116
|
+
const feature = this.feature,
|
|
117
|
+
featureProperties = feature.getProperties(),
|
|
118
|
+
textSuffix = this.attributes.textSuffix;
|
|
119
|
+
let text = mapAttributes(featureProperties, this.attributes.labelField, false);
|
|
120
|
+
|
|
121
|
+
if (textSuffix !== "") {
|
|
122
|
+
text = text + " " + textSuffix;
|
|
123
|
+
}
|
|
124
|
+
return new Text({
|
|
125
|
+
text: text.toString(),
|
|
126
|
+
textAlign: this.attributes.textAlign,
|
|
127
|
+
offsetX: this.attributes.textOffsetX,
|
|
128
|
+
offsetY: this.attributes.textOffsetY,
|
|
129
|
+
font: this.attributes.textFont,
|
|
130
|
+
scale: this.attributes.textScale,
|
|
131
|
+
fill: new Fill({
|
|
132
|
+
color: this.attributes.textFillColor
|
|
133
|
+
}),
|
|
134
|
+
stroke: new Stroke({
|
|
135
|
+
color: this.attributes.textStrokeColor,
|
|
136
|
+
width: this.attributes.textStrokeWidth
|
|
137
|
+
}),
|
|
138
|
+
rotation: this.getRotationValue(this.attributes.rotation, featureProperties)
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export default TextStyle;
|
|
@@ -3,9 +3,17 @@ import VectorSource from "ol/source/Vector.js";
|
|
|
3
3
|
import Feature from "ol/Feature";
|
|
4
4
|
import {Style, Icon} from "ol/style.js";
|
|
5
5
|
import {geojson} from "../../../src";
|
|
6
|
+
import * as webgl from "../../../src/renderer/webgl.js";
|
|
6
7
|
|
|
7
8
|
const features = [new Feature(), new Feature()];
|
|
8
9
|
|
|
10
|
+
jest.mock("../../../src/renderer/webgl.js", () => {
|
|
11
|
+
const original = jest.requireActual("../../../src/renderer/webgl.js");
|
|
12
|
+
|
|
13
|
+
original.afterLoading = jest.fn();
|
|
14
|
+
return original;
|
|
15
|
+
});
|
|
16
|
+
|
|
9
17
|
describe("geojson/index", function () {
|
|
10
18
|
describe("createLayer", function () {
|
|
11
19
|
it("creates an ol/layer/Vector", function () {
|
|
@@ -70,6 +78,12 @@ describe("geojson/index", function () {
|
|
|
70
78
|
expect(layer.get("name")).toEqual("name");
|
|
71
79
|
expect(layer.get("layers")).toEqual("layer1, layer2");
|
|
72
80
|
});
|
|
81
|
+
it("creates a WebGLLayer, with param renderer \"webgl\"", function () {
|
|
82
|
+
const layer = geojson.createLayer({}, {layerParams: {renderer: "webgl"}});
|
|
83
|
+
|
|
84
|
+
expect(layer.constructor.name).toEqual("LocalWebGLLayer");
|
|
85
|
+
expect(layer.getSource()).toBeInstanceOf(VectorSource);
|
|
86
|
+
});
|
|
73
87
|
});
|
|
74
88
|
|
|
75
89
|
describe("createLayerSource", function () {
|
|
@@ -79,6 +93,15 @@ describe("geojson/index", function () {
|
|
|
79
93
|
expect(source.getFormat()).toBeDefined();
|
|
80
94
|
expect(source.getUrl()).toBeDefined();
|
|
81
95
|
});
|
|
96
|
+
it("creates a vectorSource with an additional listener, when renderer is \"webgl\"", () => {
|
|
97
|
+
const
|
|
98
|
+
rawLayer = {url: "example.com/geo.json"},
|
|
99
|
+
source = geojson.createLayerSource({...rawLayer, renderer: "webgl"}, {});
|
|
100
|
+
|
|
101
|
+
expect(source.getListeners("featuresloadend")).toHaveLength(2);
|
|
102
|
+
source.getListeners("featuresloadend")[1]({features: []});
|
|
103
|
+
expect(webgl.afterLoading).toHaveBeenCalled();
|
|
104
|
+
});
|
|
82
105
|
|
|
83
106
|
});
|
|
84
107
|
|
package/test/layer/oaf.test.js
CHANGED
|
@@ -7,6 +7,7 @@ import defaults from "../../src/defaults";
|
|
|
7
7
|
import GeoJSON from "ol/format/GeoJSON.js";
|
|
8
8
|
import * as oaf from "../../src/layer/oaf";
|
|
9
9
|
import {featureCollection} from "./resources/oafFeatures";
|
|
10
|
+
import * as webgl from "../../src/renderer/webgl.js";
|
|
10
11
|
|
|
11
12
|
jest.mock("../../src/rawLayerList.js", () => {
|
|
12
13
|
const original = jest.requireActual("../../src/rawLayerList.js");
|
|
@@ -15,6 +16,13 @@ jest.mock("../../src/rawLayerList.js", () => {
|
|
|
15
16
|
return original;
|
|
16
17
|
});
|
|
17
18
|
|
|
19
|
+
jest.mock("../../src/renderer/webgl.js", () => {
|
|
20
|
+
const original = jest.requireActual("../../src/renderer/webgl.js");
|
|
21
|
+
|
|
22
|
+
original.afterLoading = jest.fn();
|
|
23
|
+
return original;
|
|
24
|
+
});
|
|
25
|
+
|
|
18
26
|
|
|
19
27
|
describe("oaf.js", function () {
|
|
20
28
|
describe("createLayer", function () {
|
|
@@ -107,6 +115,12 @@ describe("oaf.js", function () {
|
|
|
107
115
|
expect(layer.get("name")).toEqual("name");
|
|
108
116
|
expect(layer.get("layers")).toEqual("layer1, layer2");
|
|
109
117
|
});
|
|
118
|
+
it("creates a WebGLLayer, with param renderer \"webgl\"", function () {
|
|
119
|
+
const layer = oaf.createLayer({id: "id"}, {layerParams: {renderer: "webgl"}});
|
|
120
|
+
|
|
121
|
+
expect(layer.constructor.name).toEqual("LocalWebGLLayer");
|
|
122
|
+
expect(layer.getSource()).toBeInstanceOf(VectorSource);
|
|
123
|
+
});
|
|
110
124
|
});
|
|
111
125
|
describe("createLayerSource", function () {
|
|
112
126
|
const consoleError = console.error;
|
|
@@ -241,5 +255,21 @@ describe("oaf.js", function () {
|
|
|
241
255
|
expect(afterLoadingMock.mock.calls.length).toBe(1);
|
|
242
256
|
});
|
|
243
257
|
});
|
|
258
|
+
it("creates a vectorSource with an additional listener, when renderer is \"webgl\"", () => {
|
|
259
|
+
const
|
|
260
|
+
url = "https://url.de",
|
|
261
|
+
rawLayer = {
|
|
262
|
+
id: "id",
|
|
263
|
+
url: url,
|
|
264
|
+
featureNS: "http://www.deegree.org/app",
|
|
265
|
+
featureType: "krankenhaeuser_hh",
|
|
266
|
+
version: "1.0.0"
|
|
267
|
+
},
|
|
268
|
+
source = oaf.createLayerSource({...rawLayer, renderer: "webgl"});
|
|
269
|
+
|
|
270
|
+
expect(source.getListeners("featuresloadend")).toHaveLength(1);
|
|
271
|
+
source.getListeners("featuresloadend")[0]({features: []});
|
|
272
|
+
expect(webgl.afterLoading).toHaveBeenCalled();
|
|
273
|
+
});
|
|
244
274
|
});
|
|
245
275
|
});
|
|
@@ -4,6 +4,14 @@ import Polygon from "ol/geom/Polygon";
|
|
|
4
4
|
import VectorLayer from "ol/layer/Vector";
|
|
5
5
|
import VectorSource from "ol/source/Vector.js";
|
|
6
6
|
import * as vectorBase from "../../src/layer/vectorBase";
|
|
7
|
+
import * as webgl from "../../src/renderer/webgl.js";
|
|
8
|
+
|
|
9
|
+
jest.mock("../../src/renderer/webgl.js", () => {
|
|
10
|
+
const original = jest.requireActual("../../src/renderer/webgl.js");
|
|
11
|
+
|
|
12
|
+
original.afterLoading = jest.fn();
|
|
13
|
+
return original;
|
|
14
|
+
});
|
|
7
15
|
|
|
8
16
|
describe("vectorBase.js", function () {
|
|
9
17
|
|
|
@@ -25,23 +33,35 @@ describe("vectorBase.js", function () {
|
|
|
25
33
|
|
|
26
34
|
expect(source).toBeInstanceOf(VectorSource);
|
|
27
35
|
});
|
|
36
|
+
it("creates a vectorSource with an additional listener, when renderer is \"webgl\"", () => {
|
|
37
|
+
vectorBase.createLayerSource({renderer: "webgl"});
|
|
38
|
+
|
|
39
|
+
expect(webgl.afterLoading).toHaveBeenCalled();
|
|
40
|
+
});
|
|
28
41
|
});
|
|
29
42
|
|
|
30
43
|
describe("createLayer", function () {
|
|
44
|
+
const attr = {
|
|
45
|
+
name: "Albus Percival Wulfric Brian Dumbledore",
|
|
46
|
+
typ: "VectorBase",
|
|
47
|
+
gfiAttributes: "ignore",
|
|
48
|
+
id: "Rawenclaw_01"
|
|
49
|
+
};
|
|
50
|
+
|
|
31
51
|
it("creates a vector Base Layer", function () {
|
|
32
|
-
const
|
|
33
|
-
name: "Albus Percival Wulfric Brian Dumbledore",
|
|
34
|
-
typ: "VectorBase",
|
|
35
|
-
gfiAttributes: "ignore",
|
|
36
|
-
id: "Rawenclaw_01"
|
|
37
|
-
},
|
|
38
|
-
layer = vectorBase.createLayer(attr);
|
|
52
|
+
const layer = vectorBase.createLayer(attr);
|
|
39
53
|
|
|
40
54
|
expect(layer).toBeInstanceOf(VectorLayer);
|
|
41
55
|
expect(layer.get("name")).toEqual("Albus Percival Wulfric Brian Dumbledore");
|
|
42
56
|
expect(layer.get("typ")).toEqual("VectorBase");
|
|
43
57
|
expect(layer.get("id")).toEqual("Rawenclaw_01");
|
|
44
58
|
});
|
|
59
|
+
it("creates a WebGLLayer, with param renderer \"webgl\"", function () {
|
|
60
|
+
const layer = vectorBase.createLayer({...attr, renderer: "webgl"});
|
|
61
|
+
|
|
62
|
+
expect(layer.constructor.name).toEqual("LocalWebGLLayer");
|
|
63
|
+
expect(layer.getSource()).toBeInstanceOf(VectorSource);
|
|
64
|
+
});
|
|
45
65
|
});
|
|
46
66
|
|
|
47
67
|
describe("updateSource", function () {
|
package/test/layer/wfs.test.js
CHANGED
|
@@ -8,6 +8,7 @@ import {WFS} from "ol/format.js";
|
|
|
8
8
|
import * as wfs from "../../src/layer/wfs";
|
|
9
9
|
import {featureCollection} from "./resources/wfsFeatures";
|
|
10
10
|
import {wfsFilterQuery} from "./resources/wfsFilter";
|
|
11
|
+
import * as webgl from "../../src/renderer/webgl.js";
|
|
11
12
|
|
|
12
13
|
jest.mock("../../src/rawLayerList.js", () => {
|
|
13
14
|
const original = jest.requireActual("../../src/rawLayerList.js");
|
|
@@ -16,6 +17,13 @@ jest.mock("../../src/rawLayerList.js", () => {
|
|
|
16
17
|
return original;
|
|
17
18
|
});
|
|
18
19
|
|
|
20
|
+
jest.mock("../../src/renderer/webgl.js", () => {
|
|
21
|
+
const original = jest.requireActual("../../src/renderer/webgl.js");
|
|
22
|
+
|
|
23
|
+
original.afterLoading = jest.fn();
|
|
24
|
+
return original;
|
|
25
|
+
});
|
|
26
|
+
|
|
19
27
|
|
|
20
28
|
describe("wfs.js", function () {
|
|
21
29
|
describe("createLayer", function () {
|
|
@@ -107,6 +115,12 @@ describe("wfs.js", function () {
|
|
|
107
115
|
expect(layer.get("name")).toEqual("name");
|
|
108
116
|
expect(layer.get("layers")).toEqual("layer1, layer2");
|
|
109
117
|
});
|
|
118
|
+
it("creates a WebGLLayer, with param renderer \"webgl\"", function () {
|
|
119
|
+
const layer = wfs.createLayer({version: "1.1.0"}, {layerParams: {renderer: "webgl"}});
|
|
120
|
+
|
|
121
|
+
expect(layer.constructor.name).toEqual("LocalWebGLLayer");
|
|
122
|
+
expect(layer.getSource()).toBeInstanceOf(VectorSource);
|
|
123
|
+
});
|
|
110
124
|
});
|
|
111
125
|
describe("createLayerSource", function () {
|
|
112
126
|
const consoleError = console.error;
|
|
@@ -383,6 +397,22 @@ describe("wfs.js", function () {
|
|
|
383
397
|
expect(afterLoadingMock.mock.calls.length).toBe(1);
|
|
384
398
|
});
|
|
385
399
|
});
|
|
400
|
+
it("creates a vectorSource with an additional listener, when renderer is \"webgl\"", () => {
|
|
401
|
+
const
|
|
402
|
+
url = "https://url.de",
|
|
403
|
+
rawLayer = {
|
|
404
|
+
id: "id",
|
|
405
|
+
url: url,
|
|
406
|
+
featureNS: "http://www.deegree.org/app",
|
|
407
|
+
featureType: "krankenhaeuser_hh",
|
|
408
|
+
version: "1.0.0"
|
|
409
|
+
},
|
|
410
|
+
source = wfs.createLayerSource({...rawLayer, renderer: "webgl"});
|
|
411
|
+
|
|
412
|
+
expect(source.getListeners("featuresloadend")).toHaveLength(1);
|
|
413
|
+
source.getListeners("featuresloadend")[0]({features: []});
|
|
414
|
+
expect(webgl.afterLoading).toHaveBeenCalled();
|
|
415
|
+
});
|
|
386
416
|
});
|
|
387
417
|
});
|
|
388
418
|
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import {mapAttributes, isObjectPath} from "../../src/lib/attributeMapper";
|
|
2
|
+
|
|
3
|
+
const props = {
|
|
4
|
+
random_text: "foobar",
|
|
5
|
+
random_boolean: true,
|
|
6
|
+
random_int: 12345,
|
|
7
|
+
random_float: 1.23,
|
|
8
|
+
random_date: "2021-11-17 13:02:00 UTC",
|
|
9
|
+
random_datastreams: [
|
|
10
|
+
{
|
|
11
|
+
Observations: [
|
|
12
|
+
{
|
|
13
|
+
result: 123
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
Observations: [
|
|
19
|
+
{
|
|
20
|
+
result: 456
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
describe("src/utils/attributeMapper.js", () => {
|
|
28
|
+
describe("mapAttributes", () => {
|
|
29
|
+
it("should map object with single attribute", () => {
|
|
30
|
+
const mappingObj = {
|
|
31
|
+
random_text: "text"
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
35
|
+
text: "foobar"
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
it("should map object with single attribute and objectpath", () => {
|
|
39
|
+
const mappingObj = {
|
|
40
|
+
"@random_text": "text"
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
44
|
+
text: "foobar"
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
it("should map object with single attribute and nested objectpath", () => {
|
|
48
|
+
const mappingObj = {
|
|
49
|
+
"@random_datastreams.0.Observations.0.result": "result"
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
53
|
+
result: 123
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
it("should map object with multiple attributes", () => {
|
|
57
|
+
const mappingObj = {
|
|
58
|
+
random_text: "text",
|
|
59
|
+
random_boolean: "boolean"
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
63
|
+
text: "foobar",
|
|
64
|
+
boolean: true
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
it("should map object with multiple attributes with nested objectpath", () => {
|
|
68
|
+
const mappingObj = {
|
|
69
|
+
random_text: "text",
|
|
70
|
+
random_boolean: "boolean",
|
|
71
|
+
"@random_datastreams.0.Observations.0.result": "result"
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
75
|
+
text: "foobar",
|
|
76
|
+
boolean: true,
|
|
77
|
+
result: 123
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
it("should map object with mapping object and condition:endsWith", () => {
|
|
81
|
+
const mappingObj = {
|
|
82
|
+
random_text: {
|
|
83
|
+
name: "text",
|
|
84
|
+
condition: "endsWith"
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
89
|
+
text: "foobar"
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
it("should map object with mapping object and condition:startsWith", () => {
|
|
93
|
+
const mappingObj = {
|
|
94
|
+
random_text: {
|
|
95
|
+
name: "text",
|
|
96
|
+
condition: "startsWith"
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
101
|
+
text: "foobar"
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
it("should map object with mapping object and condition:contains", () => {
|
|
105
|
+
const mappingObj = {
|
|
106
|
+
random_text: {
|
|
107
|
+
name: "text",
|
|
108
|
+
condition: "contains"
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
113
|
+
text: "foobar"
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
it("should map object with mapping object and suffix", () => {
|
|
117
|
+
const mappingObj = {
|
|
118
|
+
random_text: {
|
|
119
|
+
name: "text",
|
|
120
|
+
condition: "contains",
|
|
121
|
+
suffix: "barfoo"
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
126
|
+
text: "foobar barfoo"
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
it("should map object with mapping object and prefix", () => {
|
|
130
|
+
const mappingObj = {
|
|
131
|
+
random_text: {
|
|
132
|
+
name: "text",
|
|
133
|
+
condition: "contains",
|
|
134
|
+
prefix: "barfoo"
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
139
|
+
text: "barfoofoobar"
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
it("should map object with mapping object and type:date", () => {
|
|
143
|
+
const mappingObj = {
|
|
144
|
+
random_date: {
|
|
145
|
+
name: "date",
|
|
146
|
+
condition: "contains",
|
|
147
|
+
type: "date"
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
152
|
+
date: "2021-11-17T13:02:00.000+01:00"
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
it("should map object with mapping object and type:date and format:YYYY-MM-DD", () => {
|
|
156
|
+
const mappingObj = {
|
|
157
|
+
random_date: {
|
|
158
|
+
name: "date",
|
|
159
|
+
condition: "contains",
|
|
160
|
+
type: "date",
|
|
161
|
+
format: "YYYY-MM-DD"
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
166
|
+
date: "2021-11-17"
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
it("should map object with mapping object and type:date and format:DD-MM-YYYYf", () => {
|
|
170
|
+
const mappingObj = {
|
|
171
|
+
random_date: {
|
|
172
|
+
name: "date",
|
|
173
|
+
condition: "contains",
|
|
174
|
+
type: "date",
|
|
175
|
+
format: "DD-MM-YYYY"
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
180
|
+
date: "17-11-2021"
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
it("should map object with mapping object (random_int) and type:number", () => {
|
|
184
|
+
const mappingObj = {
|
|
185
|
+
random_int: {
|
|
186
|
+
name: "integer",
|
|
187
|
+
condition: "contains",
|
|
188
|
+
type: "number"
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
193
|
+
integer: "12.345"
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
it("should map object with mapping object (random_float) and type:number", () => {
|
|
197
|
+
const mappingObj = {
|
|
198
|
+
random_float: {
|
|
199
|
+
name: "float",
|
|
200
|
+
condition: "contains",
|
|
201
|
+
type: "number"
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
206
|
+
float: "1,23"
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
it("should map object with mapping object and type:boolean", () => {
|
|
210
|
+
const mappingObj = {
|
|
211
|
+
random_boolean: {
|
|
212
|
+
name: "boolean",
|
|
213
|
+
condition: "contains",
|
|
214
|
+
type: "boolean"
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
219
|
+
boolean: "true"
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
it("should map object with mapping object and type:boolean and format", () => {
|
|
223
|
+
const mappingObj = {
|
|
224
|
+
random_boolean: {
|
|
225
|
+
name: "boolean",
|
|
226
|
+
condition: "contains",
|
|
227
|
+
type: "boolean",
|
|
228
|
+
format: {
|
|
229
|
+
true: "Ja",
|
|
230
|
+
false: "Nein"
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
236
|
+
boolean: "Ja"
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
it("should map object with mapping object and type:boolean and format with i18next", () => {
|
|
240
|
+
const mappingObj = {
|
|
241
|
+
random_boolean: {
|
|
242
|
+
name: "boolean",
|
|
243
|
+
condition: "contains",
|
|
244
|
+
type: "boolean",
|
|
245
|
+
format: {
|
|
246
|
+
true: "common:modules.tools.gfi.boolean.yes",
|
|
247
|
+
false: "common:modules.tools.gfi.boolean.no"
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
// i18next only returns the path.
|
|
253
|
+
// Propably mocking of language-file would get the right translated value?
|
|
254
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
255
|
+
boolean: "common:modules.tools.gfi.boolean.yes"
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
it("should map object with mapping object and no type (defaults to string)", () => {
|
|
259
|
+
const mappingObj = {
|
|
260
|
+
random_boolean: {
|
|
261
|
+
name: "boolean",
|
|
262
|
+
condition: "contains"
|
|
263
|
+
},
|
|
264
|
+
random_int: {
|
|
265
|
+
name: "int",
|
|
266
|
+
condition: "contains"
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
expect(mapAttributes(props, mappingObj)).toEqual({
|
|
271
|
+
boolean: "true",
|
|
272
|
+
int: "12345"
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
describe("isObjectPath", () => {
|
|
277
|
+
it("should return true for \"@foobar\"", () => {
|
|
278
|
+
expect(isObjectPath("@foobar")).toBe(true);
|
|
279
|
+
});
|
|
280
|
+
it("should return false for \"foobar\"", () => {
|
|
281
|
+
expect(isObjectPath("foobar")).toBe(false);
|
|
282
|
+
});
|
|
283
|
+
it("should return false for 1", () => {
|
|
284
|
+
expect(isObjectPath(1)).toBe(false);
|
|
285
|
+
});
|
|
286
|
+
it("should return false for true", () => {
|
|
287
|
+
expect(isObjectPath(true)).toBe(false);
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
});
|