@omicronenergy/oscd-scl-dialogs 0.0.11 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/README.md +4 -2
- package/custom-elements.json +292 -3
- package/dist/OscdSclDialogs.d.ts +2 -0
- package/dist/OscdSclDialogs.js +62 -12
- package/dist/OscdSclDialogs.js.map +1 -1
- package/dist/wizards/dataset.d.ts +2 -0
- package/dist/wizards/dataset.js +86 -0
- package/dist/wizards/dataset.js.map +1 -0
- package/dist/wizards/dataset.spec.d.ts +1 -0
- package/dist/wizards/dataset.spec.js +240 -0
- package/dist/wizards/dataset.spec.js.map +1 -0
- package/dist/wizards/gsecontrol.d.ts +2 -0
- package/dist/wizards/gsecontrol.js +86 -0
- package/dist/wizards/gsecontrol.js.map +1 -0
- package/dist/wizards/gsecontrol.spec.d.ts +1 -0
- package/dist/wizards/gsecontrol.spec.js +216 -0
- package/dist/wizards/gsecontrol.spec.js.map +1 -0
- package/dist/wizards/lnode.d.ts +1 -0
- package/dist/wizards/lnode.js +101 -1
- package/dist/wizards/lnode.js.map +1 -1
- package/dist/wizards/patterns.d.ts +2 -0
- package/dist/wizards/patterns.js +2 -0
- package/dist/wizards/patterns.js.map +1 -1
- package/dist/wizards/sampledvaluecontrol.d.ts +2 -0
- package/dist/wizards/sampledvaluecontrol.js +115 -0
- package/dist/wizards/sampledvaluecontrol.js.map +1 -0
- package/dist/wizards/sampledvaluecontrol.spec.d.ts +1 -0
- package/dist/wizards/sampledvaluecontrol.spec.js +227 -0
- package/dist/wizards/sampledvaluecontrol.spec.js.map +1 -0
- package/dist/wizards/smvopts.d.ts +2 -0
- package/dist/wizards/smvopts.js +43 -0
- package/dist/wizards/smvopts.js.map +1 -0
- package/dist/wizards/smvopts.spec.d.ts +1 -0
- package/dist/wizards/smvopts.spec.js +193 -0
- package/dist/wizards/smvopts.spec.js.map +1 -0
- package/dist/wizards/wizards.js +16 -4
- package/dist/wizards/wizards.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import { getValue, reservedNames, } from '../foundation.js';
|
|
3
|
+
import { maxLength, tSecurityEnable, tSmpMod } from './patterns.js';
|
|
4
|
+
function render(options) {
|
|
5
|
+
const fields = [
|
|
6
|
+
html `<scl-text-field
|
|
7
|
+
label="name"
|
|
8
|
+
.value=${options.name}
|
|
9
|
+
required
|
|
10
|
+
maxLength="${maxLength.cbName}"
|
|
11
|
+
.reservedValues=${options.reservedValues}
|
|
12
|
+
dialogInitialFocus
|
|
13
|
+
></scl-text-field>`,
|
|
14
|
+
html `<scl-text-field
|
|
15
|
+
label="desc"
|
|
16
|
+
.value=${options.desc}
|
|
17
|
+
nullable
|
|
18
|
+
></scl-text-field>`,
|
|
19
|
+
html `<scl-text-field
|
|
20
|
+
label="smvID"
|
|
21
|
+
.value=${options.smvID}
|
|
22
|
+
required
|
|
23
|
+
></scl-text-field>`,
|
|
24
|
+
html `<scl-select
|
|
25
|
+
label="smpMod"
|
|
26
|
+
.selectOptions=${tSmpMod}
|
|
27
|
+
.value=${options.smpMod}
|
|
28
|
+
nullable
|
|
29
|
+
></scl-select>`,
|
|
30
|
+
html `<scl-text-field
|
|
31
|
+
label="smpRate"
|
|
32
|
+
.value=${options.smpRate}
|
|
33
|
+
required
|
|
34
|
+
type="number"
|
|
35
|
+
min="0"
|
|
36
|
+
></scl-text-field>`,
|
|
37
|
+
html `<scl-text-field
|
|
38
|
+
label="nofASDU"
|
|
39
|
+
.value=${options.nofASDU}
|
|
40
|
+
required
|
|
41
|
+
type="number"
|
|
42
|
+
min="0"
|
|
43
|
+
></scl-text-field>`,
|
|
44
|
+
html `<scl-select
|
|
45
|
+
label="securityEnabled"
|
|
46
|
+
.selectOptions=${tSecurityEnable}
|
|
47
|
+
.value=${options.securityEnabled}
|
|
48
|
+
nullable
|
|
49
|
+
></scl-select>`,
|
|
50
|
+
];
|
|
51
|
+
if (options.multicast === 'false') {
|
|
52
|
+
fields.push(html `<scl-checkbox
|
|
53
|
+
label="multicast"
|
|
54
|
+
.value=${'false'}
|
|
55
|
+
disabled
|
|
56
|
+
></scl-checkbox>`);
|
|
57
|
+
}
|
|
58
|
+
return fields;
|
|
59
|
+
}
|
|
60
|
+
function updateAction(element) {
|
|
61
|
+
return (inputs) => {
|
|
62
|
+
const name = getValue(inputs.find(i => i.label === 'name'));
|
|
63
|
+
const desc = getValue(inputs.find(i => i.label === 'desc'));
|
|
64
|
+
const smvID = getValue(inputs.find(i => i.label === 'smvID'));
|
|
65
|
+
const smpMod = getValue(inputs.find(i => i.label === 'smpMod'));
|
|
66
|
+
const smpRate = getValue(inputs.find(i => i.label === 'smpRate'));
|
|
67
|
+
const nofASDU = getValue(inputs.find(i => i.label === 'nofASDU'));
|
|
68
|
+
const securityEnabled = getValue(inputs.find(i => i.label === 'securityEnabled'));
|
|
69
|
+
if (name === element.getAttribute('name') &&
|
|
70
|
+
desc === element.getAttribute('desc') &&
|
|
71
|
+
smvID === element.getAttribute('smvID') &&
|
|
72
|
+
smpMod === element.getAttribute('smpMod') &&
|
|
73
|
+
smpRate === element.getAttribute('smpRate') &&
|
|
74
|
+
nofASDU === element.getAttribute('nofASDU') &&
|
|
75
|
+
securityEnabled === element.getAttribute('securityEnabled')) {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
return [
|
|
79
|
+
{
|
|
80
|
+
element,
|
|
81
|
+
attributes: {
|
|
82
|
+
name,
|
|
83
|
+
desc,
|
|
84
|
+
smvID,
|
|
85
|
+
smpMod,
|
|
86
|
+
smpRate,
|
|
87
|
+
nofASDU,
|
|
88
|
+
securityEnabled,
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
export function editSampledValueControlWizard(element) {
|
|
95
|
+
return {
|
|
96
|
+
title: 'Edit SampledValueControl',
|
|
97
|
+
primary: {
|
|
98
|
+
icon: 'edit',
|
|
99
|
+
label: 'save',
|
|
100
|
+
action: updateAction(element),
|
|
101
|
+
},
|
|
102
|
+
content: render({
|
|
103
|
+
name: element.getAttribute('name') ?? '',
|
|
104
|
+
reservedValues: reservedNames(element),
|
|
105
|
+
desc: element.getAttribute('desc'),
|
|
106
|
+
smvID: element.getAttribute('smvID') ?? '',
|
|
107
|
+
smpMod: element.getAttribute('smpMod'),
|
|
108
|
+
smpRate: element.getAttribute('smpRate') ?? '',
|
|
109
|
+
nofASDU: element.getAttribute('nofASDU') ?? '',
|
|
110
|
+
securityEnabled: element.getAttribute('securityEnabled'),
|
|
111
|
+
multicast: element.getAttribute('multicast'),
|
|
112
|
+
}),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=sampledvaluecontrol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sampledvaluecontrol.js","sourceRoot":"","sources":["../../wizards/sampledvaluecontrol.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, TemplateResult } from 'lit';\n\nimport { EditV2 } from '@openscd/oscd-api';\n\nimport {\n getValue,\n reservedNames,\n Wizard,\n WizardActor,\n WizardInputElement,\n} from '../foundation.js';\nimport { maxLength, tSecurityEnable, tSmpMod } from './patterns.js';\n\ntype RenderOptions = {\n name: string;\n reservedValues: string[];\n desc: string | null;\n smvID: string;\n smpMod: string | null;\n smpRate: string;\n nofASDU: string;\n securityEnabled: string | null;\n multicast: string | null;\n};\n\nfunction render(options: RenderOptions): TemplateResult[] {\n const fields: TemplateResult[] = [\n html`<scl-text-field\n label=\"name\"\n .value=${options.name}\n required\n maxLength=\"${maxLength.cbName}\"\n .reservedValues=${options.reservedValues}\n dialogInitialFocus\n ></scl-text-field>`,\n html`<scl-text-field\n label=\"desc\"\n .value=${options.desc}\n nullable\n ></scl-text-field>`,\n html`<scl-text-field\n label=\"smvID\"\n .value=${options.smvID}\n required\n ></scl-text-field>`,\n html`<scl-select\n label=\"smpMod\"\n .selectOptions=${tSmpMod}\n .value=${options.smpMod}\n nullable\n ></scl-select>`,\n html`<scl-text-field\n label=\"smpRate\"\n .value=${options.smpRate}\n required\n type=\"number\"\n min=\"0\"\n ></scl-text-field>`,\n html`<scl-text-field\n label=\"nofASDU\"\n .value=${options.nofASDU}\n required\n type=\"number\"\n min=\"0\"\n ></scl-text-field>`,\n html`<scl-select\n label=\"securityEnabled\"\n .selectOptions=${tSecurityEnable}\n .value=${options.securityEnabled}\n nullable\n ></scl-select>`,\n ];\n\n if (options.multicast === 'false') {\n fields.push(\n html`<scl-checkbox\n label=\"multicast\"\n .value=${'false'}\n disabled\n ></scl-checkbox>`,\n );\n }\n\n return fields;\n}\n\nfunction updateAction(element: Element): WizardActor {\n return (inputs: WizardInputElement[]): EditV2[] => {\n const name = getValue(inputs.find(i => i.label === 'name')!)!;\n const desc = getValue(inputs.find(i => i.label === 'desc')!);\n const smvID = getValue(inputs.find(i => i.label === 'smvID')!)!;\n const smpMod = getValue(inputs.find(i => i.label === 'smpMod')!);\n const smpRate = getValue(inputs.find(i => i.label === 'smpRate')!)!;\n const nofASDU = getValue(inputs.find(i => i.label === 'nofASDU')!)!;\n const securityEnabled = getValue(\n inputs.find(i => i.label === 'securityEnabled')!,\n );\n\n if (\n name === element.getAttribute('name') &&\n desc === element.getAttribute('desc') &&\n smvID === element.getAttribute('smvID') &&\n smpMod === element.getAttribute('smpMod') &&\n smpRate === element.getAttribute('smpRate') &&\n nofASDU === element.getAttribute('nofASDU') &&\n securityEnabled === element.getAttribute('securityEnabled')\n ) {\n return [];\n }\n\n return [\n {\n element,\n attributes: {\n name,\n desc,\n smvID,\n smpMod,\n smpRate,\n nofASDU,\n securityEnabled,\n },\n },\n ];\n };\n}\n\nexport function editSampledValueControlWizard(element: Element): Wizard {\n return {\n title: 'Edit SampledValueControl',\n primary: {\n icon: 'edit',\n label: 'save',\n action: updateAction(element),\n },\n content: render({\n name: element.getAttribute('name') ?? '',\n reservedValues: reservedNames(element),\n desc: element.getAttribute('desc'),\n smvID: element.getAttribute('smvID') ?? '',\n smpMod: element.getAttribute('smpMod'),\n smpRate: element.getAttribute('smpRate') ?? '',\n nofASDU: element.getAttribute('nofASDU') ?? '',\n securityEnabled: element.getAttribute('securityEnabled'),\n multicast: element.getAttribute('multicast'),\n }),\n };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
|
2
|
+
import { expect, fixture } from '@open-wc/testing';
|
|
3
|
+
import { html } from 'lit';
|
|
4
|
+
import { editSampledValueControlWizard } from './sampledvaluecontrol.js';
|
|
5
|
+
import { XMLEditor } from '@openscd/oscd-editor';
|
|
6
|
+
import { SclTextField } from '@openenergytools/scl-text-field';
|
|
7
|
+
import { SclSelect } from '@openenergytools/scl-select';
|
|
8
|
+
import { SclCheckbox } from '@openenergytools/scl-checkbox';
|
|
9
|
+
if (!customElements.get('scl-text-field')) {
|
|
10
|
+
customElements.define('scl-text-field', SclTextField);
|
|
11
|
+
}
|
|
12
|
+
if (!customElements.get('scl-select')) {
|
|
13
|
+
customElements.define('scl-select', SclSelect);
|
|
14
|
+
}
|
|
15
|
+
if (!customElements.get('scl-checkbox')) {
|
|
16
|
+
customElements.define('scl-checkbox', SclCheckbox);
|
|
17
|
+
}
|
|
18
|
+
const xmlParser = new DOMParser();
|
|
19
|
+
function createSclDoc(multicast) {
|
|
20
|
+
const multicastAttr = multicast !== undefined ? `multicast="${multicast}"` : '';
|
|
21
|
+
return xmlParser.parseFromString(`
|
|
22
|
+
<SCL xmlns="http://www.iec.ch/61850/2003/SCL">
|
|
23
|
+
<IED name="IED1">
|
|
24
|
+
<AccessPoint name="AP1">
|
|
25
|
+
<Server>
|
|
26
|
+
<LDevice inst="LD1">
|
|
27
|
+
<LN0 lnClass="LLN0" inst="" lnType="LLN0_Type">
|
|
28
|
+
<SampledValueControl name="SVC1" desc="SV control 1" smvID="SV_ID1" smpMod="SmpPerPeriod" smpRate="80" nofASDU="1" securityEnabled="None" ${multicastAttr} datSet="ds1" confRev="1" />
|
|
29
|
+
<SampledValueControl name="SVC2" smvID="SV_ID2" smpRate="256" nofASDU="2" />
|
|
30
|
+
</LN0>
|
|
31
|
+
</LDevice>
|
|
32
|
+
</Server>
|
|
33
|
+
</AccessPoint>
|
|
34
|
+
</IED>
|
|
35
|
+
</SCL>
|
|
36
|
+
`, 'application/xml');
|
|
37
|
+
}
|
|
38
|
+
async function renderContent(wizard) {
|
|
39
|
+
const content = await fixture(html `<form>${wizard.content}</form>`);
|
|
40
|
+
const nameField = content.querySelector('scl-text-field[label="name"]');
|
|
41
|
+
const descField = content.querySelector('scl-text-field[label="desc"]');
|
|
42
|
+
const smvIDField = content.querySelector('scl-text-field[label="smvID"]');
|
|
43
|
+
const smpModField = content.querySelector('scl-select[label="smpMod"]');
|
|
44
|
+
const smpRateField = content.querySelector('scl-text-field[label="smpRate"]');
|
|
45
|
+
const nofASDUField = content.querySelector('scl-text-field[label="nofASDU"]');
|
|
46
|
+
const securityEnabledField = content.querySelector('scl-select[label="securityEnabled"]');
|
|
47
|
+
const multicastField = content.querySelector('scl-checkbox[label="multicast"]');
|
|
48
|
+
expect(nameField).to.exist;
|
|
49
|
+
expect(descField).to.exist;
|
|
50
|
+
expect(smvIDField).to.exist;
|
|
51
|
+
expect(smpModField).to.exist;
|
|
52
|
+
expect(smpRateField).to.exist;
|
|
53
|
+
expect(nofASDUField).to.exist;
|
|
54
|
+
expect(securityEnabledField).to.exist;
|
|
55
|
+
return {
|
|
56
|
+
content,
|
|
57
|
+
nameField,
|
|
58
|
+
descField,
|
|
59
|
+
smvIDField,
|
|
60
|
+
smpModField,
|
|
61
|
+
smpRateField,
|
|
62
|
+
nofASDUField,
|
|
63
|
+
securityEnabledField,
|
|
64
|
+
multicastField,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
describe('SampledValueControl edit wizard', () => {
|
|
68
|
+
let xmlEditor;
|
|
69
|
+
let renderedContainer;
|
|
70
|
+
beforeEach(() => {
|
|
71
|
+
xmlEditor = new XMLEditor();
|
|
72
|
+
});
|
|
73
|
+
afterEach(() => {
|
|
74
|
+
if (renderedContainer) {
|
|
75
|
+
renderedContainer.remove();
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
it('returns a wizard with correct title and 7 fields (multicast true/absent)', () => {
|
|
79
|
+
const scl = createSclDoc();
|
|
80
|
+
const element = scl.querySelector('SampledValueControl[name="SVC1"]');
|
|
81
|
+
const wizard = editSampledValueControlWizard(element);
|
|
82
|
+
expect(wizard.title).to.equal('Edit SampledValueControl');
|
|
83
|
+
expect(wizard.primary).to.exist;
|
|
84
|
+
expect(wizard.primary.icon).to.equal('edit');
|
|
85
|
+
expect(wizard.primary.label).to.equal('save');
|
|
86
|
+
// 7 fields: name, desc, smvID, smpMod, smpRate, nofASDU, securityEnabled
|
|
87
|
+
// No multicast field when multicast is absent (defaults to true)
|
|
88
|
+
expect(wizard.content).to.have.lengthOf(7);
|
|
89
|
+
});
|
|
90
|
+
it('shows 8 fields with disabled multicast checkbox when multicast is false', () => {
|
|
91
|
+
const scl = createSclDoc('false');
|
|
92
|
+
const element = scl.querySelector('SampledValueControl[name="SVC1"]');
|
|
93
|
+
const wizard = editSampledValueControlWizard(element);
|
|
94
|
+
expect(wizard.content).to.have.lengthOf(8);
|
|
95
|
+
});
|
|
96
|
+
it('does not show multicast field when multicast is true', () => {
|
|
97
|
+
const scl = createSclDoc('true');
|
|
98
|
+
const element = scl.querySelector('SampledValueControl[name="SVC1"]');
|
|
99
|
+
const wizard = editSampledValueControlWizard(element);
|
|
100
|
+
// 7 fields — no multicast
|
|
101
|
+
expect(wizard.content).to.have.lengthOf(7);
|
|
102
|
+
});
|
|
103
|
+
it('populates fields with current attribute values', async () => {
|
|
104
|
+
const scl = createSclDoc();
|
|
105
|
+
const element = scl.querySelector('SampledValueControl[name="SVC1"]');
|
|
106
|
+
const wizard = editSampledValueControlWizard(element);
|
|
107
|
+
const fields = await renderContent(wizard);
|
|
108
|
+
renderedContainer = fields.content;
|
|
109
|
+
expect(fields.nameField.value).to.equal('SVC1');
|
|
110
|
+
expect(fields.descField.value).to.equal('SV control 1');
|
|
111
|
+
expect(fields.smvIDField.value).to.equal('SV_ID1');
|
|
112
|
+
expect(fields.smpModField.value).to.equal('SmpPerPeriod');
|
|
113
|
+
expect(fields.smpRateField.value).to.equal('80');
|
|
114
|
+
expect(fields.nofASDUField.value).to.equal('1');
|
|
115
|
+
expect(fields.securityEnabledField.value).to.equal('None');
|
|
116
|
+
expect(fields.multicastField).to.be.null;
|
|
117
|
+
});
|
|
118
|
+
it('returns [] when no changes are made', async () => {
|
|
119
|
+
const scl = createSclDoc();
|
|
120
|
+
const element = scl.querySelector('SampledValueControl[name="SVC1"]');
|
|
121
|
+
const wizard = editSampledValueControlWizard(element);
|
|
122
|
+
const fields = await renderContent(wizard);
|
|
123
|
+
renderedContainer = fields.content;
|
|
124
|
+
const edits = wizard.primary.action([
|
|
125
|
+
fields.nameField,
|
|
126
|
+
fields.descField,
|
|
127
|
+
fields.smvIDField,
|
|
128
|
+
fields.smpModField,
|
|
129
|
+
fields.smpRateField,
|
|
130
|
+
fields.nofASDUField,
|
|
131
|
+
fields.securityEnabledField,
|
|
132
|
+
], renderedContainer);
|
|
133
|
+
expect(edits).to.have.lengthOf(0);
|
|
134
|
+
});
|
|
135
|
+
it('returns SetAttributes with changed name', async () => {
|
|
136
|
+
const scl = createSclDoc();
|
|
137
|
+
const element = scl.querySelector('SampledValueControl[name="SVC1"]');
|
|
138
|
+
const wizard = editSampledValueControlWizard(element);
|
|
139
|
+
const fields = await renderContent(wizard);
|
|
140
|
+
renderedContainer = fields.content;
|
|
141
|
+
fields.nameField.value = 'SVC_New';
|
|
142
|
+
const edits = wizard.primary.action([
|
|
143
|
+
fields.nameField,
|
|
144
|
+
fields.descField,
|
|
145
|
+
fields.smvIDField,
|
|
146
|
+
fields.smpModField,
|
|
147
|
+
fields.smpRateField,
|
|
148
|
+
fields.nofASDUField,
|
|
149
|
+
fields.securityEnabledField,
|
|
150
|
+
], renderedContainer);
|
|
151
|
+
expect(edits).to.have.lengthOf(1);
|
|
152
|
+
const edit = edits[0];
|
|
153
|
+
expect(edit.element).to.equal(element);
|
|
154
|
+
expect(edit.attributes.name).to.equal('SVC_New');
|
|
155
|
+
});
|
|
156
|
+
it('applies changed attributes to the document', async () => {
|
|
157
|
+
const scl = createSclDoc();
|
|
158
|
+
const element = scl.querySelector('SampledValueControl[name="SVC1"]');
|
|
159
|
+
const wizard = editSampledValueControlWizard(element);
|
|
160
|
+
const fields = await renderContent(wizard);
|
|
161
|
+
renderedContainer = fields.content;
|
|
162
|
+
fields.nameField.value = 'SVC_New';
|
|
163
|
+
fields.smpRateField.value = '4000';
|
|
164
|
+
fields.nofASDUField.value = '8';
|
|
165
|
+
const edits = wizard.primary.action([
|
|
166
|
+
fields.nameField,
|
|
167
|
+
fields.descField,
|
|
168
|
+
fields.smvIDField,
|
|
169
|
+
fields.smpModField,
|
|
170
|
+
fields.smpRateField,
|
|
171
|
+
fields.nofASDUField,
|
|
172
|
+
fields.securityEnabledField,
|
|
173
|
+
], renderedContainer);
|
|
174
|
+
xmlEditor.commit(edits);
|
|
175
|
+
expect(element.getAttribute('name')).to.equal('SVC_New');
|
|
176
|
+
expect(element.getAttribute('smpRate')).to.equal('4000');
|
|
177
|
+
expect(element.getAttribute('nofASDU')).to.equal('8');
|
|
178
|
+
});
|
|
179
|
+
it('handles nullable smpMod cleared returns null attribute', async () => {
|
|
180
|
+
const scl = createSclDoc();
|
|
181
|
+
const element = scl.querySelector('SampledValueControl[name="SVC1"]');
|
|
182
|
+
expect(element.getAttribute('smpMod')).to.equal('SmpPerPeriod');
|
|
183
|
+
const wizard = editSampledValueControlWizard(element);
|
|
184
|
+
const fields = await renderContent(wizard);
|
|
185
|
+
renderedContainer = fields.content;
|
|
186
|
+
fields.smpModField.value = null;
|
|
187
|
+
const edits = wizard.primary.action([
|
|
188
|
+
fields.nameField,
|
|
189
|
+
fields.descField,
|
|
190
|
+
fields.smvIDField,
|
|
191
|
+
fields.smpModField,
|
|
192
|
+
fields.smpRateField,
|
|
193
|
+
fields.nofASDUField,
|
|
194
|
+
fields.securityEnabledField,
|
|
195
|
+
], renderedContainer);
|
|
196
|
+
expect(edits).to.have.lengthOf(1);
|
|
197
|
+
const edit = edits[0];
|
|
198
|
+
expect(edit.attributes.smpMod).to.be.null;
|
|
199
|
+
xmlEditor.commit(edits);
|
|
200
|
+
expect(element.getAttribute('smpMod')).to.be.null;
|
|
201
|
+
});
|
|
202
|
+
it('handles element with minimal attributes (SVC2)', async () => {
|
|
203
|
+
const scl = createSclDoc();
|
|
204
|
+
const element = scl.querySelector('SampledValueControl[name="SVC2"]');
|
|
205
|
+
const wizard = editSampledValueControlWizard(element);
|
|
206
|
+
const fields = await renderContent(wizard);
|
|
207
|
+
renderedContainer = fields.content;
|
|
208
|
+
expect(fields.nameField.value).to.equal('SVC2');
|
|
209
|
+
expect(fields.descField.value).to.be.null;
|
|
210
|
+
expect(fields.smvIDField.value).to.equal('SV_ID2');
|
|
211
|
+
expect(fields.smpModField.value).to.be.null;
|
|
212
|
+
expect(fields.smpRateField.value).to.equal('256');
|
|
213
|
+
expect(fields.nofASDUField.value).to.equal('2');
|
|
214
|
+
expect(fields.securityEnabledField.value).to.be.null;
|
|
215
|
+
});
|
|
216
|
+
it('renders disabled multicast checkbox for unicast SV', async () => {
|
|
217
|
+
const scl = createSclDoc('false');
|
|
218
|
+
const element = scl.querySelector('SampledValueControl[name="SVC1"]');
|
|
219
|
+
const wizard = editSampledValueControlWizard(element);
|
|
220
|
+
const fields = await renderContent(wizard);
|
|
221
|
+
renderedContainer = fields.content;
|
|
222
|
+
expect(fields.multicastField).to.exist;
|
|
223
|
+
expect(fields.multicastField.disabled).to.be.true;
|
|
224
|
+
expect(fields.multicastField.value).to.equal('false');
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
//# sourceMappingURL=sampledvaluecontrol.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sampledvaluecontrol.spec.js","sourceRoot":"","sources":["../../wizards/sampledvaluecontrol.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unused-expressions */\nimport { expect, fixture } from '@open-wc/testing';\nimport { html } from 'lit';\n\nimport { editSampledValueControlWizard } from './sampledvaluecontrol.js';\nimport { EditV2, SetAttributes } from '@openscd/oscd-api';\nimport { XMLEditor } from '@openscd/oscd-editor';\nimport { SclTextField } from '@openenergytools/scl-text-field';\nimport { SclSelect } from '@openenergytools/scl-select';\nimport { SclCheckbox } from '@openenergytools/scl-checkbox';\nimport { Wizard } from '../foundation.js';\n\nif (!customElements.get('scl-text-field')) {\n customElements.define('scl-text-field', SclTextField);\n}\nif (!customElements.get('scl-select')) {\n customElements.define('scl-select', SclSelect);\n}\nif (!customElements.get('scl-checkbox')) {\n customElements.define('scl-checkbox', SclCheckbox);\n}\n\nconst xmlParser = new DOMParser();\nfunction createSclDoc(multicast?: string): XMLDocument {\n const multicastAttr =\n multicast !== undefined ? `multicast=\"${multicast}\"` : '';\n return xmlParser.parseFromString(\n `\n <SCL xmlns=\"http://www.iec.ch/61850/2003/SCL\">\n <IED name=\"IED1\">\n <AccessPoint name=\"AP1\">\n <Server>\n <LDevice inst=\"LD1\">\n <LN0 lnClass=\"LLN0\" inst=\"\" lnType=\"LLN0_Type\">\n <SampledValueControl name=\"SVC1\" desc=\"SV control 1\" smvID=\"SV_ID1\" smpMod=\"SmpPerPeriod\" smpRate=\"80\" nofASDU=\"1\" securityEnabled=\"None\" ${multicastAttr} datSet=\"ds1\" confRev=\"1\" />\n <SampledValueControl name=\"SVC2\" smvID=\"SV_ID2\" smpRate=\"256\" nofASDU=\"2\" />\n </LN0>\n </LDevice>\n </Server>\n </AccessPoint>\n </IED>\n </SCL>\n `,\n 'application/xml',\n );\n}\n\nasync function renderContent(wizard: Wizard) {\n const content = await fixture(html`<form>${wizard.content}</form>`);\n\n const nameField = content.querySelector(\n 'scl-text-field[label=\"name\"]',\n ) as SclTextField;\n const descField = content.querySelector(\n 'scl-text-field[label=\"desc\"]',\n ) as SclTextField;\n const smvIDField = content.querySelector(\n 'scl-text-field[label=\"smvID\"]',\n ) as SclTextField;\n const smpModField = content.querySelector(\n 'scl-select[label=\"smpMod\"]',\n ) as SclSelect;\n const smpRateField = content.querySelector(\n 'scl-text-field[label=\"smpRate\"]',\n ) as SclTextField;\n const nofASDUField = content.querySelector(\n 'scl-text-field[label=\"nofASDU\"]',\n ) as SclTextField;\n const securityEnabledField = content.querySelector(\n 'scl-select[label=\"securityEnabled\"]',\n ) as SclSelect;\n const multicastField = content.querySelector(\n 'scl-checkbox[label=\"multicast\"]',\n ) as SclCheckbox | null;\n\n expect(nameField).to.exist;\n expect(descField).to.exist;\n expect(smvIDField).to.exist;\n expect(smpModField).to.exist;\n expect(smpRateField).to.exist;\n expect(nofASDUField).to.exist;\n expect(securityEnabledField).to.exist;\n\n return {\n content,\n nameField,\n descField,\n smvIDField,\n smpModField,\n smpRateField,\n nofASDUField,\n securityEnabledField,\n multicastField,\n };\n}\n\ndescribe('SampledValueControl edit wizard', () => {\n let xmlEditor: XMLEditor;\n let renderedContainer: Element | undefined;\n\n beforeEach(() => {\n xmlEditor = new XMLEditor();\n });\n\n afterEach(() => {\n if (renderedContainer) {\n renderedContainer.remove();\n }\n });\n\n it('returns a wizard with correct title and 7 fields (multicast true/absent)', () => {\n const scl = createSclDoc();\n const element = scl.querySelector('SampledValueControl[name=\"SVC1\"]')!;\n const wizard = editSampledValueControlWizard(element);\n\n expect(wizard.title).to.equal('Edit SampledValueControl');\n expect(wizard.primary).to.exist;\n expect(wizard.primary!.icon).to.equal('edit');\n expect(wizard.primary!.label).to.equal('save');\n // 7 fields: name, desc, smvID, smpMod, smpRate, nofASDU, securityEnabled\n // No multicast field when multicast is absent (defaults to true)\n expect(wizard.content).to.have.lengthOf(7);\n });\n\n it('shows 8 fields with disabled multicast checkbox when multicast is false', () => {\n const scl = createSclDoc('false');\n const element = scl.querySelector('SampledValueControl[name=\"SVC1\"]')!;\n const wizard = editSampledValueControlWizard(element);\n\n expect(wizard.content).to.have.lengthOf(8);\n });\n\n it('does not show multicast field when multicast is true', () => {\n const scl = createSclDoc('true');\n const element = scl.querySelector('SampledValueControl[name=\"SVC1\"]')!;\n const wizard = editSampledValueControlWizard(element);\n\n // 7 fields — no multicast\n expect(wizard.content).to.have.lengthOf(7);\n });\n\n it('populates fields with current attribute values', async () => {\n const scl = createSclDoc();\n const element = scl.querySelector('SampledValueControl[name=\"SVC1\"]')!;\n const wizard = editSampledValueControlWizard(element);\n const fields = await renderContent(wizard);\n renderedContainer = fields.content;\n\n expect(fields.nameField.value).to.equal('SVC1');\n expect(fields.descField.value).to.equal('SV control 1');\n expect(fields.smvIDField.value).to.equal('SV_ID1');\n expect(fields.smpModField.value).to.equal('SmpPerPeriod');\n expect(fields.smpRateField.value).to.equal('80');\n expect(fields.nofASDUField.value).to.equal('1');\n expect(fields.securityEnabledField.value).to.equal('None');\n expect(fields.multicastField).to.be.null;\n });\n\n it('returns [] when no changes are made', async () => {\n const scl = createSclDoc();\n const element = scl.querySelector('SampledValueControl[name=\"SVC1\"]')!;\n const wizard = editSampledValueControlWizard(element);\n const fields = await renderContent(wizard);\n renderedContainer = fields.content;\n\n const edits = wizard.primary!.action(\n [\n fields.nameField,\n fields.descField,\n fields.smvIDField,\n fields.smpModField,\n fields.smpRateField,\n fields.nofASDUField,\n fields.securityEnabledField,\n ],\n renderedContainer!,\n ) as EditV2[];\n\n expect(edits).to.have.lengthOf(0);\n });\n\n it('returns SetAttributes with changed name', async () => {\n const scl = createSclDoc();\n const element = scl.querySelector('SampledValueControl[name=\"SVC1\"]')!;\n const wizard = editSampledValueControlWizard(element);\n const fields = await renderContent(wizard);\n renderedContainer = fields.content;\n\n fields.nameField.value = 'SVC_New';\n\n const edits = wizard.primary!.action(\n [\n fields.nameField,\n fields.descField,\n fields.smvIDField,\n fields.smpModField,\n fields.smpRateField,\n fields.nofASDUField,\n fields.securityEnabledField,\n ],\n renderedContainer!,\n ) as EditV2[];\n\n expect(edits).to.have.lengthOf(1);\n const edit = edits[0] as SetAttributes;\n expect(edit.element).to.equal(element);\n expect(edit.attributes!.name).to.equal('SVC_New');\n });\n\n it('applies changed attributes to the document', async () => {\n const scl = createSclDoc();\n const element = scl.querySelector('SampledValueControl[name=\"SVC1\"]')!;\n const wizard = editSampledValueControlWizard(element);\n const fields = await renderContent(wizard);\n renderedContainer = fields.content;\n\n fields.nameField.value = 'SVC_New';\n fields.smpRateField.value = '4000';\n fields.nofASDUField.value = '8';\n\n const edits = wizard.primary!.action(\n [\n fields.nameField,\n fields.descField,\n fields.smvIDField,\n fields.smpModField,\n fields.smpRateField,\n fields.nofASDUField,\n fields.securityEnabledField,\n ],\n renderedContainer!,\n ) as EditV2[];\n\n xmlEditor.commit(edits);\n expect(element.getAttribute('name')).to.equal('SVC_New');\n expect(element.getAttribute('smpRate')).to.equal('4000');\n expect(element.getAttribute('nofASDU')).to.equal('8');\n });\n\n it('handles nullable smpMod cleared returns null attribute', async () => {\n const scl = createSclDoc();\n const element = scl.querySelector('SampledValueControl[name=\"SVC1\"]')!;\n expect(element.getAttribute('smpMod')).to.equal('SmpPerPeriod');\n\n const wizard = editSampledValueControlWizard(element);\n const fields = await renderContent(wizard);\n renderedContainer = fields.content;\n\n fields.smpModField.value = null as unknown as string;\n\n const edits = wizard.primary!.action(\n [\n fields.nameField,\n fields.descField,\n fields.smvIDField,\n fields.smpModField,\n fields.smpRateField,\n fields.nofASDUField,\n fields.securityEnabledField,\n ],\n renderedContainer!,\n ) as EditV2[];\n\n expect(edits).to.have.lengthOf(1);\n const edit = edits[0] as SetAttributes;\n expect(edit.attributes!.smpMod).to.be.null;\n\n xmlEditor.commit(edits);\n expect(element.getAttribute('smpMod')).to.be.null;\n });\n\n it('handles element with minimal attributes (SVC2)', async () => {\n const scl = createSclDoc();\n const element = scl.querySelector('SampledValueControl[name=\"SVC2\"]')!;\n const wizard = editSampledValueControlWizard(element);\n const fields = await renderContent(wizard);\n renderedContainer = fields.content;\n\n expect(fields.nameField.value).to.equal('SVC2');\n expect(fields.descField.value).to.be.null;\n expect(fields.smvIDField.value).to.equal('SV_ID2');\n expect(fields.smpModField.value).to.be.null;\n expect(fields.smpRateField.value).to.equal('256');\n expect(fields.nofASDUField.value).to.equal('2');\n expect(fields.securityEnabledField.value).to.be.null;\n });\n\n it('renders disabled multicast checkbox for unicast SV', async () => {\n const scl = createSclDoc('false');\n const element = scl.querySelector('SampledValueControl[name=\"SVC1\"]')!;\n const wizard = editSampledValueControlWizard(element);\n const fields = await renderContent(wizard);\n renderedContainer = fields.content;\n\n expect(fields.multicastField).to.exist;\n expect(fields.multicastField!.disabled).to.be.true;\n expect(fields.multicastField!.value).to.equal('false');\n });\n});\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import { getValue, } from '../foundation.js';
|
|
3
|
+
const smvOptKeys = [
|
|
4
|
+
'refreshTime',
|
|
5
|
+
'sampleRate',
|
|
6
|
+
'dataSet',
|
|
7
|
+
'security',
|
|
8
|
+
'synchSourceId',
|
|
9
|
+
];
|
|
10
|
+
function render(options) {
|
|
11
|
+
return smvOptKeys.map(key => html `<scl-checkbox
|
|
12
|
+
label="${key}"
|
|
13
|
+
.value=${options[key]}
|
|
14
|
+
nullable
|
|
15
|
+
></scl-checkbox>`);
|
|
16
|
+
}
|
|
17
|
+
function updateAction(element) {
|
|
18
|
+
return (inputs) => {
|
|
19
|
+
const attributes = {};
|
|
20
|
+
for (const key of smvOptKeys) {
|
|
21
|
+
attributes[key] = getValue(inputs.find(i => i.label === key));
|
|
22
|
+
}
|
|
23
|
+
if (!smvOptKeys.some(key => attributes[key] !== element.getAttribute(key)))
|
|
24
|
+
return [];
|
|
25
|
+
return [{ element, attributes }];
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function editSmvOptsWizard(element) {
|
|
29
|
+
const options = {};
|
|
30
|
+
for (const key of smvOptKeys) {
|
|
31
|
+
options[key] = element.getAttribute(key);
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
title: 'Edit SmvOpts',
|
|
35
|
+
primary: {
|
|
36
|
+
icon: 'edit',
|
|
37
|
+
label: 'save',
|
|
38
|
+
action: updateAction(element),
|
|
39
|
+
},
|
|
40
|
+
content: render(options),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=smvopts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smvopts.js","sourceRoot":"","sources":["../../wizards/smvopts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAkB,MAAM,KAAK,CAAC;AAI3C,OAAO,EACL,QAAQ,GAIT,MAAM,kBAAkB,CAAC;AAE1B,MAAM,UAAU,GAAG;IACjB,aAAa;IACb,YAAY;IACZ,SAAS;IACT,UAAU;IACV,eAAe;CACP,CAAC;AAMX,SAAS,MAAM,CAAC,OAAsB;IACpC,OAAO,UAAU,CAAC,GAAG,CACnB,GAAG,CAAC,EAAE,CACJ,IAAI,CAAA;iBACO,GAAG;iBACH,OAAO,CAAC,GAAG,CAAC;;uBAEN,CACpB,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,OAAgB;IACpC,OAAO,CAAC,MAA4B,EAAY,EAAE;QAChD,MAAM,UAAU,GAAkC,EAAE,CAAC;QACrD,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,UAAU,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,GAAG,CAAE,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;YACxE,OAAO,EAAE,CAAC;QAEZ,OAAO,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,MAAM,OAAO,GAAG,EAAmB,CAAC;IACpC,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO;QACL,KAAK,EAAE,cAAc;QACrB,OAAO,EAAE;YACP,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,MAAM;YACb,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC;SAC9B;QACD,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC;KACzB,CAAC;AACJ,CAAC","sourcesContent":["import { html, TemplateResult } from 'lit';\n\nimport { EditV2 } from '@openscd/oscd-api';\n\nimport {\n getValue,\n Wizard,\n WizardActor,\n WizardInputElement,\n} from '../foundation.js';\n\nconst smvOptKeys = [\n 'refreshTime',\n 'sampleRate',\n 'dataSet',\n 'security',\n 'synchSourceId',\n] as const;\n\ntype SmvOptKey = (typeof smvOptKeys)[number];\n\ntype RenderOptions = Record<SmvOptKey, string | null>;\n\nfunction render(options: RenderOptions): TemplateResult[] {\n return smvOptKeys.map(\n key =>\n html`<scl-checkbox\n label=\"${key}\"\n .value=${options[key]}\n nullable\n ></scl-checkbox>`,\n );\n}\n\nfunction updateAction(element: Element): WizardActor {\n return (inputs: WizardInputElement[]): EditV2[] => {\n const attributes: Record<string, string | null> = {};\n for (const key of smvOptKeys) {\n attributes[key] = getValue(inputs.find(i => i.label === key)!);\n }\n\n if (!smvOptKeys.some(key => attributes[key] !== element.getAttribute(key)))\n return [];\n\n return [{ element, attributes }];\n };\n}\n\nexport function editSmvOptsWizard(element: Element): Wizard {\n const options = {} as RenderOptions;\n for (const key of smvOptKeys) {\n options[key] = element.getAttribute(key);\n }\n\n return {\n title: 'Edit SmvOpts',\n primary: {\n icon: 'edit',\n label: 'save',\n action: updateAction(element),\n },\n content: render(options),\n };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|