Skip to content

Commit 3b39d20

Browse files
author
Dennis Labordus
authored
refactor(setting/nsdoc): Loading NSDoc Files through Custom Event (openscd#644)
Refactor loading NSDoc File through Custom Event. And added some integration tests.
1 parent cbde240 commit 3b39d20

File tree

14 files changed

+1487
-110
lines changed

14 files changed

+1487
-110
lines changed

src/Logging.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,8 @@ export function Logging<TBase extends LitElementConstructor>(Base: TBase) {
245245

246246
this.undo = this.undo.bind(this);
247247
this.redo = this.redo.bind(this);
248-
249248
this.onLog = this.onLog.bind(this);
249+
250250
this.addEventListener('log', this.onLog);
251251
this.addEventListener('issue', this.onIssue);
252252
this.addEventListener('open-doc', this.onLoadHistoryFromDoc);

src/Setting.ts

Lines changed: 63 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,23 @@ type NsdVersions = {
5454
'IEC 61850-8-1': NsdVersion;
5555
}
5656

57+
/** Represents a document to be opened. */
58+
export interface LoadNsdocDetail {
59+
nsdoc: string;
60+
filename: string;
61+
}
62+
export type LoadNsdocEvent = CustomEvent<LoadNsdocDetail>;
63+
export function newLoadNsdocEvent(
64+
nsdoc: string,
65+
filename: string
66+
): LoadNsdocEvent {
67+
return new CustomEvent<LoadNsdocDetail>('load-nsdoc', {
68+
bubbles: true,
69+
composed: true,
70+
detail: { nsdoc, filename },
71+
});
72+
}
73+
5774
/** Mixin that saves [[`Settings`]] to `localStorage`, reflecting them in the
5875
* `settings` property, setting them through `setSetting(setting, value)`. */
5976
export type SettingElement = Mixin<typeof Setting>;
@@ -168,7 +185,7 @@ export function Setting<TBase extends LitElementConstructor>(Base: TBase) {
168185
private renderFileSelect(): TemplateResult {
169186
return html `
170187
<input id="nsdoc-file" accept=".nsdoc" type="file" hidden required multiple
171-
@change=${(evt: Event) => this.loadNsdocFile(evt)}}>
188+
@change=${(evt: Event) => this.uploadNsdocFile(evt)}}>
172189
<mwc-button label="${translate('settings.selectFileButton')}"
173190
id="selectFileButton"
174191
@click=${() => {
@@ -179,50 +196,63 @@ export function Setting<TBase extends LitElementConstructor>(Base: TBase) {
179196
`;
180197
}
181198

182-
private async loadNsdocFile(evt: Event): Promise<void> {
183-
const nsdVersions = await this.nsdVersions();
199+
private async uploadNsdocFile(evt: Event): Promise<void> {
184200
const files = Array.from(
185201
(<HTMLInputElement | null>evt.target)?.files ?? []
186202
);
187-
203+
188204
if (files.length == 0) return;
189-
files.forEach(async file => {
205+
for (const file of files) {
190206
const text = await file.text();
191-
const nsdocElement = this.parseToXmlObject(text).querySelector('NSDoc');
192-
const id = nsdocElement?.getAttribute('id');
193-
if (!id) {
194-
document
207+
document
195208
.querySelector('open-scd')!
196209
.dispatchEvent(
197-
newLogEvent({ kind: 'error', title: get('settings.invalidFileNoIdFound') })
198-
);
199-
return;
200-
}
201-
const nsdVersion = nsdVersions[id as keyof NsdVersions];
202-
const nsdocVersion = {
203-
version: nsdocElement!.getAttribute('version') ?? '',
204-
revision: nsdocElement!.getAttribute('revision') ?? '',
205-
release: nsdocElement!.getAttribute('release') ?? ''
206-
}
210+
newLoadNsdocEvent(text, file.name)
211+
);
212+
}
213+
214+
this.nsdocFileUI.value = '';
215+
this.requestUpdate();
216+
}
217+
218+
private async onLoadNsdoc(event: LoadNsdocEvent) {
219+
const nsdocElement = this.parseToXmlObject(event.detail.nsdoc).querySelector('NSDoc');
207220

208-
if (!this.isEqual(nsdVersion, nsdocVersion)) {
209-
document
221+
const id = nsdocElement?.getAttribute('id');
222+
if (!id) {
223+
document
210224
.querySelector('open-scd')!
211225
.dispatchEvent(
212-
newLogEvent({ kind: 'error', title: get('settings.invalidNsdocVersion', {
226+
newLogEvent({ kind: 'error', title: get('settings.invalidFileNoIdFound', {
227+
filename: event.detail.filename
228+
}) })
229+
);
230+
return;
231+
}
232+
233+
const nsdVersions = await this.nsdVersions();
234+
const nsdVersion = nsdVersions[id as keyof NsdVersions];
235+
const nsdocVersion = {
236+
version: nsdocElement!.getAttribute('version') ?? '',
237+
revision: nsdocElement!.getAttribute('revision') ?? '',
238+
release: nsdocElement!.getAttribute('release') ?? ''
239+
}
240+
241+
if (!this.isEqual(nsdVersion, nsdocVersion)) {
242+
document
243+
.querySelector('open-scd')!
244+
.dispatchEvent(
245+
newLogEvent({ kind: 'error', title: get('settings.invalidNsdocVersion', {
213246
id: id,
247+
filename: event.detail.filename,
214248
nsdVersion: `${nsdVersion.version}${nsdVersion.revision}${nsdVersion.release}`,
215249
nsdocVersion: `${nsdocVersion.version}${nsdocVersion.revision}${nsdocVersion.release}`
216250
}) })
217-
);
218-
return;
219-
}
220-
221-
this.setSetting(id as keyof Settings, text);
222-
})
251+
);
252+
return;
253+
}
223254

224-
this.nsdocFileUI.value = '';
225-
this.requestUpdate();
255+
this.setSetting(id as keyof Settings, event.detail.nsdoc);
226256
}
227257

228258
/**
@@ -245,7 +275,7 @@ export function Setting<TBase extends LitElementConstructor>(Base: TBase) {
245275
let nsdVersion: string | undefined | null;
246276
let nsdRevision: string | undefined | null;
247277
let nsdRelease: string | undefined | null;
248-
278+
249279
if (nsdSetting) {
250280
const nsdoc = this.parseToXmlObject(nsdSetting)!.querySelector('NSDoc');
251281
nsdVersion = nsdoc?.getAttribute('version');
@@ -273,6 +303,8 @@ export function Setting<TBase extends LitElementConstructor>(Base: TBase) {
273303

274304
registerTranslateConfig({ loader, empty: key => key });
275305
use(this.settings.language);
306+
307+
(<any>this).addEventListener('load-nsdoc', this.onLoadNsdoc);
276308
}
277309

278310
render(): TemplateResult {

src/translations/de.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,9 @@ export const de: Translations = {
7070
showieds: 'Zeige IEDs im Substation-Editor',
7171
selectFileButton: 'Datei auswählen',
7272
loadNsdTranslations: 'NSDoc-Dateien hochladen',
73-
invalidFileNoIdFound:
74-
"Ungültiges NSDoc; kein 'id'-Attribut in der Datei gefunden",
73+
invalidFileNoIdFound: "Ungültiges NSDoc ({{ filename }}); kein 'id'-Attribut in der Datei gefunden",
7574
invalidNsdocVersion:
76-
'Die Version {{ id }} NSD ({{ nsdVersion }}) passt nicht zu der geladenen NSDoc ({{ nsdocVersion }})',
75+
'Die Version {{ id }} NSD ({{ nsdVersion }}) passt nicht zu der geladenen NSDoc ({{ filename }}, {{ nsdocVersion }})',
7776
},
7877
menu: {
7978
new: 'Neues projekt',

src/translations/en.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,10 @@ export const en = {
6767
mode: 'Pro mode',
6868
showieds: 'Show IEDs in substation editor',
6969
selectFileButton: 'Select file',
70-
loadNsdTranslations: 'Uploading NSDoc files',
71-
invalidFileNoIdFound: "Invalid NSDoc; no 'id' attribute found in file",
70+
loadNsdTranslations: 'Uploaded NSDoc files',
71+
invalidFileNoIdFound: "Invalid NSDoc ({{ filename }}); no 'id' attribute found in file",
7272
invalidNsdocVersion:
73-
'The version of {{ id }} NSD ({{ nsdVersion }}) does not correlate with the version of the corresponding NSDoc ({{ nsdocVersion }})',
73+
'The version of {{ id }} NSD ({{ nsdVersion }}) does not correlate with the version of the corresponding NSDoc ({{ filename }}, {{ nsdocVersion }})',
7474
},
7575
menu: {
7676
new: 'New project',

test/integration/Setting.test.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { html, fixture, expect } from '@open-wc/testing';
2+
3+
import '../../src/open-scd.js';
4+
5+
import { OpenSCD } from '../../src/open-scd.js';
6+
import { newLoadNsdocEvent } from "../../src/Setting.js";
7+
8+
describe('Setting', () => {
9+
let element: OpenSCD;
10+
11+
beforeEach(async () => {
12+
localStorage.clear();
13+
14+
element = await fixture(html`
15+
<open-scd></open-scd>
16+
17+
<link href="public/google/fonts/roboto-v27.css" rel="stylesheet" />
18+
<link href="public/google/fonts/roboto-mono-v13.css" rel="stylesheet" />
19+
<link href="public/google/icons/material-icons-outlined.css" rel="stylesheet" />
20+
`);
21+
});
22+
23+
it('opens the log on log menu entry click', async () => {
24+
await (<HTMLElement>(
25+
element.shadowRoot!.querySelector('mwc-list-item[iconid="history"]')!
26+
)).click();
27+
expect(element.logUI).to.have.property('open', true);
28+
});
29+
30+
it('upload .nsdoc file using event and looks like latest snapshot', async () => {
31+
element.settingsUI.show();
32+
await element.settingsUI.updateComplete;
33+
34+
const nsdocFile = await fetch('/test/testfiles/nsdoc/IEC_61850-7-2.nsdoc')
35+
.then(response => response.text())
36+
37+
element.dispatchEvent(
38+
newLoadNsdocEvent(nsdocFile, 'IEC_61850-7-2.nsdoc')
39+
);
40+
41+
await element.requestUpdate();
42+
await element.updateComplete;
43+
44+
expect(localStorage.getItem('IEC 61850-7-2')).to.eql(nsdocFile);
45+
expect(element).shadowDom.to.equalSnapshot();
46+
});
47+
48+
it('upload invalid .nsdoc file using event and log event fired', async () => {
49+
element.settingsUI.show();
50+
await element.settingsUI.updateComplete;
51+
52+
const nsdocFile = await fetch('/test/testfiles/nsdoc/invalid.nsdoc')
53+
.then(response => response.text())
54+
55+
element.dispatchEvent(
56+
newLoadNsdocEvent(nsdocFile, 'invalid.nsdoc')
57+
);
58+
59+
await element.requestUpdate();
60+
await element.updateComplete;
61+
62+
expect(element.history.length).to.be.equal(1);
63+
expect(element.history[0].title).to.be.equal('Invalid NSDoc (invalid.nsdoc); no \'id\' attribute found in file');
64+
});
65+
66+
it('upload .nsdoc file with wrong version using event and log event fired', async () => {
67+
element.settingsUI.show();
68+
await element.settingsUI.updateComplete;
69+
70+
const nsdocFile = await fetch('/test/testfiles/nsdoc/wrong-version.nsdoc')
71+
.then(response => response.text())
72+
73+
element.dispatchEvent(
74+
newLoadNsdocEvent(nsdocFile, 'wrong-version.nsdoc')
75+
);
76+
77+
await element.requestUpdate();
78+
await element.updateComplete;
79+
80+
expect(element.history.length).to.be.equal(1);
81+
expect(element.history[0].title).to.be.equal('The version of IEC 61850-7-3 NSD (2007B3) does not correlate ' +
82+
'with the version of the corresponding NSDoc (wrong-version.nsdoc, 2007B4)');
83+
});
84+
}).timeout(4000);

0 commit comments

Comments
 (0)