Skip to content

Commit 8f89f27

Browse files
fix(wizards/conductingequipment): on create earth switch add missing ground cNode (openscd#753)
1 parent 2f0bad9 commit 8f89f27

File tree

3 files changed

+205
-8
lines changed

3 files changed

+205
-8
lines changed

src/wizards/conductingequipment.ts

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -248,13 +248,36 @@ export function createAction(parent: Element): WizardActor {
248248
desc,
249249
});
250250

251-
if (proxyType === 'ERS')
252-
element.appendChild(
253-
createElement(parent.ownerDocument, 'Terminal', {
254-
name: 'T1',
255-
cNodeName: 'grounded',
256-
})
257-
);
251+
if (proxyType !== 'ERS') return [{ new: { parent, element } }];
252+
253+
const groundNode = parent
254+
.closest('VoltageLevel')
255+
?.querySelector('ConnectivityNode[name="grounded"]');
256+
257+
const substationName = groundNode
258+
? groundNode.closest('Substation')?.getAttribute('name') ?? null
259+
: parent.closest('Substation')?.getAttribute('name') ?? null;
260+
const voltageLevelName = groundNode
261+
? groundNode.closest('VoltageLevel')?.getAttribute('name') ?? null
262+
: parent.closest('VoltageLevel')?.getAttribute('name') ?? null;
263+
const bayName = groundNode
264+
? groundNode.closest('Bay')?.getAttribute('name') ?? null
265+
: parent.closest('Bay')?.getAttribute('name') ?? null;
266+
const connectivityNode =
267+
bayName && voltageLevelName && substationName
268+
? substationName + '/' + voltageLevelName + '/' + bayName + '/grounded'
269+
: null;
270+
271+
element.appendChild(
272+
createElement(parent.ownerDocument, 'Terminal', {
273+
name: 'T1',
274+
cNodeName: 'grounded',
275+
substationName,
276+
voltageLevelName,
277+
bayName,
278+
connectivityNode,
279+
})
280+
);
258281

259282
const action = {
260283
new: {
@@ -263,7 +286,25 @@ export function createAction(parent: Element): WizardActor {
263286
},
264287
};
265288

266-
return [action];
289+
if (groundNode) return [action];
290+
291+
const cNodeElement = createElement(
292+
parent.ownerDocument,
293+
'ConnectivityNode',
294+
{
295+
name: 'grounded',
296+
pathName: connectivityNode,
297+
}
298+
);
299+
300+
const cNodeAction = {
301+
new: {
302+
parent,
303+
element: cNodeElement,
304+
},
305+
};
306+
307+
return [action, cNodeAction];
267308
};
268309
}
269310

