Skip to content

Commit 7c6e281

Browse files
author
Dennis Labordus
committed
Refactor loading NSDoc File through Custom Event. And added some integration tests.
Signed-off-by: Dennis Labordus <[email protected]>
1 parent 42c2b29 commit 7c6e281

File tree

13 files changed

+1476
-54
lines changed

13 files changed

+1476
-54
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: 66 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { Dialog } from '@material/mwc-dialog';
1212
import { Select } from '@material/mwc-select';
1313
import { Switch } from '@material/mwc-switch';
1414

15-
import { ifImplemented, LitElementConstructor, Mixin, newLogEvent } from './foundation.js';
15+
import {ifImplemented, LitElementConstructor, Mixin, newLogEvent, OpenDocEvent} from './foundation.js';
1616
import { Language, languages, loader } from './translations/loader.js';
1717

1818
import './WizardDivider.js';
@@ -54,6 +54,25 @@ 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+
eventInitDict?: CustomEventInit<Partial<LoadNsdocDetail>>
67+
): LoadNsdocEvent {
68+
return new CustomEvent<LoadNsdocDetail>('load-nsdoc', {
69+
bubbles: true,
70+
composed: true,
71+
...eventInitDict,
72+
detail: { nsdoc, filename, ...eventInitDict?.detail },
73+
});
74+
}
75+
5776
/** Mixin that saves [[`Settings`]] to `localStorage`, reflecting them in the
5877
* `settings` property, setting them through `setSetting(setting, value)`. */
5978
export type SettingElement = Mixin<typeof Setting>;
@@ -168,7 +187,7 @@ export function Setting<TBase extends LitElementConstructor>(Base: TBase) {
168187
private renderFileSelect(): TemplateResult {
169188
return html `
170189
<input id="nsdoc-file" accept=".nsdoc" type="file" hidden required multiple
171-
@change=${(evt: Event) => this.loadNsdocFile(evt)}}>
190+
@change=${(evt: Event) => this.uploadNsdocFile(evt)}}>
172191
<mwc-button label="${translate('settings.selectFileButton')}"
173192
id="selectFileButton"
174193
@click=${() => {
@@ -179,50 +198,63 @@ export function Setting<TBase extends LitElementConstructor>(Base: TBase) {
179198
`;
180199
}
181200

182-
private async loadNsdocFile(evt: Event): Promise<void> {
183-
const nsdVersions = await this.nsdVersions();
201+
private async uploadNsdocFile(evt: Event): Promise<void> {
184202
const files = Array.from(
185203
(<HTMLInputElement | null>evt.target)?.files ?? []
186204
);
187-
205+
188206
if (files.length == 0) return;
189-
files.forEach(async file => {
207+
for (const file of files) {
190208
const text = await file.text();
191-
const nsdocElement = this.parseToXmlObject(text).querySelector('NSDoc');
192-
const id = nsdocElement?.getAttribute('id');
193-
if (!id) {
194-
document
209+
document
195210
.querySelector('open-scd')!
196211
.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-
}
212+
newLoadNsdocEvent(text, file.name)
213+
);
214+
}
215+
216+
this.nsdocFileUI.value = '';
217+
this.requestUpdate();
218+
}
219+
220+
private async onLoadNsdoc(event: LoadNsdocEvent) {
221+
const nsdocElement = this.parseToXmlObject(event.detail.nsdoc).querySelector('NSDoc');
207222

208-
if (!this.isEqual(nsdVersion, nsdocVersion)) {
209-
document
223+
const id = nsdocElement?.getAttribute('id');
224+
if (!id) {
225+
document
210226
.querySelector('open-scd')!
211227
.dispatchEvent(
212-
newLogEvent({ kind: 'error', title: get('settings.invalidNsdocVersion', {
228+
newLogEvent({ kind: 'error', title: get('settings.invalidFileNoIdFound', {
229+
filename: event.detail.filename
230+
}) })
231+
);
232+
return;
233+
}
234+
235+
const nsdVersions = await this.nsdVersions();
236+
const nsdVersion = nsdVersions[id as keyof NsdVersions];
237+
const nsdocVersion = {
238+
version: nsdocElement!.getAttribute('version') ?? '',
239+
revision: nsdocElement!.getAttribute('revision') ?? '',
240+
release: nsdocElement!.getAttribute('release') ?? ''
241+
}
242+
243+
if (!this.isEqual(nsdVersion, nsdocVersion)) {
244+
document
245+
.querySelector('open-scd')!
246+
.dispatchEvent(
247+
newLogEvent({ kind: 'error', title: get('settings.invalidNsdocVersion', {
213248
id: id,
249+
filename: event.detail.filename,
214250
nsdVersion: `${nsdVersion.version}${nsdVersion.revision}${nsdVersion.release}`,
215251
nsdocVersion: `${nsdocVersion.version}${nsdocVersion.revision}${nsdocVersion.release}`
216252
}) })
217-
);
218-
return;
219-
}
220-
221-
this.setSetting(id as keyof Settings, text);
222-
})
253+
);
254+
return;
255+
}
223256

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

228260
/**
@@ -245,7 +277,7 @@ export function Setting<TBase extends LitElementConstructor>(Base: TBase) {
245277
let nsdVersion: string | undefined | null;
246278
let nsdRevision: string | undefined | null;
247279
let nsdRelease: string | undefined | null;
248-
280+
249281
if (nsdSetting) {
250282
const nsdoc = this.parseToXmlObject(nsdSetting)!.querySelector('NSDoc');
251283
nsdVersion = nsdoc?.getAttribute('version');
@@ -273,6 +305,8 @@ export function Setting<TBase extends LitElementConstructor>(Base: TBase) {
273305

274306
registerTranslateConfig({ loader, empty: key => key });
275307
use(this.settings.language);
308+
309+
(<any>this).addEventListener('load-nsdoc', this.onLoadNsdoc);
276310
}
277311

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

0 commit comments

Comments
 (0)