Skip to content

Commit 216226c

Browse files
fix(menu/importieds): allow import to new projects (openscd#1012)
1 parent 6e0ccf1 commit 216226c

File tree

3 files changed

+137
-35
lines changed

3 files changed

+137
-35
lines changed

src/menu/ImportIEDs.ts

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,10 @@ function hasConnectionToIed(type: Element, ied: Element): boolean {
178178
function addEnumType(
179179
ied: Element,
180180
enumType: Element,
181-
doc: Document
181+
parent: Element
182182
): SimpleAction | undefined {
183-
const existEnumType = doc.querySelector(
184-
`:root > DataTypeTemplates > EnumType[id="${enumType.getAttribute('id')}"]`
183+
const existEnumType = parent.querySelector(
184+
`EnumType[id="${enumType.getAttribute('id')}"]`
185185
);
186186

187187
if (existEnumType && enumType.isEqualNode(existEnumType)) return;
@@ -204,7 +204,7 @@ function addEnumType(
204204

205205
return {
206206
new: {
207-
parent: doc.querySelector(':root > DataTypeTemplates')!,
207+
parent,
208208
element: enumType,
209209
},
210210
};
@@ -213,10 +213,10 @@ function addEnumType(
213213
function addDAType(
214214
ied: Element,
215215
daType: Element,
216-
doc: Document
216+
parent: Element
217217
): SimpleAction | undefined {
218-
const existDAType = doc.querySelector(
219-
`:root > DataTypeTemplates > DAType[id="${daType.getAttribute('id')}"]`
218+
const existDAType = parent.querySelector(
219+
`DAType[id="${daType.getAttribute('id')}"]`
220220
);
221221

222222
if (existDAType && daType.isEqualNode(existDAType)) return;
@@ -239,7 +239,7 @@ function addDAType(
239239

240240
return {
241241
new: {
242-
parent: doc.querySelector(':root > DataTypeTemplates')!,
242+
parent,
243243
element: daType,
244244
},
245245
};
@@ -248,10 +248,10 @@ function addDAType(
248248
function addDOType(
249249
ied: Element,
250250
doType: Element,
251-
doc: Document
251+
parent: Element
252252
): SimpleAction | undefined {
253-
const existDOType = doc.querySelector(
254-
`:root > DataTypeTemplates > DOType[id="${doType.getAttribute('id')}"]`
253+
const existDOType = parent.querySelector(
254+
`DOType[id="${doType.getAttribute('id')}"]`
255255
);
256256

257257
if (existDOType && doType.isEqualNode(existDOType)) return;
@@ -274,7 +274,7 @@ function addDOType(
274274

275275
return {
276276
new: {
277-
parent: doc.querySelector(':root > DataTypeTemplates')!,
277+
parent,
278278
element: doType,
279279
},
280280
};
@@ -283,12 +283,10 @@ function addDOType(
283283
function addLNodeType(
284284
ied: Element,
285285
lNodeType: Element,
286-
doc: Document
286+
parent: Element
287287
): SimpleAction | undefined {
288-
const existLNodeType = doc.querySelector(
289-
`:root > DataTypeTemplates > LNodeType[id="${lNodeType.getAttribute(
290-
'id'
291-
)}"]`
288+
const existLNodeType = parent.querySelector(
289+
`LNodeType[id="${lNodeType.getAttribute('id')}"]`
292290
);
293291

294292
if (existLNodeType && lNodeType.isEqualNode(existLNodeType)) return;
@@ -310,7 +308,7 @@ function addLNodeType(
310308

311309
return {
312310
new: {
313-
parent: doc.querySelector(':root > DataTypeTemplates')!,
311+
parent,
314312
element: lNodeType,
315313
},
316314
};
@@ -319,21 +317,42 @@ function addLNodeType(
319317
function addDataTypeTemplates(ied: Element, doc: XMLDocument): SimpleAction[] {
320318
const actions: (SimpleAction | undefined)[] = [];
321319

320+
const dataTypeTemplates = doc.querySelector(':root > DataTypeTemplates')
321+
? doc.querySelector(':root > DataTypeTemplates')!
322+
: createElement(doc, 'DataTypeTemplates', {});
323+
324+
if (!dataTypeTemplates.parentElement) {
325+
actions.push({
326+
new: {
327+
parent: doc.querySelector('SCL')!,
328+
element: dataTypeTemplates,
329+
},
330+
});
331+
}
332+
322333
ied.ownerDocument
323334
.querySelectorAll(':root > DataTypeTemplates > LNodeType')
324-
.forEach(lNodeType => actions.push(addLNodeType(ied, lNodeType, doc)));
335+
.forEach(lNodeType =>
336+
actions.push(addLNodeType(ied, lNodeType, dataTypeTemplates!))
337+
);
325338

326339
ied.ownerDocument
327340
.querySelectorAll(':root > DataTypeTemplates > DOType')
328-
.forEach(doType => actions.push(addDOType(ied, doType, doc)));
341+
.forEach(doType =>
342+
actions.push(addDOType(ied, doType, dataTypeTemplates!))
343+
);
329344

330345
ied.ownerDocument
331346
.querySelectorAll(':root > DataTypeTemplates > DAType')
332-
.forEach(daType => actions.push(addDAType(ied, daType, doc)));
347+
.forEach(daType =>
348+
actions.push(addDAType(ied, daType, dataTypeTemplates!))
349+
);
333350

334351
ied.ownerDocument
335352
.querySelectorAll(':root > DataTypeTemplates > EnumType')
336-
.forEach(enumType => actions.push(addEnumType(ied, enumType, doc)));
353+
.forEach(enumType =>
354+
actions.push(addEnumType(ied, enumType, dataTypeTemplates!))
355+
);
337356

338357
return <SimpleAction[]>actions.filter(item => item !== undefined);
339358
}
@@ -459,19 +478,6 @@ export default class ImportingIedPlugin extends LitElement {
459478
return;
460479
}
461480

462-
if (!doc.querySelector(':root > DataTypeTemplates')) {
463-
const element = createElement(doc, 'DataTypeTemplates', {});
464-
465-
this.parent.dispatchEvent(
466-
newActionEvent({
467-
new: {
468-
parent: doc.documentElement,
469-
element,
470-
},
471-
})
472-
);
473-
}
474-
475481
if (ieds.length === 1) {
476482
importIED(ieds[0], doc, this.parent);
477483
return;

test/integration/editors/triggered/ImportIedsPlugin.test.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,92 @@ import ImportingIedPlugin from '../../../../src/menu/ImportIEDs.js';
1313
describe('ImportIedsPlugin', () => {
1414
customElements.define('import-ieds-plugin', ImportingIedPlugin);
1515

16+
describe('imports valid ied elements to empty projects', () => {
17+
let doc: XMLDocument;
18+
let importDoc: XMLDocument;
19+
20+
let parent: MockWizardEditor;
21+
let element: ImportingIedPlugin;
22+
23+
beforeEach(async () => {
24+
parent = await fixture(
25+
html`<mock-wizard-editor
26+
><import-ieds-plugin></import-ieds-plugin
27+
></mock-wizard-editor>`
28+
);
29+
30+
element = <ImportingIedPlugin>parent.querySelector('import-ieds-plugin')!;
31+
32+
doc = await fetch('/test/testfiles/importieds/emptyproject.scd')
33+
.then(response => response.text())
34+
.then(str => new DOMParser().parseFromString(str, 'application/xml'));
35+
element.doc = doc;
36+
await element.updateComplete;
37+
38+
importDoc = await fetch('/test/testfiles/importieds/valid.iid')
39+
.then(response => response.text())
40+
.then(str => new DOMParser().parseFromString(str, 'application/xml'));
41+
});
42+
43+
it('loads ied element to the project', async () => {
44+
expect(element.doc?.querySelector(':root > IED[name="TestImportIED"]')).to
45+
.not.exist;
46+
element.prepareImport(importDoc, doc);
47+
await element.updateComplete;
48+
expect(element.doc?.querySelector(':root > IED[name="TestImportIED"]')).to
49+
.exist;
50+
});
51+
52+
it('adds the connectedap of the imported ied', async () => {
53+
element.prepareImport(importDoc, doc);
54+
await element.updateComplete;
55+
expect(
56+
element.doc.querySelector(
57+
'SubNetwork[name="NewSubNetwork"] > ConnectedAP[iedName="TestImportIED"]'
58+
)
59+
).to.exist;
60+
});
61+
62+
it('creates new subnetwork if not present in the doc', () => {
63+
expect(element.doc.querySelector('SubNetwork[name="NewSubNetwork"]')).to
64+
.not.exist;
65+
element.prepareImport(importDoc, doc);
66+
expect(element.doc.querySelector('SubNetwork[name="NewSubNetwork"]')).to
67+
.exist;
68+
});
69+
70+
it('allows multiple import of TEMPLATE IEDs', async () => {
71+
const templateIED1 = await fetch(
72+
'/test/testfiles/importieds/template.icd'
73+
)
74+
.then(response => response.text())
75+
.then(str => new DOMParser().parseFromString(str, 'application/xml'));
76+
element.prepareImport(templateIED1, doc);
77+
78+
const templateIED2 = await fetch(
79+
'/test/testfiles/importieds/template.icd'
80+
)
81+
.then(response => response.text())
82+
.then(str => new DOMParser().parseFromString(str, 'application/xml'));
83+
element.prepareImport(templateIED2, doc);
84+
85+
expect(element.doc.querySelector('IED[name="TEMPLATE_IED1"]')).to.exist;
86+
expect(element.doc.querySelector('IED[name="TEMPLATE_IED2"]')).to.exist;
87+
});
88+
89+
it('loads unique lnodetypes to the project', () => {
90+
expect(
91+
element.doc?.querySelectorAll(':root > DataTypeTemplates > LNodeType')
92+
.length
93+
).to.equal(0);
94+
element.prepareImport(importDoc, doc);
95+
expect(
96+
element.doc?.querySelectorAll(':root > DataTypeTemplates > LNodeType')
97+
.length
98+
).to.equal(5);
99+
});
100+
});
101+
16102
describe('imports valid ied elements', () => {
17103
let doc: XMLDocument;
18104
let importDoc: XMLDocument;
@@ -83,6 +169,7 @@ describe('ImportIedsPlugin', () => {
83169
.length
84170
).to.equal(11);
85171
});
172+
86173
it('loads unique enumtypes to the project', () => {
87174
expect(
88175
element.doc?.querySelectorAll(':root > DataTypeTemplates > EnumType')
@@ -94,6 +181,7 @@ describe('ImportIedsPlugin', () => {
94181
.length
95182
).to.equal(10);
96183
});
184+
97185
it('adds the connectedap of the imported ied', () => {
98186
expect(element.doc.querySelector('ConnectedAP[iedName="TestImportIED"]'))
99187
.to.not.exist;
@@ -105,13 +193,15 @@ describe('ImportIedsPlugin', () => {
105193
?.parentElement
106194
).to.equal(element.doc.querySelector('SubNetwork[name="NewSubNetwork"]'));
107195
});
196+
108197
it('creates new subnetwork if not present in the doc', () => {
109198
expect(element.doc.querySelector('SubNetwork[name="NewSubNetwork"]')).to
110199
.not.exist;
111200
element.prepareImport(importDoc, doc);
112201
expect(element.doc.querySelector('SubNetwork[name="NewSubNetwork"]')).to
113202
.exist;
114203
});
204+
115205
it('allows multiple import of TEMPLATE IEDs', async () => {
116206
expect(element.doc.querySelectorAll('IED').length).to.equal(3);
117207

@@ -132,6 +222,7 @@ describe('ImportIedsPlugin', () => {
132222
expect(element.doc.querySelector('IED[name="TEMPLATE_IED1"]')).to.exist;
133223
expect(element.doc.querySelector('IED[name="TEMPLATE_IED2"]')).to.exist;
134224
});
225+
135226
it('renders wizard for files containing more than one IED', async () => {
136227
const multipleIedDoc = await fetch(
137228
'/test/testfiles/importieds/multipleied.scd'
@@ -147,6 +238,7 @@ describe('ImportIedsPlugin', () => {
147238
parent.wizardUI.dialog?.querySelectorAll('mwc-check-list-item').length
148239
).to.equal(3);
149240
});
241+
150242
it('imports selected IED from Import IED wizard', async () => {
151243
const multipleIedDoc = await fetch(
152244
'/test/testfiles/importieds/multipleied.scd'
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<SCL xmlns="http://www.iec.ch/61850/2003/SCL" version="2007" revision="B" release="4">
3+
<Header id="TestIID"/>
4+
</SCL>

0 commit comments

Comments
 (0)