From 7c6e281e9c8f9bce0b982711c5edb1a3a3886407 Mon Sep 17 00:00:00 2001 From: Dennis Labordus Date: Tue, 29 Mar 2022 10:41:39 +0200 Subject: [PATCH 1/5] Refactor loading NSDoc File through Custom Event. And added some integration tests. Signed-off-by: Dennis Labordus --- src/Logging.ts | 2 +- src/Setting.ts | 98 +- src/translations/de.ts | 5 +- src/translations/en.ts | 6 +- test/integration/Setting.test.ts | 81 ++ .../__snapshots__/Setting.test.snap.js | 1293 +++++++++++++++++ .../__snapshots__/open-scd.test.snap.js | 2 +- test/integration/open-scd.test.ts | 5 +- test/testfiles/nsdoc/IEC_61850-7-2.nsdoc | 7 + test/testfiles/nsdoc/invalid.nsdoc | 7 + test/testfiles/nsdoc/wrong-version.nsdoc | 7 + test/testfiles/settingTest.nsdoc | 3 - test/unit/Setting.test.ts | 14 +- 13 files changed, 1476 insertions(+), 54 deletions(-) create mode 100644 test/integration/Setting.test.ts create mode 100644 test/integration/__snapshots__/Setting.test.snap.js create mode 100644 test/testfiles/nsdoc/IEC_61850-7-2.nsdoc create mode 100644 test/testfiles/nsdoc/invalid.nsdoc create mode 100644 test/testfiles/nsdoc/wrong-version.nsdoc delete mode 100644 test/testfiles/settingTest.nsdoc diff --git a/src/Logging.ts b/src/Logging.ts index 25f1bd6aaa..0467b3632b 100644 --- a/src/Logging.ts +++ b/src/Logging.ts @@ -245,8 +245,8 @@ export function Logging(Base: TBase) { this.undo = this.undo.bind(this); this.redo = this.redo.bind(this); - this.onLog = this.onLog.bind(this); + this.addEventListener('log', this.onLog); this.addEventListener('issue', this.onIssue); this.addEventListener('open-doc', this.onLoadHistoryFromDoc); diff --git a/src/Setting.ts b/src/Setting.ts index 89569deef7..ccd2fbe9b6 100644 --- a/src/Setting.ts +++ b/src/Setting.ts @@ -12,7 +12,7 @@ import { Dialog } from '@material/mwc-dialog'; import { Select } from '@material/mwc-select'; import { Switch } from '@material/mwc-switch'; -import { ifImplemented, LitElementConstructor, Mixin, newLogEvent } from './foundation.js'; +import {ifImplemented, LitElementConstructor, Mixin, newLogEvent, OpenDocEvent} from './foundation.js'; import { Language, languages, loader } from './translations/loader.js'; import './WizardDivider.js'; @@ -54,6 +54,25 @@ type NsdVersions = { 'IEC 61850-8-1': NsdVersion; } +/** Represents a document to be opened. */ +export interface LoadNsdocDetail { + nsdoc: string; + filename: string; +} +export type LoadNsdocEvent = CustomEvent; +export function newLoadNsdocEvent( + nsdoc: string, + filename: string, + eventInitDict?: CustomEventInit> +): LoadNsdocEvent { + return new CustomEvent('load-nsdoc', { + bubbles: true, + composed: true, + ...eventInitDict, + detail: { nsdoc, filename, ...eventInitDict?.detail }, + }); +} + /** Mixin that saves [[`Settings`]] to `localStorage`, reflecting them in the * `settings` property, setting them through `setSetting(setting, value)`. */ export type SettingElement = Mixin; @@ -168,7 +187,7 @@ export function Setting(Base: TBase) { private renderFileSelect(): TemplateResult { return html ` this.loadNsdocFile(evt)}}> + @change=${(evt: Event) => this.uploadNsdocFile(evt)}}> { @@ -179,50 +198,63 @@ export function Setting(Base: TBase) { `; } - private async loadNsdocFile(evt: Event): Promise { - const nsdVersions = await this.nsdVersions(); + private async uploadNsdocFile(evt: Event): Promise { const files = Array.from( (evt.target)?.files ?? [] ); - + if (files.length == 0) return; - files.forEach(async file => { + for (const file of files) { const text = await file.text(); - const nsdocElement = this.parseToXmlObject(text).querySelector('NSDoc'); - const id = nsdocElement?.getAttribute('id'); - if (!id) { - document + document .querySelector('open-scd')! .dispatchEvent( - newLogEvent({ kind: 'error', title: get('settings.invalidFileNoIdFound') }) - ); - return; - } - const nsdVersion = nsdVersions[id as keyof NsdVersions]; - const nsdocVersion = { - version: nsdocElement!.getAttribute('version') ?? '', - revision: nsdocElement!.getAttribute('revision') ?? '', - release: nsdocElement!.getAttribute('release') ?? '' - } + newLoadNsdocEvent(text, file.name) + ); + } + + this.nsdocFileUI.value = ''; + this.requestUpdate(); + } + + private async onLoadNsdoc(event: LoadNsdocEvent) { + const nsdocElement = this.parseToXmlObject(event.detail.nsdoc).querySelector('NSDoc'); - if (!this.isEqual(nsdVersion, nsdocVersion)) { - document + const id = nsdocElement?.getAttribute('id'); + if (!id) { + document .querySelector('open-scd')! .dispatchEvent( - newLogEvent({ kind: 'error', title: get('settings.invalidNsdocVersion', { + newLogEvent({ kind: 'error', title: get('settings.invalidFileNoIdFound', { + filename: event.detail.filename + }) }) + ); + return; + } + + const nsdVersions = await this.nsdVersions(); + const nsdVersion = nsdVersions[id as keyof NsdVersions]; + const nsdocVersion = { + version: nsdocElement!.getAttribute('version') ?? '', + revision: nsdocElement!.getAttribute('revision') ?? '', + release: nsdocElement!.getAttribute('release') ?? '' + } + + if (!this.isEqual(nsdVersion, nsdocVersion)) { + document + .querySelector('open-scd')! + .dispatchEvent( + newLogEvent({ kind: 'error', title: get('settings.invalidNsdocVersion', { id: id, + filename: event.detail.filename, nsdVersion: `${nsdVersion.version}${nsdVersion.revision}${nsdVersion.release}`, nsdocVersion: `${nsdocVersion.version}${nsdocVersion.revision}${nsdocVersion.release}` }) }) - ); - return; - } - - this.setSetting(id as keyof Settings, text); - }) + ); + return; + } - this.nsdocFileUI.value = ''; - this.requestUpdate(); + this.setSetting(id as keyof Settings, event.detail.nsdoc); } /** @@ -245,7 +277,7 @@ export function Setting(Base: TBase) { let nsdVersion: string | undefined | null; let nsdRevision: string | undefined | null; let nsdRelease: string | undefined | null; - + if (nsdSetting) { const nsdoc = this.parseToXmlObject(nsdSetting)!.querySelector('NSDoc'); nsdVersion = nsdoc?.getAttribute('version'); @@ -273,6 +305,8 @@ export function Setting(Base: TBase) { registerTranslateConfig({ loader, empty: key => key }); use(this.settings.language); + + (this).addEventListener('load-nsdoc', this.onLoadNsdoc); } render(): TemplateResult { diff --git a/src/translations/de.ts b/src/translations/de.ts index 3310787e61..f51ec246a1 100644 --- a/src/translations/de.ts +++ b/src/translations/de.ts @@ -70,10 +70,9 @@ export const de: Translations = { showieds: 'Zeige IEDs im Substation-Editor', selectFileButton: 'Datei auswählen', loadNsdTranslations: 'NSDoc-Dateien hochladen', - invalidFileNoIdFound: - "Ungültiges NSDoc; kein 'id'-Attribut in der Datei gefunden", + invalidFileNoIdFound: "Ungültiges NSDoc ({{ filename }}); kein 'id'-Attribut in der Datei gefunden", invalidNsdocVersion: - 'Die Version {{ id }} NSD ({{ nsdVersion }}) passt nicht zu der geladenen NSDoc ({{ nsdocVersion }})', + 'Die Version {{ id }} NSD ({{ nsdVersion }}) passt nicht zu der geladenen NSDoc ({{ filename }}, {{ nsdocVersion }})', }, menu: { new: 'Neues projekt', diff --git a/src/translations/en.ts b/src/translations/en.ts index 3182a72387..f5d6cd5c91 100644 --- a/src/translations/en.ts +++ b/src/translations/en.ts @@ -67,10 +67,10 @@ export const en = { mode: 'Pro mode', showieds: 'Show IEDs in substation editor', selectFileButton: 'Select file', - loadNsdTranslations: 'Uploading NSDoc files', - invalidFileNoIdFound: "Invalid NSDoc; no 'id' attribute found in file", + loadNsdTranslations: 'Uploaded NSDoc files', + invalidFileNoIdFound: "Invalid NSDoc ({{ filename }}); no 'id' attribute found in file", invalidNsdocVersion: - 'The version of {{ id }} NSD ({{ nsdVersion }}) does not correlate with the version of the corresponding NSDoc ({{ nsdocVersion }})', + 'The version of {{ id }} NSD ({{ nsdVersion }}) does not correlate with the version of the corresponding NSDoc ({{ filename }}, {{ nsdocVersion }})', }, menu: { new: 'New project', diff --git a/test/integration/Setting.test.ts b/test/integration/Setting.test.ts new file mode 100644 index 0000000000..a52250bfd5 --- /dev/null +++ b/test/integration/Setting.test.ts @@ -0,0 +1,81 @@ +import { html, fixture, expect } from '@open-wc/testing'; + +import '../../src/open-scd.js'; +import { OpenSCD } from '../../src/open-scd.js'; +import { newLoadNsdocEvent } from "../../src/Setting.js"; + +describe('Setting', () => { + let element: OpenSCD; + + beforeEach(async () => { + element = await fixture(html` + + + + + + `); + }); + + it('opens the log on log menu entry click', async () => { + await (( + element.shadowRoot!.querySelector('mwc-list-item[iconid="history"]')! + )).click(); + expect(element.logUI).to.have.property('open', true); + }); + + it('upload .nsdoc file using event and looks like latest snapshot', async () => { + element.settingsUI.show(); + await element.settingsUI.updateComplete; + + const nsdocFile = await fetch('/test/testfiles/nsdoc/IEC_61850-7-2.nsdoc') + .then(response => response.text()) + + element.dispatchEvent( + newLoadNsdocEvent(nsdocFile, 'IEC_61850-7-2.nsdoc') + ); + + await element.requestUpdate(); + await element.updateComplete; + + expect(localStorage.getItem('IEC 61850-7-2')).to.eql(nsdocFile); + expect(element).shadowDom.to.equalSnapshot(); + }); + + it('upload invalid .nsdoc file using event and log event fired', async () => { + element.settingsUI.show(); + await element.settingsUI.updateComplete; + + const nsdocFile = await fetch('/test/testfiles/nsdoc/invalid.nsdoc') + .then(response => response.text()) + + element.dispatchEvent( + newLoadNsdocEvent(nsdocFile, 'invalid.nsdoc') + ); + + await element.requestUpdate(); + await element.updateComplete; + + expect(element.history.length).to.be.equal(1); + expect(element.history[0].title).to.be.equal('Invalid NSDoc (invalid.nsdoc); no \'id\' attribute found in file'); + }); + + it('upload .nsdoc file with wrong version using event and log event fired', async () => { + element.settingsUI.show(); + await element.settingsUI.updateComplete; + + const nsdocFile = await fetch('/test/testfiles/nsdoc/wrong-version.nsdoc') + .then(response => response.text()) + + element.dispatchEvent( + newLoadNsdocEvent(nsdocFile, 'wrong-version.nsdoc') + ); + + await element.requestUpdate(); + await element.updateComplete; + + expect(element.history.length).to.be.equal(1); + expect(element.history[0].title).to.be.equal('The version of IEC 61850-7-3 NSD (2007B3) does not correlate ' + + 'with the version of the corresponding NSDoc (wrong-version.nsdoc, 2007B4)'); + }); +}).timeout(4000); diff --git a/test/integration/__snapshots__/Setting.test.snap.js b/test/integration/__snapshots__/Setting.test.snap.js new file mode 100644 index 0000000000..08ab15631e --- /dev/null +++ b/test/integration/__snapshots__/Setting.test.snap.js @@ -0,0 +1,1293 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["Setting upload .nsdoc file using event and looks like latest snapshot"] = +` + + Menu + + +
  • +
  • + + + folder_open + + + Open project + + + + + + + create_new_folder + + + New project + + + + + + + save + + + Save project + + + + +
  • +
  • + + + undo + + + Undo + + + + + redo + + + Redo + + + + + rule_folder + + + Validate project + + + + + + + rule_folder + + + Validate Templates + + + + + + + history + + + View log + + + + + rule + + + View diagnostics + + +
  • +
  • + + + snippet_folder + + + Import IEDs + + + + + + + play_circle + + + Subscriber Update + + + + + + + merge_type + + + Merge Project + + + + + + + merge_type + + + Update Substation + + + + +
  • +
  • + + + settings + + + Settings + + + + + help + + + Help + + + + +
  • +
  • + + + extension + + + Extensions + + +
    + + + +
    +
    + + + + + + + + +
    +
    +
    + +
    + Open project +
    +
    + +
    + New project +
    +
    +
    + + + + + + + + + + + + + + + Edits, errors, and other notifications will show up here. + + + info + + + + + + + + + Close + + + + + + + Issues found during validation will show up here + + + info + + + + + Close + + + + + + + + + Show + + + + + + + Show + + + + + + + Show + + + + + + + + + Editor tab + + + tab + + +
  • +
  • + + + margin + + Substation + + + + developer_board + + IED + + + + edit + + Single Line Diagram + + + + link + + Subscription + + + + link + + Sampled Values Subscriber + + + + settings_ethernet + + Communication + + + + copy_all + + Templates + + + + cleaning_services + + Cleanup + + + + Menu entry + + + + play_circle + + + +
  • +
  • + + + folder_open + + Open project + + + + create_new_folder + + New project + + + + save + + Save project + +
  • +
  • + + + rule_folder + + Validate project + + + + rule_folder + + Validate Templates + +
  • +
  • + + + snippet_folder + + Import IEDs + + + + play_circle + + Subscriber Update + + + + play_circle + + Update desc (ABB) + + + + play_circle + + Update desc (SEL) + + + + merge_type + + Merge Project + + + + merge_type + + Update Substation + +
  • +
  • + + + help + + Help + +
    + + + + + + +
    + +
    +

    + Here you may add remote extensions directly from a custom URL. + You do this at your own risk. +

    + + + + + Editor tab + + tab + + + + Menu entry + + play_circle + + + + + Validator + + rule_folder + + + + + +
    + + + + +
    + + + + + +
    + + + English + + + German (Deutsch) + + + + + + + + + + + + + + +
    + + +
    +

    + Uploaded NSDoc files +

    + + + +
    + + + + IEC 61850-7-2 + + + 2007B3 + + + done + + + delete + + + + + IEC 61850-7-3 + + + 1010X1 + + + done + + + delete + + + + + IEC 61850-7-4 + + + 2007B3 + + + done + + + delete + + + + + IEC 61850-8-1 + + + 1010X1 + + + done + + + delete + + + + + Cancel + + + Reset + + + Save + +
    +`; +/* end snapshot Setting upload .nsdoc file using event and looks like latest snapshot */ + diff --git a/test/integration/__snapshots__/open-scd.test.snap.js b/test/integration/__snapshots__/open-scd.test.snap.js index 1729df09d5..f5e924598e 100644 --- a/test/integration/__snapshots__/open-scd.test.snap.js +++ b/test/integration/__snapshots__/open-scd.test.snap.js @@ -1135,7 +1135,7 @@ snapshots["open-scd looks like its snapshot"] =

    - Uploading NSDoc files + Uploaded NSDoc files

    { - + `); }); diff --git a/test/testfiles/nsdoc/IEC_61850-7-2.nsdoc b/test/testfiles/nsdoc/IEC_61850-7-2.nsdoc new file mode 100644 index 0000000000..d10a9893cb --- /dev/null +++ b/test/testfiles/nsdoc/IEC_61850-7-2.nsdoc @@ -0,0 +1,7 @@ + + + diff --git a/test/testfiles/nsdoc/invalid.nsdoc b/test/testfiles/nsdoc/invalid.nsdoc new file mode 100644 index 0000000000..99f4ab6443 --- /dev/null +++ b/test/testfiles/nsdoc/invalid.nsdoc @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/testfiles/nsdoc/wrong-version.nsdoc b/test/testfiles/nsdoc/wrong-version.nsdoc new file mode 100644 index 0000000000..4260851f12 --- /dev/null +++ b/test/testfiles/nsdoc/wrong-version.nsdoc @@ -0,0 +1,7 @@ + + + diff --git a/test/testfiles/settingTest.nsdoc b/test/testfiles/settingTest.nsdoc deleted file mode 100644 index fdaef2cebf..0000000000 --- a/test/testfiles/settingTest.nsdoc +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/test/unit/Setting.test.ts b/test/unit/Setting.test.ts index 6463e40ddd..01afda0283 100644 --- a/test/unit/Setting.test.ts +++ b/test/unit/Setting.test.ts @@ -52,12 +52,12 @@ describe('SettingElement', () => { it('saves chosen .nsdoc file and looks like latest snapshot', async () => { element.settingsUI.show(); await element.settingsUI.updateComplete; - - const nsdocFile = await fetch('/test/testfiles/settingTest.nsdoc') + + const nsdocFile = await fetch('/test/testfiles/nsdoc/IEC_61850-7-2.nsdoc') .then(response => response.text()) element.setSetting('IEC 61850-7-2', nsdocFile); - + await element.requestUpdate(); await element.updateComplete; @@ -68,19 +68,19 @@ describe('SettingElement', () => { it('deletes a chosen .nsdoc file and looks like latest snapshot', async () => { element.settingsUI.show(); await element.settingsUI.updateComplete; - - const nsdocFile = await fetch('/test/testfiles/settingTest.nsdoc') + + const nsdocFile = await fetch('/test/testfiles/nsdoc/IEC_61850-7-2.nsdoc') .then(response => response.text()) element.setSetting('IEC 61850-7-2', nsdocFile); - + await element.requestUpdate(); await element.updateComplete; (