Skip to content

Commit e1105a8

Browse files
authored
Show validation errors (#123)
* show validation errors + tests * fix typo
1 parent 0c52fe6 commit e1105a8

File tree

2 files changed

+60
-28
lines changed

2 files changed

+60
-28
lines changed

src/building.js

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -75,29 +75,30 @@ class Building {
7575
} else {
7676
this.type = 'relation';
7777
}
78-
if (this.isValidData(outerElementXml)) {
79-
this.nodelist = Building.buildNodeList(this.fullXmlData);
80-
this.setHome();
81-
this.repositionNodes();
82-
if (this.type === 'way') {
78+
try {
79+
this.validateData(outerElementXml);
80+
} catch (e) {
81+
throw new Error(`Rendering of ${outerElementXml.tagName.toLowerCase()} ${id} is not possible. ${e}`);
82+
}
83+
84+
this.nodelist = Building.buildNodeList(this.fullXmlData);
85+
this.setHome();
86+
this.repositionNodes();
87+
if (this.type === 'way') {
88+
this.outerElement = new BuildingPart(id, this.fullXmlData, this.nodelist);
89+
} else if (this.type === 'multipolygon') {
90+
this.outerElement = new MultiBuildingPart(id, this.fullXmlData, this.nodelist);
91+
} else {
92+
const outlineRef = outerElementXml.querySelector('member[role="outline"]').getAttribute('ref');
93+
const outline = this.fullXmlData.getElementById(outlineRef);
94+
const outlineType = outline.tagName.toLowerCase();
95+
if (outlineType === 'way') {
8396
this.outerElement = new BuildingPart(id, this.fullXmlData, this.nodelist);
84-
} else if (this.type === 'multipolygon') {
85-
this.outerElement = new MultiBuildingPart(id, this.fullXmlData, this.nodelist);
8697
} else {
87-
const outlineRef = outerElementXml.querySelector('member[role="outline"]').getAttribute('ref');
88-
const outline = this.fullXmlData.getElementById(outlineRef);
89-
const outlineType = outline.tagName.toLowerCase();
90-
if (outlineType === 'way') {
91-
this.outerElement = new BuildingPart(id, this.fullXmlData, this.nodelist);
92-
} else {
93-
this.outerElement = new MultiBuildingPart(outlineRef, this.fullXmlData, this.nodelist);
94-
}
98+
this.outerElement = new MultiBuildingPart(outlineRef, this.fullXmlData, this.nodelist);
9599
}
96-
this.addParts();
97-
} else {
98-
window.printError('XML Not Valid');
99-
throw new Error('invalid XML');
100100
}
101+
this.addParts();
101102
}
102103

103104
/**
@@ -248,15 +249,15 @@ class Building {
248249
/**
249250
* validate that we have the ID of a building way.
250251
*/
251-
isValidData(xmlData) {
252+
validateData(xmlData) {
252253
// Check that it is a building (<tag k="building" v="*"/> exists)
253254
const buildingType = xmlData.querySelector('[k="building"]');
254255
const ways = [];
255256
if (xmlData.tagName === 'relation') {
256257
// get all building relation parts
257258
// todo: multipolygon inner and outer roles.
258259
let parts = xmlData.querySelectorAll('member[role="part"]');
259-
var ref = 0;
260+
let ref = 0;
260261
for (let i = 0; i < parts.length; i++) {
261262
ref = parts[i].getAttribute('ref');
262263
const part = this.fullXmlData.getElementById(ref);
@@ -268,8 +269,7 @@ class Building {
268269
}
269270
} else {
270271
if (!buildingType) {
271-
window.printError('Outer way is not a building');
272-
return false;
272+
throw new Error('Outer way is not a building');
273273
}
274274
ways.push(xmlData);
275275
}
@@ -282,16 +282,14 @@ class Building {
282282
const firstRef = nodes[0].getAttribute('ref');
283283
const lastRef = nodes[nodes.length - 1].getAttribute('ref');
284284
if (firstRef !== lastRef) {
285-
window.printError('Way ' + way.getAttribute('id') + ' is not a closed way. ' + firstRef + ' !== ' + lastRef + '.');
286-
return false;
285+
throw new Error('Way ' + way.getAttribute('id') + ' is not a closed way. ' + firstRef + ' !== ' + lastRef + '.');
287286
}
288287
} else {
289-
window.printError('Way ' + way.getAttribute('id') + ' has no nodes.');
290-
return false;
288+
throw new Error('Way ' + way.getAttribute('id') + ' has no nodes.');
291289
}
292290
} else {
293291
let parts = way.querySelectorAll('member[role="part"]');
294-
var ref = 0;
292+
let ref = 0;
295293
for (let i = 0; i < parts.length; i++) {
296294
ref = parts[i].getAttribute('ref');
297295
const part = this.fullXmlData.getElementById(ref);

test/building.test.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,40 @@ describe.each([
6060
});
6161
});
6262

63+
test('Test data validation open outline', () => {
64+
const data = `
65+
<way id="1">
66+
<nd ref="2"/>
67+
<nd ref="3"/>
68+
<nd ref="4"/>
69+
<tag k="building" v="yes"/>
70+
</way>`;
71+
expect(() => new Building('1', data))
72+
.toThrow(new Error('Rendering of way 1 is not possible. Error: Way 1 is not a closed way. 2 !== 4.'));
73+
});
74+
75+
test('Test data validation with not building', () => {
76+
const data = `
77+
<way id="1">
78+
<nd ref="2"/>
79+
<nd ref="3"/>
80+
<nd ref="4"/>
81+
<nd ref="2"/>
82+
<tag k="not:building" v="yes"/>
83+
</way>`;
84+
expect(() => new Building('1', data))
85+
.toThrow(new Error('Rendering of way 1 is not possible. Error: Outer way is not a building'));
86+
});
87+
88+
test('Test data validation with empty way', () => {
89+
const data = `
90+
<way id="1">
91+
<tag k="building" v="yes"/>
92+
</way>`;
93+
expect(() => new Building('1', data))
94+
.toThrow(new Error('Rendering of way 1 is not possible. Error: Way 1 has no nodes.'));
95+
});
96+
6397
test('Test Constructor', async() => {
6498
const bldg = new Building('31361386', data);
6599
expect(bldg.home).toBeDeepCloseTo([11.015512, 49.5833659], 10);

0 commit comments

Comments
 (0)