test/testfiles/valid2007B.scd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
<Terminal connectivityNode="AA1/E1/COUPLING_BAY/grounded" name="T1" substationName="AA1" voltageLevelName="E1" bayName="COUPLING_BAY" cNodeName="grounded"/>
2626
</ConductingEquipment>
2727
<ConnectivityNode pathName="AA1/E1/COUPLING_BAY/L2" name="L2"/>
28+
<ConnectivityNode pathName="AA1/E1/COUPLING_BAY/grounded" name="grounded"/>
2829
</Bay>
2930
<Bay name="Bay2" desc="Bay2">
3031
</Bay>
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import { expect, fixture, html } from '@open-wc/testing';
2+
import { SinonSpy, spy } from 'sinon';
3+
4+
import '../../mock-wizard.js';
5+
import { MockWizard } from '../../mock-wizard.js';
6+
7+
import {
8+
Create,
9+
isCreate,
10+
WizardInputElement,
11+
} from '../../../src/foundation.js';
12+
13+
import { fetchDoc } from './test-support.js';
14+
import { createConductingEquipmentWizard } from '../../../src/wizards/conductingequipment.js';
15+
16+
describe('Wizards for SCL element ConductingEquipment', () => {
17+
let doc: XMLDocument;
18+
let element: MockWizard;
19+
let inputs: WizardInputElement[];
20+
let primaryAction: HTMLElement;
21+
22+
let actionEvent: SinonSpy;
23+
24+
describe('defines a create wizard that', () => {
25+
let parent: Element;
26+
27+
beforeEach(async () => {
28+
doc = await fetchDoc('/test/testfiles/valid2007B.scd');
29+
30+
actionEvent = spy();
31+
window.addEventListener('editor-action', actionEvent);
32+
});
33+
34+
describe('when adding an earth switch', () => {
35+
describe('with existing ground cNode in the same VoltageLevel', () => {
36+
beforeEach(async () => {
37+
parent = doc.querySelector('Bay')!;
38+
39+
element = await fixture(html`<mock-wizard></mock-wizard>`);
40+
const wizard = createConductingEquipmentWizard(parent);
41+
element.workflow.push(() => wizard);
42+
await element.requestUpdate();
43+
inputs = Array.from(element.wizardUI.inputs);
44+
45+
primaryAction = <HTMLElement>(
46+
element.wizardUI.dialog?.querySelector(
47+
'mwc-button[slot="primaryAction"]'
48+
)
49+
);
50+
});
51+
it('does not create a new ConnectivityNode', async () => {
52+
inputs[0].value = 'ERS';
53+
inputs[1].value = 'QC9';
54+
55+
await element.requestUpdate();
56+
await primaryAction.click();
57+
58+
expect(actionEvent).to.be.calledOnce;
59+
});
60+
61+
it('does set the Terminals attributes correctly', async () => {
62+
inputs[0].value = 'ERS';
63+
inputs[1].value = 'QC9';
64+
65+
await element.requestUpdate();
66+
await primaryAction.click();
67+
68+
const action = <Create>actionEvent.args[0][0].detail.action;
69+
const terminal = (<Element>action.new.element).querySelector(
70+
'Terminal'
71+
)!;
72+
expect(terminal).to.have.attribute('substationName', 'AA1');
73+
expect(terminal).to.have.attribute('voltageLevelName', 'E1');
74+
expect(terminal).to.have.attribute('bayName', 'COUPLING_BAY');
75+
expect(terminal).to.have.attribute(
76+
'connectivityNode',
77+
'AA1/E1/COUPLING_BAY/grounded'
78+
);
79+
});
80+
});
81+
82+
describe('with missing ground cNode in the same VoltageLevel', () => {
83+
beforeEach(async () => {
84+
parent = doc.querySelector('VoltageLevel[name="J1"] > Bay')!;
85+
86+
element = await fixture(html`<mock-wizard></mock-wizard>`);
87+
const wizard = createConductingEquipmentWizard(parent);
88+
element.workflow.push(() => wizard);
89+
await element.requestUpdate();
90+
inputs = Array.from(element.wizardUI.inputs);
91+
92+
primaryAction = <HTMLElement>(
93+
element.wizardUI.dialog?.querySelector(
94+
'mwc-button[slot="primaryAction"]'
95+
)
96+
);
97+
});
98+
99+
it('does create a new ConnectivityNode', async () => {
100+
inputs[0].value = 'ERS';
101+
inputs[1].value = 'QC9';
102+
103+
await element.requestUpdate();
104+
await primaryAction.click();
105+
106+
expect(actionEvent).to.be.calledTwice;
107+
expect(actionEvent.args[0][0].detail.action).to.satisfy(isCreate);
108+
109+
const action = <Create>actionEvent.args[1][0].detail.action;
110+
expect((<Element>action.new.element).tagName).to.equal(
111+
'ConnectivityNode'
112+
);
113+
});
114+
115+
it('does set the pathName of ConnectivityNode correctly', async () => {
116+
inputs[0].value = 'ERS';
117+
inputs[1].value = 'QC9';
118+
119+
await element.requestUpdate();
120+
await primaryAction.click();
121+
122+
const action = <Create>actionEvent.args[1][0].detail.action;
123+
expect(<Element>action.new.element).to.have.attribute(
124+
'pathName',
125+
'AA1/J1/Bay1/grounded'
126+
);
127+
expect(<Element>action.new.element).to.have.attribute(
128+
'name',
129+
'grounded'
130+
);
131+
});
132+
133+
it('does set the Terminals attributes correctly', async () => {
134+
inputs[0].value = 'ERS';
135+
inputs[1].value = 'QC9';
136+
137+
await element.requestUpdate();
138+
await primaryAction.click();
139+
140+
const action = <Create>actionEvent.args[0][0].detail.action;
141+
const terminal = (<Element>action.new.element).querySelector(
142+
'Terminal'
143+
)!;
144+
expect(terminal).to.have.attribute('substationName', 'AA1');
145+
expect(terminal).to.have.attribute('voltageLevelName', 'J1');
146+
expect(terminal).to.have.attribute('bayName', 'Bay1');
147+
expect(terminal).to.have.attribute(
148+
'connectivityNode',
149+
'AA1/J1/Bay1/grounded'
150+
);
151+
});
152+
});
153+
});
154+
});
155+
});

0 commit comments

Comments
 (0)