From 2b4a93f47935c6509421c2d803802102e73db87c Mon Sep 17 00:00:00 2001 From: Jakob Vogelsang Date: Mon, 17 Jan 2022 20:00:32 +0100 Subject: [PATCH 1/2] feat(wizards/reportcontrol): access edit wizard from select wizard --- src/foundation.ts | 6 + src/wizards/reportcontrol.ts | 16 ++ src/zeroline-pane.ts | 9 +- src/zeroline/ied-editor.ts | 7 +- .../reportcontrol-wizarding-editing.test.ts | 143 ++++++++++++++++++ 5 files changed, 175 insertions(+), 6 deletions(-) create mode 100644 test/integration/wizards/reportcontrol-wizarding-editing.test.ts diff --git a/src/foundation.ts b/src/foundation.ts index ed639b97a4..e2de6e75bc 100644 --- a/src/foundation.ts +++ b/src/foundation.ts @@ -235,6 +235,12 @@ export function newWizardEvent( }); } +export function newSubWizardEvent( + wizardOrFactory?: Wizard | WizardFactory +): WizardEvent { + return newWizardEvent(wizardOrFactory, { detail: { subwizard: true } }); +} + type InfoEntryKind = 'info' | 'warning' | 'error'; export type LogEntryType = diff --git a/src/wizards/reportcontrol.ts b/src/wizards/reportcontrol.ts index 1d9f330ce2..651c1fa8b0 100644 --- a/src/wizards/reportcontrol.ts +++ b/src/wizards/reportcontrol.ts @@ -3,6 +3,9 @@ import { get, translate } from 'lit-translate'; import '@material/mwc-button'; import '@material/mwc-list/mwc-list-item'; +import { List } from '@material/mwc-list'; +import { ListItemBase } from '@material/mwc-list/mwc-list-item-base'; +import { SingleSelectedEvent } from '@material/mwc-list/mwc-list-foundation'; import '../wizard-textfield.js'; import '../wizard-select.js'; @@ -15,6 +18,8 @@ import { getValue, identity, isPublic, + newSubWizardEvent, + selector, SimpleAction, Wizard, WizardActor, @@ -230,6 +235,17 @@ export function selectReportControlWizard(element: Element): Wizard { title: get('wizard.title.select', { tagName: 'ReportControl' }), content: [ html` { + const identity = ((e.target).selected).value; + const reportControl = element.querySelector( + selector('ReportControl', identity) + ); + if (!reportControl) return; + + e.target?.dispatchEvent( + newSubWizardEvent(() => editReportControlWizard(reportControl)) + ); + }} >${reportControls.map( reportControl => html` + selectReportControlWizard(this.doc.documentElement) + ) + ); } openGseControlSelection(): void { diff --git a/src/zeroline/ied-editor.ts b/src/zeroline/ied-editor.ts index a358519fea..40e7589521 100644 --- a/src/zeroline/ied-editor.ts +++ b/src/zeroline/ied-editor.ts @@ -14,7 +14,7 @@ import { Fab } from '@material/mwc-fab'; import '../action-icon.js'; import { createClientLnWizard } from '../wizards/clientln.js'; import { gooseIcon, smvIcon, reportIcon } from '../icons.js'; -import { newWizardEvent } from '../foundation.js'; +import { newSubWizardEvent, newWizardEvent } from '../foundation.js'; import { selectGseControlWizard } from '../wizards/gsecontrol.js'; import { selectSampledValueControlWizard } from '../wizards/sampledvaluecontrol.js'; import { selectReportControlWizard } from '../wizards/reportcontrol.js'; @@ -34,8 +34,9 @@ export class IedEditor extends LitElement { @query('.connectreport') connectReport!: Fab; private openReportControlSelection(): void { - const wizard = selectReportControlWizard(this.element); - if (wizard) this.dispatchEvent(newWizardEvent(wizard)); + this.dispatchEvent( + newSubWizardEvent(() => selectReportControlWizard(this.element)) + ); } private openGseControlSelection(): void { diff --git a/test/integration/wizards/reportcontrol-wizarding-editing.test.ts b/test/integration/wizards/reportcontrol-wizarding-editing.test.ts new file mode 100644 index 0000000000..2cdb0b3354 --- /dev/null +++ b/test/integration/wizards/reportcontrol-wizarding-editing.test.ts @@ -0,0 +1,143 @@ +import { expect, fixture, html } from '@open-wc/testing'; + +import '../../mock-wizard-editor.js'; +import { MockWizardEditor } from '../../mock-wizard-editor.js'; + +import { ListItemBase } from '@material/mwc-list/mwc-list-item-base'; + +import { FilteredList } from '../../../src/filtered-list.js'; +import { WizardTextField } from '../../../src/wizard-textfield.js'; +import { selectReportControlWizard } from '../../../src/wizards/reportcontrol.js'; + +describe('Wizards for SCL element ReportControl', () => { + let doc: XMLDocument; + let element: MockWizardEditor; + + beforeEach(async () => { + element = await fixture(html``); + doc = await fetch('/test/testfiles/wizards/reportcontrol.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + }); + + describe('define a select wizards that ', () => { + let reportControlList: FilteredList; + + beforeEach(async () => { + const wizard = selectReportControlWizard(doc.documentElement); + element.workflow.push(() => wizard); + await element.requestUpdate(); + + reportControlList = ( + element.wizardUI.dialog?.querySelector('filtered-list') + ); + await reportControlList.updateComplete; + }); + + it('shows all ReportControl elements within a project', () => + expect(reportControlList.items.length).to.equal( + doc.querySelectorAll('ReportControl').length + )); + + it('allows to filter ReportControl elements per IED', async () => { + const wizard = selectReportControlWizard(doc.querySelector('IED')!); + element.workflow.unshift(); + element.workflow.push(() => wizard); + await element.requestUpdate(); + + expect(reportControlList.items.length).to.equal( + doc.querySelector('IED')!.querySelectorAll('ReportControl').length + ); + }); + + it('opens edit wizard for selected ReportControl element on click', async () => { + const gse2 = reportControlList.items[1]; + gse2.click(); + await new Promise(resolve => setTimeout(resolve, 20)); // await animation + + const nameField = ( + element.wizardUI.dialog?.querySelector('wizard-textfield[label="name"]') + ); + await nameField.requestUpdate(); + + expect(nameField.value).to.equal( + doc.querySelectorAll('ReportControl')[1].getAttribute('name') + ); + }); + }); + + describe('defines an edit wizard that', () => { + let nameField: WizardTextField; + let secondaryAction: HTMLElement; + let primaryAction: HTMLElement; + let reportControl: Element; + + beforeEach(async () => { + reportControl = doc.querySelector('IED')!; + element.workflow.push(() => selectReportControlWizard(reportControl)); + await element.requestUpdate(); + await new Promise(resolve => setTimeout(resolve, 20)); // await animation + + const report = ( + (element.wizardUI.dialog?.querySelector('filtered-list')) + .items[0] + ); + report.click(); + await new Promise(resolve => setTimeout(resolve, 20)); // await animation + + nameField = element.wizardUI.dialog!.querySelector( + 'wizard-textfield[label="name"]' + )!; + primaryAction = ( + element.wizardUI.dialog?.querySelector( + 'mwc-button[slot="primaryAction"]' + ) + ); + secondaryAction = ( + element.wizardUI.dialog?.querySelector( + 'mwc-button[slot="secondaryAction"]' + ) + ); + await nameField.updateComplete; + }); + + it('rejects name attribute starting with decimals', async () => { + nameField.value = '4adsasd'; + primaryAction.click(); + expect(reportControl.getAttribute('name')).to.not.equal('4adsasd'); + }); + + it('edits name attribute on primary action', async () => { + nameField.value = 'myNewName'; + primaryAction.click(); + expect(reportControl.getAttribute('name')).to.not.equal('myNewName'); + }); + + it('dynamically updates wizards after attribute change', async () => { + nameField.value = 'myNewName'; + primaryAction.click(); + + await new Promise(resolve => setTimeout(resolve, 100)); // await animation + + const report = ( + (element.wizardUI.dialog?.querySelector('filtered-list')) + .items[0] + ); + + expect(report.innerHTML).to.contain('myNewName'); + }); + + it('returns back to its starting wizard on secondary action', async () => { + secondaryAction.click(); + + await new Promise(resolve => setTimeout(resolve, 100)); // await animation + + const report = ( + (element.wizardUI.dialog?.querySelector('filtered-list')) + .items[0] + ); + + expect(report.innerHTML).to.contain('ReportCb'); + }); + }); +}); From e9497beeb3f92994ab5dd5ad1aa2baed35718a21 Mon Sep 17 00:00:00 2001 From: Jakob Vogelsang Date: Tue, 18 Jan 2022 15:43:31 +0100 Subject: [PATCH 2/2] test(wizards/reportcontrol): fix issues found in review --- .../reportcontrol-wizarding-editing.test.ts | 37 ++++++-- test/testfiles/wizards/reportcontrol.scd | 84 +++++++++++++++++++ .../__snapshots__/reportcontrol.test.snap.js | 28 +++++++ 3 files changed, 141 insertions(+), 8 deletions(-) diff --git a/test/integration/wizards/reportcontrol-wizarding-editing.test.ts b/test/integration/wizards/reportcontrol-wizarding-editing.test.ts index 2cdb0b3354..32dd3a8faf 100644 --- a/test/integration/wizards/reportcontrol-wizarding-editing.test.ts +++ b/test/integration/wizards/reportcontrol-wizarding-editing.test.ts @@ -41,18 +41,23 @@ describe('Wizards for SCL element ReportControl', () => { it('allows to filter ReportControl elements per IED', async () => { const wizard = selectReportControlWizard(doc.querySelector('IED')!); - element.workflow.unshift(); + element.workflow.pop(); element.workflow.push(() => wizard); await element.requestUpdate(); + reportControlList = ( + element.wizardUI.dialog?.querySelector('filtered-list') + ); + await reportControlList.updateComplete; + expect(reportControlList.items.length).to.equal( doc.querySelector('IED')!.querySelectorAll('ReportControl').length ); }); it('opens edit wizard for selected ReportControl element on click', async () => { - const gse2 = reportControlList.items[1]; - gse2.click(); + const reportItem = reportControlList.items[1]; + reportItem.click(); await new Promise(resolve => setTimeout(resolve, 20)); // await animation const nameField = ( @@ -70,11 +75,11 @@ describe('Wizards for SCL element ReportControl', () => { let nameField: WizardTextField; let secondaryAction: HTMLElement; let primaryAction: HTMLElement; - let reportControl: Element; + let parentIED: Element; beforeEach(async () => { - reportControl = doc.querySelector('IED')!; - element.workflow.push(() => selectReportControlWizard(reportControl)); + parentIED = doc.querySelector('IED')!; + element.workflow.push(() => selectReportControlWizard(parentIED)); await element.requestUpdate(); await new Promise(resolve => setTimeout(resolve, 20)); // await animation @@ -102,15 +107,31 @@ describe('Wizards for SCL element ReportControl', () => { }); it('rejects name attribute starting with decimals', async () => { + expect( + parentIED.querySelector('ReportControl')?.getAttribute('name') + ).to.not.equal('4adsasd'); + nameField.value = '4adsasd'; + await element.requestUpdate(); primaryAction.click(); - expect(reportControl.getAttribute('name')).to.not.equal('4adsasd'); + + expect( + parentIED.querySelector('ReportControl')?.getAttribute('name') + ).to.not.equal('4adsasd'); }); it('edits name attribute on primary action', async () => { + expect( + parentIED.querySelector('ReportControl')?.getAttribute('name') + ).to.not.equal('myNewName'); + nameField.value = 'myNewName'; + await element.requestUpdate(); primaryAction.click(); - expect(reportControl.getAttribute('name')).to.not.equal('myNewName'); + + expect( + parentIED.querySelector('ReportControl')?.getAttribute('name') + ).to.equal('myNewName'); }); it('dynamically updates wizards after attribute change', async () => { diff --git a/test/testfiles/wizards/reportcontrol.scd b/test/testfiles/wizards/reportcontrol.scd index f34ab84548..1d2874926e 100644 --- a/test/testfiles/wizards/reportcontrol.scd +++ b/test/testfiles/wizards/reportcontrol.scd @@ -126,4 +126,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + status-only + + + + + + + + + + + + + + + status-only + + + + + + + + + + + status-only + + + + + + + + diff --git a/test/unit/wizards/__snapshots__/reportcontrol.test.snap.js b/test/unit/wizards/__snapshots__/reportcontrol.test.snap.js index c8eb4f4e33..6c29bd7141 100644 --- a/test/unit/wizards/__snapshots__/reportcontrol.test.snap.js +++ b/test/unit/wizards/__snapshots__/reportcontrol.test.snap.js @@ -180,6 +180,34 @@ snapshots["Wizards for SCL ReportControl element define a select wizard that loo IED2>>CBSW> XSWI 2>ReportCb3 + + + ReportCb + + + IED3>>CBSW>ReportCb + + + + + ReportCb2 + + + IED3>>CBSW> XSWI 1>ReportCb2 + +