Skip to content

Commit cc48b0a

Browse files
author
Dennis Labordus
authored
Fix MinTime Element order bug. (openscd#957)
1 parent 758da72 commit cc48b0a

File tree

2 files changed

+102
-61
lines changed

2 files changed

+102
-61
lines changed

src/wizards/gsecontrol.ts

Lines changed: 37 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
newSubWizardEvent,
2828
newWizardEvent,
2929
selector,
30+
SimpleAction,
3031
Wizard,
3132
WizardActor,
3233
WizardInputElement,
@@ -128,7 +129,9 @@ export function contentGseControlWizard(
128129

129130
function createGseControlAction(parent: Element): WizardActor {
130131
return (inputs: WizardInputElement[], wizard: Element) => {
131-
// create ReportControl element
132+
const actions: SimpleAction[] = [];
133+
134+
// Create ReportControl element
132135
const gseControlAttrs: Record<string, string | null> = {};
133136
const gseControlKeys = [
134137
'name',
@@ -153,52 +156,56 @@ function createGseControlAction(parent: Element): WizardActor {
153156
'GSEControl',
154157
gseControlAttrs
155158
);
159+
actions.push({ new: { parent, element: gseControl } });
156160

157-
// create GSE element with connected AccessPoint
158-
let gse: Element | null = null;
159-
let gseParent: Element | null = null;
161+
// Create GSE element with connected AccessPoint
160162
if (isAccessPointConnected(parent)) {
163+
// Get `GSE`'s ``ConnectedAP`` parent
164+
const gseParent = getConnectedAP(parent);
165+
// Create the new GSE Element.
166+
const gse = createElement(parent.ownerDocument, 'GSE', {
167+
ldInst: parent.closest('LDevice')?.getAttribute('inst') ?? '',
168+
cbName: gseControlAttrs['name']!,
169+
});
170+
actions.push({ new: { parent: gseParent!, element: gse } });
171+
172+
// Create Address Element
161173
const instType: boolean =
162174
(<Checkbox>wizard.shadowRoot?.querySelector('#instType'))?.checked ??
163175
false;
164-
165176
const gseAttrs: Record<string, string | null> = {};
166177
const gseKeys = ['MAC-Address', 'APPID', 'VLAN-ID', 'VLAN-PRIORITY'];
167178
gseKeys.forEach(key => {
168179
gseAttrs[key] = getValue(inputs.find(i => i.label === key)!);
169180
});
170-
const minTime = getValue(inputs.find(i => i.label === 'MinTime')!);
171-
const maxTime = getValue(inputs.find(i => i.label === 'MaxTime')!);
172-
173-
gse = createElement(parent.ownerDocument, 'GSE', {
174-
ldInst: parent.closest('LDevice')?.getAttribute('inst') ?? '',
175-
cbName: gseControlAttrs['name']!,
176-
});
177181
const address = createAddressElement(gseAttrs, gse, instType);
182+
actions.push({ new: { parent: gse, element: address } });
178183

179-
const MinTime = createElement(parent.ownerDocument, 'MinTime', {
184+
// Create MinTime Element
185+
const minTime = getValue(inputs.find(i => i.label === 'MinTime')!);
186+
const minTimeElement = createElement(parent.ownerDocument, 'MinTime', {
180187
unit: 's',
181188
multiplier: 'm',
182189
});
183-
MinTime.textContent = minTime;
184-
const MaxTime = createElement(parent.ownerDocument, 'MaxTime', {
190+
minTimeElement.textContent = minTime;
191+
actions.push({ new: { parent: gse, element: minTimeElement } });
192+
193+
// Create MaxTime Element
194+
const maxTime = getValue(inputs.find(i => i.label === 'MaxTime')!);
195+
const maxTimeElement = createElement(parent.ownerDocument, 'MaxTime', {
185196
unit: 's',
186197
multiplier: 'm',
187198
});
188-
MaxTime.textContent = maxTime;
189-
190-
gse.appendChild(address);
191-
gse.appendChild(MaxTime);
192-
gse.appendChild(MinTime);
193-
194-
// get `GSE`'s ``ConnectedAP`` parent
195-
gseParent = getConnectedAP(parent);
199+
maxTimeElement.textContent = maxTime;
200+
actions.push({ new: { parent: gse, element: maxTimeElement } });
196201
}
197202

198203
//add empty dataset that can be filled later
199204
const dataSet = createElement(parent.ownerDocument, 'DataSet', {
200205
name: dataSetName,
201206
});
207+
actions.push({ new: { parent, element: dataSet } });
208+
202209
const finder = wizard.shadowRoot!.querySelector<FinderList>('finder-list');
203210
const paths = finder?.paths ?? [];
204211

@@ -207,27 +214,15 @@ function createGseControlAction(parent: Element): WizardActor {
207214

208215
if (!element) continue;
209216

210-
dataSet.appendChild(element);
217+
actions.push({ new: { parent: dataSet, element } });
211218
}
212219

213-
const complexAction = gse
214-
? {
215-
title: 'Create GSEControl',
216-
actions: [
217-
{ new: { parent, element: gseControl } },
218-
{ new: { parent: gseParent!, element: gse } },
219-
{ new: { parent, element: dataSet } },
220-
],
221-
}
222-
: {
223-
title: 'Create GSEControl',
224-
actions: [
225-
{ new: { parent, element: gseControl } },
226-
{ new: { parent, element: dataSet } },
227-
],
228-
};
229-
230-
return [complexAction];
220+
return [
221+
{
222+
title: get('editing.created', { name: 'GSEControl' }),
223+
actions,
224+
},
225+
];
231226
};
232227
}
233228

test/unit/wizards/gsecontrol.test.ts

Lines changed: 65 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ import {
1919
WizardInputElement,
2020
} from '../../../src/foundation.js';
2121
import {
22+
contentGseControlWizard,
23+
createGseControlWizard,
2224
editGseControlWizard,
25+
gseControlParentSelector,
2326
removeGseControlAction,
24-
contentGseControlWizard,
2527
selectGseControlWizard,
2628
updateGseControlAction,
27-
gseControlParentSelector,
28-
createGseControlWizard,
2929
} from '../../../src/wizards/gsecontrol.js';
3030
import { regExp, regexString } from '../../foundation.js';
3131
import { FinderList } from '../../../src/finder-list.js';
@@ -413,7 +413,7 @@ describe('gsecontrol wizards', () => {
413413

414414
const actions = (<ComplexAction>actionEvent.args[0][0].detail.action)
415415
.actions;
416-
expect(actions.length).to.equal(3);
416+
expect(actions.length).to.equal(6);
417417
const action = actions[0];
418418
expect(action).to.satisfy(isCreate);
419419
const createAction = <Create>action;
@@ -427,7 +427,7 @@ describe('gsecontrol wizards', () => {
427427

428428
const actions = (<ComplexAction>actionEvent.args[0][0].detail.action)
429429
.actions;
430-
expect(actions.length).to.equal(3);
430+
expect(actions.length).to.equal(6);
431431
const action = actions[0];
432432
expect(action).to.satisfy(isCreate);
433433
const createAction = <Create>action;
@@ -439,8 +439,8 @@ describe('gsecontrol wizards', () => {
439439

440440
const actions = (<ComplexAction>actionEvent.args[0][0].detail.action)
441441
.actions;
442-
expect(actions.length).to.equal(3);
443-
const action = actions[2];
442+
expect(actions.length).to.equal(6);
443+
const action = actions[5];
444444
expect(action).to.satisfy(isCreate);
445445
const createAction = <Create>action;
446446
expect((<Element>createAction.new.element).tagName).to.equal('DataSet');
@@ -449,10 +449,17 @@ describe('gsecontrol wizards', () => {
449449
it('referenced DataSet element not having any FCDA per default', async () => {
450450
await primaryAction.click();
451451

452-
const createAction = <Create>(
453-
(<ComplexAction>actionEvent.args[0][0].detail.action).actions[2]
454-
);
455-
expect((<Element>createAction.new.element).children).to.be.empty;
452+
const actions = (<ComplexAction>actionEvent.args[0][0].detail.action)
453+
.actions;
454+
expect(actions.length).to.equal(6);
455+
456+
actions.forEach(action => {
457+
expect(action).to.satisfy(isCreate);
458+
const createAction = <Create>action;
459+
expect((<Element>createAction.new.element).tagName).to.not.equal(
460+
'FCDA'
461+
);
462+
});
456463
});
457464

458465
it('referenced DataSet element saving selected FCDA', async () => {
@@ -469,21 +476,21 @@ describe('gsecontrol wizards', () => {
469476

470477
await primaryAction.click();
471478

472-
const createAction = <Create>(
473-
(<ComplexAction>actionEvent.args[0][0].detail.action).actions[2]
474-
);
475-
expect((<Element>createAction.new.element).children).to.not.be.empty;
476-
expect((<Element>createAction.new.element).children).to.have.lengthOf(
477-
1
478-
);
479+
const actions = (<ComplexAction>actionEvent.args[0][0].detail.action)
480+
.actions;
481+
expect(actions.length).to.equal(7);
482+
const action = actions[6];
483+
expect(action).to.satisfy(isCreate);
484+
const createAction = <Create>action;
485+
expect((<Element>createAction.new.element).tagName).to.equal('FCDA');
479486
});
480487

481488
it('complex action adding GSE element in the Communication section', async () => {
482489
await primaryAction.click();
483490

484491
const actions = (<ComplexAction>actionEvent.args[0][0].detail.action)
485492
.actions;
486-
expect(actions.length).to.equal(3);
493+
expect(actions.length).to.equal(6);
487494
const action = actions[1];
488495
expect(action).to.satisfy(isCreate);
489496
const createAction = <Create>action;
@@ -533,6 +540,45 @@ describe('gsecontrol wizards', () => {
533540
expect(action).to.not.satisfy(isSimple);
534541
});
535542

543+
it('referenced DataSet element not having any FCDA per default', async () => {
544+
await primaryAction.click();
545+
546+
const actions = (<ComplexAction>actionEvent.args[0][0].detail.action)
547+
.actions;
548+
expect(actions.length).to.equal(2);
549+
550+
actions.forEach(action => {
551+
expect(action).to.satisfy(isCreate);
552+
const createAction = <Create>action;
553+
expect((<Element>createAction.new.element).tagName).to.not.equal(
554+
'FCDA'
555+
);
556+
});
557+
});
558+
559+
it('referenced DataSet element saving selected FCDA', async () => {
560+
const path = [
561+
'Server: IED4>P1',
562+
'LDevice: IED4>>MU01',
563+
'LN0: IED4>>MU01',
564+
'DO: #Dummy.LLN0.two>Beh',
565+
'DA: #Dummy.LLN0.Beh>stVal',
566+
];
567+
568+
dataPicker.paths = [path];
569+
await element.requestUpdate();
570+
571+
await primaryAction.click();
572+
573+
const actions = (<ComplexAction>actionEvent.args[0][0].detail.action)
574+
.actions;
575+
expect(actions.length).to.equal(3);
576+
const action = actions[2];
577+
expect(action).to.satisfy(isCreate);
578+
const createAction = <Create>action;
579+
expect((<Element>createAction.new.element).tagName).to.equal('FCDA');
580+
});
581+
536582
it('complex action NOT adding GSE element in the Communication section', async () => {
537583
await primaryAction.click();
538584

0 commit comments

Comments
 (0)