Skip to content

Commit 94726b8

Browse files
committed
implement link intersection tests using readConnectedLinks attribute reader [00466eb]
Signed-off-by: Tim Deubler <tim.deubler@here.com>
1 parent 00466eb commit 94726b8

File tree

5 files changed

+214
-6
lines changed

5 files changed

+214
-6
lines changed

packages/tests/rollup.config.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ module.exports = function(config) {
5656
'displayUtils',
5757
'editorUtils',
5858
'utils',
59-
'triggerEvents'
59+
'triggerEvents',
60+
'TestProvider',
61+
'TestLocalProvider'
6062
];
6163

6264
const globals = {
@@ -68,7 +70,9 @@ module.exports = function(config) {
6870
'displayUtils': 'here.test.displayUtils',
6971
'utils': 'here.test.utils',
7072
'triggerEvents': 'here.test.events',
71-
'editorUtils': 'here.test.editorUtils'
73+
'editorUtils': 'here.test.editorUtils',
74+
'TestProvider': 'here.test.TestProvider',
75+
'TestLocalProvider': 'here.test.TestLocalProvider'
7276
};
7377

7478

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
/*
2+
* Copyright (C) 2019-2025 HERE Europe B.V.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
* License-Filename: LICENSE
18+
*/
19+
20+
import {waitForEditorReady, editorClick, submit} from 'editorUtils';
21+
import {TileLayer} from '@here/xyz-maps-core';
22+
import {TestLocalProvider} from 'TestProviders';
23+
import {Map} from '@here/xyz-maps-display';
24+
// @ts-ignore @deprecated
25+
import {Editor, features, Navlink, NavlinkShape} from '@here/xyz-maps-editor';
26+
import chaiAlmost from 'chai-almost';
27+
28+
29+
const expect = chai.expect;
30+
let editor;
31+
let display;
32+
const runIntersectionTests = (customProviderOptions = {}) => {
33+
let linkLayer;
34+
let link1;
35+
let link2;
36+
37+
before(async function() {
38+
chai.use(chaiAlmost());
39+
40+
linkLayer = new TileLayer({
41+
name: 'linkLayer',
42+
min: 14, max: 20,
43+
provider: new TestLocalProvider({
44+
editable: true,
45+
id: 'linkProvider',
46+
enforceRandomFeatureId: false,
47+
...customProviderOptions
48+
})
49+
});
50+
51+
52+
display = new Map(document.getElementById('map'), {
53+
center: {longitude: 77.47053701721183, latitude: 13.211750283939665},
54+
zoomlevel: 18,
55+
layers: [linkLayer]
56+
});
57+
editor = new Editor(display, {
58+
layers: [linkLayer]
59+
});
60+
61+
62+
await waitForEditorReady(editor);
63+
link1 = editor.addFeature(new features.Navlink('Link1', [{x: 100, y: 100}, {x: 200, y: 200}], {
64+
featureClass: 'NAVLINK',
65+
intersection: {
66+
endNode: {link: 'Link2', index: 0}
67+
}
68+
}), linkLayer);
69+
70+
link2 = editor.addFeature(new features.Navlink('Link2', [{x: 200, y: 200}, {x: 300, y: 100}], {
71+
featureClass: 'NAVLINK',
72+
intersection: {
73+
startNode: {link: 'Link1', index: 1}
74+
}
75+
}), linkLayer);
76+
});
77+
78+
it('link1: validate simple intersection', async function() {
79+
let connectedLinks1Start = link1.getConnectedLinks(0);
80+
let connectedLinks1End = link1.getConnectedLinks(1);
81+
82+
expect(connectedLinks1Start).to.have.lengthOf(0);
83+
expect(connectedLinks1End).to.have.lengthOf(1);
84+
expect(connectedLinks1End[0].id).to.equal(link2.id);
85+
});
86+
87+
88+
it('link2: validate simple intersection', async function() {
89+
let connectedLinks2Start = link2.getConnectedLinks(0);
90+
let connectedLinks2End = link2.getConnectedLinks(1);
91+
92+
expect(connectedLinks2Start).to.have.lengthOf(1);
93+
expect(connectedLinks2End).to.have.lengthOf(0);
94+
expect(connectedLinks2Start[0].id).to.equal(link1.id);
95+
});
96+
97+
it('clear intersection - coordinates', async function() {
98+
let point = display.pixelToGeo({x: 150, y: 200});
99+
100+
link1.coord([link1.coord()[0], [point.longitude, point.latitude]]);
101+
102+
expect(link1.getConnectedLinks(0)).to.have.lengthOf(0);
103+
expect(link1.getConnectedLinks(1)).to.have.lengthOf(0);
104+
105+
expect(link2.getConnectedLinks(0)).to.have.lengthOf(0);
106+
expect(link2.getConnectedLinks(1)).to.have.lengthOf(0);
107+
});
108+
109+
it('recreate intersection', async () => {
110+
let point = display.pixelToGeo({x: 200, y: 200});
111+
link1.coord([link1.coord()[0], [point.longitude, point.latitude]]);
112+
113+
const connectedLinks1Start = link1.getConnectedLinks(0);
114+
const connectedLinks1End = link1.getConnectedLinks(1);
115+
116+
expect(connectedLinks1Start).to.have.lengthOf(0);
117+
expect(connectedLinks1End).to.have.lengthOf(1);
118+
expect(connectedLinks1End[0].id).to.equal(link2.id);
119+
120+
const connectedLinks2Start = link2.getConnectedLinks(0);
121+
const connectedLinks2End = link2.getConnectedLinks(1);
122+
123+
expect(connectedLinks2Start).to.have.lengthOf(1);
124+
expect(connectedLinks2End).to.have.lengthOf(0);
125+
expect(connectedLinks2Start[0].id).to.equal(link1.id);
126+
});
127+
128+
it('clear intersection - disconnect', async () => {
129+
link1.select();
130+
const node = <NavlinkShape>(await editorClick(editor, 200, 200)).target;
131+
132+
node.disconnect();
133+
134+
expect(link1.getConnectedLinks(0)).to.have.lengthOf(0);
135+
expect(link1.getConnectedLinks(1)).to.have.lengthOf(0);
136+
137+
expect(link2.getConnectedLinks(0)).to.have.lengthOf(0);
138+
expect(link2.getConnectedLinks(1)).to.have.lengthOf(0);
139+
});
140+
141+
return {linkLayer, link1, link2};
142+
};
143+
144+
145+
describe('link intersections - default mode', () => {
146+
runIntersectionTests({readConnectedLinks: undefined});
147+
148+
after(async function() {
149+
editor.destroy();
150+
display.destroy();
151+
});
152+
});
153+
154+
describe('link intersections - custom mode', () => {
155+
let readConnectedLinksCalls = 0;
156+
157+
runIntersectionTests({
158+
readConnectedLinks(link: Navlink, index: number) {
159+
readConnectedLinksCalls++;
160+
const connected = link.properties.intersection?.[index ? 'endNode' : 'startNode'];
161+
if (connected) {
162+
return Array.isArray(connected) ? connected : [connected];
163+
}
164+
}
165+
// writeConnectedLinks(link: Navlink, index: number, connectedLinks: {link: number|string, index: number}[]) {
166+
// const propIntersection = link.properties.intersection ||= {};
167+
// propIntersection[index ? 'endNode' : 'startNode'] = connectedLinks;
168+
// }
169+
});
170+
171+
it('validate custom reader usage', async () => {
172+
expect(readConnectedLinksCalls).to.be.greaterThan(0);
173+
});
174+
175+
it('validate unknown/invalid links are ignored', async () => {
176+
const [link1] = editor.search({id: 'Link1'}) as Navlink[];
177+
const [link2] = editor.search({id: 'Link2'}) as Navlink[];
178+
179+
let point = display.pixelToGeo({x: 200, y: 200});
180+
link1.coord([link1.coord()[0], [point.longitude, point.latitude]]);
181+
182+
link1.prop('intersection', {
183+
endNode: [{link: 'Link2', index: 0}, {link: 'UnknownLink', index: 0}]
184+
});
185+
186+
let connectedLinks1Start = link1.getConnectedLinks(0);
187+
let connectedLinks1End = link1.getConnectedLinks(1);
188+
189+
expect(connectedLinks1Start).to.have.lengthOf(0);
190+
expect(connectedLinks1End).to.have.lengthOf(1);
191+
expect(connectedLinks1End[0].id).to.equal(link2.id);
192+
});
193+
194+
after(async () => {
195+
editor.destroy();
196+
display.destroy();
197+
});
198+
});
199+

packages/tests/src/main-core.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,15 @@
2020
import * as coreUtils from './utils/coreUtils';
2121
import * as utils from './utils/utils';
2222

23+
import {TestProvider, TestLocalProvider} from './TestProvider';
24+
2325
import {run} from './runner';
2426

2527
// @ts-ignore
2628
import mochaSettings from 'settings';
2729

2830
mocha.setup(mochaSettings);
2931

30-
export default {coreUtils, utils, run};
32+
const TestProviders = {TestProvider, TestLocalProvider};
33+
export default {coreUtils, utils, TestProviders, run};
3134

packages/tests/src/main-editor.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,14 @@ import * as displayUtils from './utils/displayUtils';
2121
import * as editorUtils from './utils/editorUtils';
2222
import * as utils from './utils/utils';
2323
import * as events from './utils/triggerEvents';
24-
24+
import {TestProvider, TestLocalProvider} from './TestProvider';
2525
import {run} from './runner';
2626

2727
// @ts-ignore
2828
import mochaSettings from 'settings';
2929

3030
mocha.setup(mochaSettings);
3131

32-
export default {displayUtils, editorUtils, utils, events, run};
32+
const TestProviders = {TestProvider, TestLocalProvider};
33+
export default {displayUtils, editorUtils, utils, events, TestProviders, run};
3334

packages/tests/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"types" : ["mocha", "chai"],
88
"baseUrl": ".",
99
"paths": {
10-
"*": ["src/utils/*"]
10+
"*": ["src/utils/*"],
11+
"TestProviders": ["src/TestProvider.ts"]
1112
},
1213
"moduleResolution": "node",
1314
"resolveJsonModule": true,

0 commit comments

Comments
 (0)