diff --git a/src/editors/substation/conducting-equipment-editor.ts b/src/editors/substation/conducting-equipment-editor.ts index 74cd41747..d89799713 100644 --- a/src/editors/substation/conducting-equipment-editor.ts +++ b/src/editors/substation/conducting-equipment-editor.ts @@ -4,6 +4,7 @@ import { html, LitElement, property, + query, TemplateResult, } from 'lit-element'; import { translate } from 'lit-translate'; @@ -11,6 +12,10 @@ import { translate } from 'lit-translate'; import '@material/mwc-fab'; import '@material/mwc-icon'; import '@material/mwc-icon-button'; +import '@material/mwc-menu'; +import { Menu } from '@material/mwc-menu'; +import { IconButton } from '@material/mwc-icon-button'; +import { ListItem } from '@material/mwc-list/mwc-list-item'; import '../../action-icon.js'; import '../../action-pane.js'; @@ -21,9 +26,19 @@ import { getChildElementsByTagName, newActionEvent, newWizardEvent, + SCLTag, + tags, } from '../../foundation.js'; import { BayEditor } from './bay-editor.js'; -import { wizards } from '../../wizards/wizard-library.js'; +import { emptyWizard, wizards } from '../../wizards/wizard-library.js'; + +function childTags(element: Element | null | undefined): SCLTag[] { + if (!element) return []; + + return tags[element.tagName].children.filter( + child => wizards[child].create !== emptyWizard + ); +} /** [[`SubstationEditor`]] subeditor for a `ConductingEquipment` element. */ @customElement('conducting-equipment-editor') @@ -40,6 +55,9 @@ export class ConductingEquipmentEditor extends LitElement { @property({ type: Boolean }) showfunctions = false; + @query('mwc-menu') addMenu!: Menu; + @query('mwc-icon-button[icon="playlist_add"]') addButton!: IconButton; + private openEditWizard(): void { const wizard = wizards['ConductingEquipment'].edit(this.element); if (wizard) this.dispatchEvent(newWizardEvent(wizard)); @@ -50,6 +68,12 @@ export class ConductingEquipmentEditor extends LitElement { if (wizard) this.dispatchEvent(newWizardEvent(wizard)); } + private openCreateWizard(tagName: string): void { + const wizard = wizards[tagName].create(this.element!); + + if (wizard) this.dispatchEvent(newWizardEvent(wizard)); + } + remove(): void { if (this.element) this.dispatchEvent( @@ -63,6 +87,11 @@ export class ConductingEquipmentEditor extends LitElement { ); } + firstUpdated(): void { + if (this.addMenu && this.addButton) + this.addMenu.anchor = this.addButton; + } + private renderLNodes(): TemplateResult { const lNodes = getChildElementsByTagName(this.element, 'LNode'); @@ -85,6 +114,15 @@ export class ConductingEquipmentEditor extends LitElement { )}`; } + private renderAddButtons(): TemplateResult[] { + return childTags(this.element).map( + child => + html`${child}` + ); + } + renderContentPane(): TemplateResult { return html`${getIcon(this.element)} - `; + > + (this.addMenu.open = true)} + > { + const tagName = ((e.target).selected).value; + this.openCreateWizard(tagName); + }} + >${this.renderAddButtons()} + `; } renderContentIcon(): TemplateResult { diff --git a/src/editors/substation/eq-function-editor.ts b/src/editors/substation/eq-function-editor.ts index 8cf005db3..bb248d540 100644 --- a/src/editors/substation/eq-function-editor.ts +++ b/src/editors/substation/eq-function-editor.ts @@ -6,11 +6,34 @@ import { customElement, state, css, + query, } from 'lit-element'; +import { translate } from 'lit-translate'; + +import '@material/mwc-icon-button'; +import '@material/mwc-list/mwc-list-item'; +import '@material/mwc-menu'; +import { IconButton } from '@material/mwc-icon-button'; +import { ListItem } from '@material/mwc-list/mwc-list-item'; +import { Menu } from '@material/mwc-menu'; import '../../action-pane.js'; import './eq-sub-function-editor.js'; -import { getChildElementsByTagName } from '../../foundation.js'; +import { + getChildElementsByTagName, + newWizardEvent, + SCLTag, + tags, +} from '../../foundation.js'; +import { emptyWizard, wizards } from '../../wizards/wizard-library.js'; + +function childTags(element: Element | null | undefined): SCLTag[] { + if (!element) return []; + + return tags[element.tagName].children.filter( + child => wizards[child].create !== emptyWizard + ); +} /** Pane rendering `EqFunction` element with its children */ @customElement('eq-function-editor') @@ -27,6 +50,19 @@ export class EqFunctionEditor extends LitElement { return `${name}${desc ? ` - ${desc}` : ''}${type ? ` (${type})` : ''}`; } + @query('mwc-menu') addMenu!: Menu; + @query('mwc-icon-button[icon="playlist_add"]') addButton!: IconButton; + + private openCreateWizard(tagName: string): void { + const wizard = wizards[tagName].create(this.element!); + + if (wizard) this.dispatchEvent(newWizardEvent(wizard)); + } + + firstUpdated(): void { + this.addMenu.anchor = this.addButton; + } + private renderLNodes(): TemplateResult { const lNodes = getChildElementsByTagName(this.element, 'LNode'); @@ -52,12 +88,39 @@ export class EqFunctionEditor extends LitElement { )}`; } + private renderAddButtons(): TemplateResult[] { + return childTags(this.element).map( + child => + html`${child}` + ); + } + render(): TemplateResult { return html` + (this.addMenu.open = true)} + > { + const tagName = ((e.target).selected).value; + this.openCreateWizard(tagName); + }} + >${this.renderAddButtons()}${this.renderLNodes()}${this.renderEqSubFunctions()}`; } diff --git a/src/editors/substation/eq-sub-function-editor.ts b/src/editors/substation/eq-sub-function-editor.ts index 95f49bc8d..5d0d9ad11 100644 --- a/src/editors/substation/eq-sub-function-editor.ts +++ b/src/editors/substation/eq-sub-function-editor.ts @@ -6,11 +6,34 @@ import { customElement, state, css, + query, } from 'lit-element'; +import { translate } from 'lit-translate'; + +import '@material/mwc-icon-button'; +import '@material/mwc-list/mwc-list-item'; +import '@material/mwc-menu'; +import { IconButton } from '@material/mwc-icon-button'; +import { ListItem } from '@material/mwc-list/mwc-list-item'; +import { Menu } from '@material/mwc-menu'; + import '../../action-pane.js'; -import { getChildElementsByTagName } from '../../foundation.js'; +import { + getChildElementsByTagName, + newWizardEvent, + SCLTag, + tags, +} from '../../foundation.js'; +import { emptyWizard, wizards } from '../../wizards/wizard-library.js'; +function childTags(element: Element | null | undefined): SCLTag[] { + if (!element) return []; + + return tags[element.tagName].children.filter( + child => wizards[child].create !== emptyWizard + ); +} /** Pane rendering `EqSubFunction` element with its children */ @customElement('eq-sub-function-editor') export class EqSubFunctionEditor extends LitElement { @@ -26,6 +49,31 @@ export class EqSubFunctionEditor extends LitElement { return `${name}${desc ? ` - ${desc}` : ''}${type ? ` (${type})` : ''}`; } + @query('mwc-menu') addMenu!: Menu; + @query('mwc-icon-button[icon="playlist_add"]') addButton!: IconButton; + + private openCreateWizard(tagName: string): void { + const wizard = wizards[tagName].create(this.element!); + + if (wizard) this.dispatchEvent(newWizardEvent(wizard)); + } + + firstUpdated(): void { + this.addMenu.anchor = this.addButton; + } + + private renderLNodes(): TemplateResult { + const lNodes = getChildElementsByTagName(this.element, 'LNode'); + + return lNodes.length + ? html`
+ ${lNodes.map( + lNode => html`` + )} +
` + : html``; + } + private renderEqSubFunctions(): TemplateResult { const eqSubFunctions = getChildElementsByTagName( this.element, @@ -39,20 +87,35 @@ export class EqSubFunctionEditor extends LitElement { )}`; } - private renderLNodes(): TemplateResult { - const lNodes = getChildElementsByTagName(this.element, 'LNode'); - - return lNodes.length - ? html`
- ${lNodes.map( - lNode => html`` - )} -
` - : html``; + private renderAddButtons(): TemplateResult[] { + return childTags(this.element).map( + child => + html`${child}` + ); } render(): TemplateResult { return html` + (this.addMenu.open = true)} + > { + const tagName = ((e.target).selected).value; + this.openCreateWizard(tagName); + }} + >${this.renderAddButtons()}${this.renderLNodes()}${this.renderEqSubFunctions()}`; } diff --git a/src/editors/substation/function-editor.ts b/src/editors/substation/function-editor.ts index bb646d20a..af3d7214c 100644 --- a/src/editors/substation/function-editor.ts +++ b/src/editors/substation/function-editor.ts @@ -6,11 +6,30 @@ import { customElement, state, css, + query, } from 'lit-element'; import '../../action-pane.js'; import './sub-function-editor.js'; -import { getChildElementsByTagName } from '../../foundation.js'; +import { + getChildElementsByTagName, + newWizardEvent, + SCLTag, + tags, +} from '../../foundation.js'; +import { translate } from 'lit-translate'; +import { emptyWizard, wizards } from '../../wizards/wizard-library.js'; +import { Menu } from '@material/mwc-menu'; +import { ListItem } from '@material/mwc-list/mwc-list-item'; +import { IconButton } from '@material/mwc-icon-button'; + +function childTags(element: Element | null | undefined): SCLTag[] { + if (!element) return []; + + return tags[element.tagName].children.filter( + child => wizards[child].create !== emptyWizard + ); +} /** Pane rendering `Function` element with its children */ @customElement('function-editor') @@ -27,6 +46,19 @@ export class FunctionEditor extends LitElement { return `${name}${desc ? ` - ${desc}` : ''}${type ? ` (${type})` : ''}`; } + @query('mwc-menu') addMenu!: Menu; + @query('mwc-icon-button[icon="playlist_add"]') addButton!: IconButton; + + private openCreateWizard(tagName: string): void { + const wizard = wizards[tagName].create(this.element!); + + if (wizard) this.dispatchEvent(newWizardEvent(wizard)); + } + + firstUpdated(): void { + this.addMenu.anchor = this.addButton; + } + private renderLNodes(): TemplateResult { const lNodes = getChildElementsByTagName(this.element, 'LNode'); @@ -49,12 +81,39 @@ export class FunctionEditor extends LitElement { )}`; } + private renderAddButtons(): TemplateResult[] { + return childTags(this.element).map( + child => + html`${child}` + ); + } + render(): TemplateResult { return html` + (this.addMenu.open = true)} + > { + const tagName = ((e.target).selected).value; + this.openCreateWizard(tagName); + }} + >${this.renderAddButtons()} ${this.renderLNodes()}${this.renderSubFunctions()}`; } diff --git a/src/editors/substation/powertransformer-editor.ts b/src/editors/substation/powertransformer-editor.ts index 81db57c03..bf5a79819 100644 --- a/src/editors/substation/powertransformer-editor.ts +++ b/src/editors/substation/powertransformer-editor.ts @@ -4,6 +4,7 @@ import { html, LitElement, property, + query, TemplateResult, } from 'lit-element'; import { translate } from 'lit-translate'; @@ -11,21 +12,35 @@ import { translate } from 'lit-translate'; import '@material/mwc-fab'; import '@material/mwc-icon'; import '@material/mwc-icon-button'; +import '@material/mwc-menu'; +import { IconButton } from '@material/mwc-icon-button'; +import { ListItem } from '@material/mwc-list/mwc-list-item'; +import { Menu } from '@material/mwc-menu'; import '../../action-icon.js'; import '../../action-pane.js'; import { powerTransformerTwoWindingIcon } from '../../icons/icons.js'; -import { wizards } from '../../wizards/wizard-library.js'; +import { emptyWizard, wizards } from '../../wizards/wizard-library.js'; import { getChildElementsByTagName, newActionEvent, newWizardEvent, + SCLTag, + tags, } from '../../foundation.js'; import { startMove, styles } from './foundation.js'; import { SubstationEditor } from './substation-editor.js'; import { BayEditor } from './bay-editor.js'; import { VoltageLevelEditor } from './voltage-level-editor.js'; +function childTags(element: Element | null | undefined): SCLTag[] { + if (!element) return []; + + return tags[element.tagName].children.filter( + child => wizards[child].create !== emptyWizard + ); +} + /** [[`SubstationEditor`]] subeditor for a child-less `PowerTransformer` element. */ @customElement('powertransformer-editor') export class PowerTransformerEditor extends LitElement { @@ -42,6 +57,9 @@ export class PowerTransformerEditor extends LitElement { @property({ type: Boolean }) showfunctions = false; + @query('mwc-menu') addMenu!: Menu; + @query('mwc-icon-button[icon="playlist_add"]') addButton!: IconButton; + private openEditWizard(): void { const wizard = wizards['PowerTransformer'].edit(this.element); if (wizard) this.dispatchEvent(newWizardEvent(wizard)); @@ -65,6 +83,17 @@ export class PowerTransformerEditor extends LitElement { ); } + private openCreateWizard(tagName: string): void { + const wizard = wizards[tagName].create(this.element!); + + if (wizard) this.dispatchEvent(newWizardEvent(wizard)); + } + + firstUpdated(): void { + if (this.addMenu && this.addButton) + this.addMenu.anchor = this.addButton; + } + private renderLNodes(): TemplateResult { const lNodes = getChildElementsByTagName(this.element, 'LNode'); @@ -87,6 +116,15 @@ export class PowerTransformerEditor extends LitElement { )}`; } + private renderAddButtons(): TemplateResult[] { + return childTags(this.element).map( + child => + html`${child}` + ); + } + renderContentPane(): TemplateResult { return html`${powerTransformerTwoWindingIcon} - `; + > + (this.addMenu.open = true)} + > { + const tagName = ((e.target).selected).value; + this.openCreateWizard(tagName); + }} + >${this.renderAddButtons()} + `; } renderContentIcon(): TemplateResult { diff --git a/src/editors/substation/sub-function-editor.ts b/src/editors/substation/sub-function-editor.ts index 35c54dfcd..5dbdf7ed2 100644 --- a/src/editors/substation/sub-function-editor.ts +++ b/src/editors/substation/sub-function-editor.ts @@ -6,10 +6,34 @@ import { customElement, state, css, + query, } from 'lit-element'; +import { translate } from 'lit-translate'; + +import '@material/mwc-icon-button'; +import '@material/mwc-list/mwc-list-item'; +import '@material/mwc-menu'; +import { IconButton } from '@material/mwc-icon-button'; +import { ListItem } from '@material/mwc-list/mwc-list-item'; +import { Menu } from '@material/mwc-menu'; import '../../action-pane.js'; -import { getChildElementsByTagName } from '../../foundation.js'; +import './sub-function-editor.js'; +import { + getChildElementsByTagName, + newWizardEvent, + SCLTag, + tags, +} from '../../foundation.js'; +import { emptyWizard, wizards } from '../../wizards/wizard-library.js'; + +function childTags(element: Element | null | undefined): SCLTag[] { + if (!element) return []; + + return tags[element.tagName].children.filter( + child => wizards[child].create !== emptyWizard + ); +} /** Pane rendering `SubFunction` element with its children */ @customElement('sub-function-editor') @@ -26,6 +50,19 @@ export class SubFunctionEditor extends LitElement { return `${name}${desc ? ` - ${desc}` : ''}${type ? ` (${type})` : ''}`; } + @query('mwc-menu') addMenu!: Menu; + @query('mwc-icon-button[icon="playlist_add"]') addButton!: IconButton; + + private openCreateWizard(tagName: string): void { + const wizard = wizards[tagName].create(this.element!); + + if (wizard) this.dispatchEvent(newWizardEvent(wizard)); + } + + firstUpdated(): void { + this.addMenu.anchor = this.addButton; + } + private renderLNodes(): TemplateResult { const lNodes = getChildElementsByTagName(this.element, 'LNode'); @@ -48,8 +85,35 @@ export class SubFunctionEditor extends LitElement { )}`; } + private renderAddButtons(): TemplateResult[] { + return childTags(this.element).map( + child => + html`${child}` + ); + } + render(): TemplateResult { return html` + (this.addMenu.open = true)} + > { + const tagName = ((e.target).selected).value; + this.openCreateWizard(tagName); + }} + >${this.renderAddButtons()} ${this.renderLNodes()}${this.renderSubFunctions()}`; } diff --git a/src/wizards/eqfunction.ts b/src/wizards/eqfunction.ts new file mode 100644 index 000000000..62b5a71ef --- /dev/null +++ b/src/wizards/eqfunction.ts @@ -0,0 +1,56 @@ +import { get } from 'lit-translate'; + +import { + createElement, + getValue, + Wizard, + WizardActor, + WizardInputElement, +} from '../foundation.js'; +import { contentFunctionWizard } from './function.js'; + +function createEqFunctionAction(parent: Element): WizardActor { + return (inputs: WizardInputElement[]) => { + const eqFunctionAttrs: Record = {}; + const eqFunctionKeys = ['name', 'desc', 'type']; + eqFunctionKeys.forEach(key => { + eqFunctionAttrs[key] = getValue(inputs.find(i => i.label === key)!); + }); + + const eqFunction = createElement( + parent.ownerDocument, + 'EqFunction', + eqFunctionAttrs + ); + + return [{ new: { parent, element: eqFunction } }]; + }; +} + +export function createEqFunctionWizard(parent: Element): Wizard { + const name = ''; + const desc = null; + const type = null; + const reservedNames = Array.from(parent.querySelectorAll('EqFunction')).map( + fUnction => fUnction.getAttribute('name')! + ); + + return [ + { + title: get('wizard.title.add', { tagName: 'EqFunction' }), + primary: { + icon: 'save', + label: get('save'), + action: createEqFunctionAction(parent), + }, + content: [ + ...contentFunctionWizard({ + name, + desc, + type, + reservedNames, + }), + ], + }, + ]; +} diff --git a/src/wizards/eqsubfunction.ts b/src/wizards/eqsubfunction.ts new file mode 100644 index 000000000..4763fdb1c --- /dev/null +++ b/src/wizards/eqsubfunction.ts @@ -0,0 +1,56 @@ +import { get } from 'lit-translate'; + +import { + createElement, + getValue, + Wizard, + WizardActor, + WizardInputElement, +} from '../foundation.js'; +import { contentFunctionWizard } from './function.js'; + +function createEqSubFunctionAction(parent: Element): WizardActor { + return (inputs: WizardInputElement[]) => { + const eqSubFunctionAttrs: Record = {}; + const eqSubFunctionKeys = ['name', 'desc', 'type']; + eqSubFunctionKeys.forEach(key => { + eqSubFunctionAttrs[key] = getValue(inputs.find(i => i.label === key)!); + }); + + const eqSubFunction = createElement( + parent.ownerDocument, + 'EqSubFunction', + eqSubFunctionAttrs + ); + + return [{ new: { parent, element: eqSubFunction } }]; + }; +} + +export function createEqSubFunctionWizard(parent: Element): Wizard { + const name = ''; + const desc = null; + const type = null; + const reservedNames = Array.from( + parent.querySelectorAll('EqSubFunction') + ).map(eqSubFunction => eqSubFunction.getAttribute('name')!); + + return [ + { + title: get('wizard.title.add', { tagName: 'EqSubFunction' }), + primary: { + icon: 'save', + label: get('save'), + action: createEqSubFunctionAction(parent), + }, + content: [ + ...contentFunctionWizard({ + name, + desc, + type, + reservedNames, + }), + ], + }, + ]; +} diff --git a/src/wizards/function.ts b/src/wizards/function.ts new file mode 100644 index 000000000..a828a8e75 --- /dev/null +++ b/src/wizards/function.ts @@ -0,0 +1,91 @@ +import { html, TemplateResult } from 'lit-element'; +import { get, translate } from 'lit-translate'; + +import { + createElement, + getValue, + Wizard, + WizardActor, + WizardInputElement, +} from '../foundation.js'; + +interface ContentOptions { + name: string | null; + desc: string | null; + type: string | null; + reservedNames: string[]; +} + +export function contentFunctionWizard( + content: ContentOptions +): TemplateResult[] { + return [ + html``, + html``, + html``, + ]; +} + +function createFunctionAction(parent: Element): WizardActor { + return (inputs: WizardInputElement[]) => { + const functionAttrs: Record = {}; + const functionKeys = ['name', 'desc', 'type']; + functionKeys.forEach(key => { + functionAttrs[key] = getValue(inputs.find(i => i.label === key)!); + }); + + const fUnction = createElement( + parent.ownerDocument, + 'Function', + functionAttrs + ); + + return [{ new: { parent, element: fUnction } }]; + }; +} + +export function createFunctionWizard(parent: Element): Wizard { + const name = ''; + const desc = null; + const type = null; + const reservedNames = Array.from(parent.querySelectorAll('Function')).map( + fUnction => fUnction.getAttribute('name')! + ); + + return [ + { + title: get('wizard.title.add', { tagName: 'Function' }), + primary: { + icon: 'save', + label: get('save'), + action: createFunctionAction(parent), + }, + content: [ + ...contentFunctionWizard({ + name, + desc, + type, + reservedNames, + }), + ], + }, + ]; +} diff --git a/src/wizards/subfunction.ts b/src/wizards/subfunction.ts new file mode 100644 index 000000000..9f1278065 --- /dev/null +++ b/src/wizards/subfunction.ts @@ -0,0 +1,56 @@ +import { get } from 'lit-translate'; + +import { + createElement, + getValue, + Wizard, + WizardActor, + WizardInputElement, +} from '../foundation.js'; +import { contentFunctionWizard } from './function.js'; + +function createSubFunctionAction(parent: Element): WizardActor { + return (inputs: WizardInputElement[]) => { + const subFunctionAttrs: Record = {}; + const subFunctionKeys = ['name', 'desc', 'type']; + subFunctionKeys.forEach(key => { + subFunctionAttrs[key] = getValue(inputs.find(i => i.label === key)!); + }); + + const subFunction = createElement( + parent.ownerDocument, + 'SubFunction', + subFunctionAttrs + ); + + return [{ new: { parent, element: subFunction } }]; + }; +} + +export function createSubFunctionWizard(parent: Element): Wizard { + const name = ''; + const desc = null; + const type = null; + const reservedNames = Array.from(parent.querySelectorAll('SubFunction')).map( + fUnction => fUnction.getAttribute('name')! + ); + + return [ + { + title: get('wizard.title.add', { tagName: 'SubFunction' }), + primary: { + icon: 'save', + label: get('save'), + action: createSubFunctionAction(parent), + }, + content: [ + ...contentFunctionWizard({ + name, + desc, + type, + reservedNames, + }), + ], + }, + ]; +} diff --git a/src/wizards/wizard-library.ts b/src/wizards/wizard-library.ts index dac3e4b98..5d8fcf730 100644 --- a/src/wizards/wizard-library.ts +++ b/src/wizards/wizard-library.ts @@ -15,15 +15,25 @@ import { voltageLevelCreateWizard, voltageLevelEditWizard, } from './voltagelevel.js'; -import { createPowerTransformerWizard, editPowerTransformerWizard } from './powertransformer.js'; +import { + createPowerTransformerWizard, + editPowerTransformerWizard, +} from './powertransformer.js'; import { editSubNetworkWizard } from './subnetwork.js'; import { editIEDWizard } from './ied.js'; import { editTrgOpsWizard } from './trgops.js'; import { createDaWizard } from './da.js'; import { editDAIWizard } from './dai.js'; import { editGseControlWizard } from './gsecontrol.js'; +import { createFunctionWizard } from './function.js'; +import { createEqSubFunctionWizard } from './eqsubfunction.js'; +import { createEqFunctionWizard } from './eqfunction.js'; +import { createSubFunctionWizard } from './subfunction.js'; -type SclElementWizard = (element: Element, instanceElement?: Element) => Wizard | undefined; +type SclElementWizard = ( + element: Element, + instanceElement?: Element +) => Wizard | undefined; export function emptyWizard(): Wizard | undefined { return; @@ -182,11 +192,11 @@ export const wizards: Record< }, EqFunction: { edit: emptyWizard, - create: emptyWizard, + create: createEqFunctionWizard, }, EqSubFunction: { edit: emptyWizard, - create: emptyWizard, + create: createEqSubFunctionWizard, }, ExtRef: { edit: emptyWizard, @@ -202,7 +212,7 @@ export const wizards: Record< }, Function: { edit: emptyWizard, - create: emptyWizard, + create: createFunctionWizard, }, GeneralEquipment: { edit: emptyWizard, @@ -470,7 +480,7 @@ export const wizards: Record< }, SubFunction: { edit: emptyWizard, - create: emptyWizard, + create: createSubFunctionWizard, }, SubNetwork: { edit: editSubNetworkWizard, diff --git a/test/integration/editors/substation/bay-editor-wizarding-editing.test.ts b/test/integration/editors/substation/bay-editor-wizarding-editing.test.ts index 86f737074..cd5629f71 100644 --- a/test/integration/editors/substation/bay-editor-wizarding-editing.test.ts +++ b/test/integration/editors/substation/bay-editor-wizarding-editing.test.ts @@ -342,4 +342,77 @@ describe('bay-editor wizarding editing integration', () => { ); }); }); + + describe('open create wizard for element Function', () => { + let doc: XMLDocument; + let parent: MockWizardEditor; + let element: BayEditor | null; + + let nameField: WizardTextField; + let primaryAction: HTMLElement; + + beforeEach(async () => { + doc = await fetch('/test/testfiles/zeroline/functions.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + parent = ( + await fixture( + html`` + ) + ); + + element = parent.querySelector('bay-editor'); + + (( + element?.shadowRoot?.querySelector('mwc-list-item[value="Function"]') + )).click(); + await parent.updateComplete; + + nameField = ( + parent.wizardUI.dialog?.querySelector('wizard-textfield[label="name"]') + ); + + primaryAction = ( + parent.wizardUI.dialog?.querySelector( + 'mwc-button[slot="primaryAction"]' + ) + ); + }); + + it('does not add Function if name attribute is not unique', async () => { + expect( + doc.querySelector('Bay[name="COUPLING_BAY"] > Function[name="bayName"]') + ).to.exist; + + nameField.value = 'bayName'; + primaryAction.click(); + await parent.updateComplete; + + expect( + doc.querySelectorAll( + 'Bay[name="COUPLING_BAY"] > Function[name="bayName"]' + ).length + ).to.equal(1); + }); + + it('does add Function if name attribute is unique', async () => { + expect( + doc.querySelector( + 'Bay[name="COUPLING_BAY"] > Function[name="someNewFunction"]' + ) + ).to.not.exist; + + nameField.value = 'someNewFunction'; + await parent.updateComplete; + primaryAction.click(); + + expect( + doc.querySelector( + 'Bay[name="COUPLING_BAY"] > Function[name="someNewFunction"]' + ) + ).to.exist; + }); + }); }); diff --git a/test/integration/editors/substation/conducting-equipment-editor-wizarding-editing.test.ts b/test/integration/editors/substation/conducting-equipment-editor-wizarding-editing.test.ts index 46e323d6a..1341d01e8 100644 --- a/test/integration/editors/substation/conducting-equipment-editor-wizarding-editing.test.ts +++ b/test/integration/editors/substation/conducting-equipment-editor-wizarding-editing.test.ts @@ -205,4 +205,82 @@ describe('conducting-equipment-editor wizarding editing integration', () => { expect(doc.querySelector('ConductingEquipment[name="QA1"]')).to.not.exist; }); }); + + describe('open create wizard for element EqFunction', () => { + let doc: XMLDocument; + let parent: MockWizardEditor; + let element: ConductingEquipmentEditor | null; + + let nameField: WizardTextField; + let primaryAction: HTMLElement; + + beforeEach(async () => { + doc = await fetch('/test/testfiles/zeroline/functions.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + parent = ( + await fixture( + html`` + ) + ); + + element = parent.querySelector('conducting-equipment-editor'); + + (( + element?.shadowRoot?.querySelector('mwc-list-item[value="EqFunction"]') + )).click(); + await parent.updateComplete; + + nameField = ( + parent.wizardUI.dialog?.querySelector('wizard-textfield[label="name"]') + ); + + primaryAction = ( + parent.wizardUI.dialog?.querySelector( + 'mwc-button[slot="primaryAction"]' + ) + ); + }); + + it('does not add EqFunction if name attribute is not unique', async () => { + expect( + doc.querySelector( + 'ConductingEquipment > EqFunction[name="myEqFuncQA1"]' + ) + ).to.exist; + + nameField.value = 'myEqFuncQA1'; + primaryAction.click(); + await parent.updateComplete; + + expect( + doc.querySelectorAll( + 'ConductingEquipment > EqFunction[name="myEqFuncQA1"]' + ).length + ).to.equal(1); + }); + + it('does add EqFunction if name attribute is unique', async () => { + expect( + doc.querySelector( + 'ConductingEquipment > EqFunction[name="someNewFunction"]' + ) + ).to.not.exist; + + nameField.value = 'someNewFunction'; + await parent.updateComplete; + primaryAction.click(); + + expect( + doc.querySelector( + 'ConductingEquipment > EqFunction[name="someNewFunction"]' + ) + ).to.exist; + }); + }); }); diff --git a/test/integration/editors/substation/eq-function-wizarding-editing.test.ts b/test/integration/editors/substation/eq-function-wizarding-editing.test.ts new file mode 100644 index 000000000..eb29d5bba --- /dev/null +++ b/test/integration/editors/substation/eq-function-wizarding-editing.test.ts @@ -0,0 +1,91 @@ +import { fixture, html, expect } from '@open-wc/testing'; + +import '../../../mock-wizard-editor.js'; +import { MockWizardEditor } from '../../../mock-wizard-editor.js'; + +import '../../../../src/editors/substation/eq-function-editor.js'; +import { EqFunctionEditor } from '../../../../src/editors/substation/eq-function-editor.js'; +import { WizardTextField } from '../../../../src/wizard-textfield.js'; + +describe('eq-function-editor wizarding editing integration', () => { + describe('open create wizard for element EqSubFunction', () => { + let doc: XMLDocument; + let parent: MockWizardEditor; + let element: EqFunctionEditor | null; + + let nameField: WizardTextField; + let primaryAction: HTMLElement; + + beforeEach(async () => { + doc = await fetch('/test/testfiles/zeroline/functions.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + parent = ( + await fixture( + html` EqFunction' + )} + >` + ) + ); + + element = parent.querySelector('eq-function-editor'); + + (( + element?.shadowRoot?.querySelector( + 'mwc-list-item[value="EqSubFunction"]' + ) + )).click(); + await parent.updateComplete; + + nameField = ( + parent.wizardUI.dialog?.querySelector('wizard-textfield[label="name"]') + ); + + primaryAction = ( + parent.wizardUI.dialog?.querySelector( + 'mwc-button[slot="primaryAction"]' + ) + ); + }); + + it('does not add EqSubFunction if name attribute is not unique', async () => { + expect( + doc.querySelector( + 'ConductingEquipment[name="QA1"] EqSubFunction[name="myEqSubFunc"]' + ) + ).to.exist; + + nameField.value = 'myEqSubFunc'; + primaryAction.click(); + await parent.updateComplete; + + expect( + doc.querySelectorAll( + 'ConductingEquipment[name="QA1"] EqSubFunction[name="myEqSubFunc"]' + ).length + ).to.equal(1); + }); + + it('does add EqFunction if name attribute is unique', async () => { + expect( + doc.querySelector( + 'ConductingEquipment[name="QA1"] EqSubFunction[name="someNewEqSubFunction"]' + ) + ).to.not.exist; + + nameField.value = 'someNewEqSubFunction'; + await parent.updateComplete; + primaryAction.click(); + + expect( + doc.querySelector( + 'ConductingEquipment[name="QA1"] EqSubFunction[name="someNewEqSubFunction"]' + ) + ).to.exist; + }); + }); +}); diff --git a/test/integration/editors/substation/eq-sub-function-editor-wizarding-editing.test.ts b/test/integration/editors/substation/eq-sub-function-editor-wizarding-editing.test.ts new file mode 100644 index 000000000..f4b12ce3f --- /dev/null +++ b/test/integration/editors/substation/eq-sub-function-editor-wizarding-editing.test.ts @@ -0,0 +1,91 @@ +import { fixture, html, expect } from '@open-wc/testing'; + +import '../../../mock-wizard-editor.js'; +import { MockWizardEditor } from '../../../mock-wizard-editor.js'; + +import '../../../../src/editors/substation/eq-sub-function-editor.js'; +import { EqSubFunctionEditor } from '../../../../src/editors/substation/eq-sub-function-editor.js'; +import { WizardTextField } from '../../../../src/wizard-textfield.js'; + +describe('eq-sub-function-editor wizarding editing integration', () => { + describe('open create wizard for element EqSubFunction', () => { + let doc: XMLDocument; + let parent: MockWizardEditor; + let element: EqSubFunctionEditor | null; + + let nameField: WizardTextField; + let primaryAction: HTMLElement; + + beforeEach(async () => { + doc = await fetch('/test/testfiles/zeroline/functions.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + parent = ( + await fixture( + html`` + ) + ); + + element = parent.querySelector('eq-sub-function-editor'); + + (( + element?.shadowRoot?.querySelector( + 'mwc-list-item[value="EqSubFunction"]' + ) + )).click(); + await parent.updateComplete; + + nameField = ( + parent.wizardUI.dialog?.querySelector('wizard-textfield[label="name"]') + ); + + primaryAction = ( + parent.wizardUI.dialog?.querySelector( + 'mwc-button[slot="primaryAction"]' + ) + ); + }); + + it('does not add EqSubFunction if name attribute is not unique', async () => { + expect( + doc.querySelector( + 'ConductingEquipment[name="QA1"] EqSubFunction[name="myEqSubSubFunction"]' + ) + ).to.exist; + + nameField.value = 'myEqSubSubFunction'; + primaryAction.click(); + await parent.updateComplete; + + expect( + doc.querySelectorAll( + 'ConductingEquipment[name="QA1"] EqSubFunction[name="myEqSubSubFunction"]' + ).length + ).to.equal(1); + }); + + it('does add EqFunction if name attribute is unique', async () => { + expect( + doc.querySelector( + 'ConductingEquipment[name="QA1"] EqSubFunction[name="someNewEqSubFunction"]' + ) + ).to.not.exist; + + nameField.value = 'someNewEqSubFunction'; + await parent.updateComplete; + primaryAction.click(); + + expect( + doc.querySelector( + 'ConductingEquipment[name="QA1"] EqSubFunction[name="someNewEqSubFunction"]' + ) + ).to.exist; + }); + }); +}); diff --git a/test/integration/editors/substation/function-editor.test.ts b/test/integration/editors/substation/function-editor.test.ts new file mode 100644 index 000000000..f5bef7542 --- /dev/null +++ b/test/integration/editors/substation/function-editor.test.ts @@ -0,0 +1,87 @@ +import { fixture, html, expect } from '@open-wc/testing'; + +import '../../../mock-wizard-editor.js'; +import { MockWizardEditor } from '../../../mock-wizard-editor.js'; + +import '../../../../src/editors/substation/function-editor.js'; +import { FunctionEditor } from '../../../../src/editors/substation/function-editor.js'; +import { WizardTextField } from '../../../../src/wizard-textfield.js'; + +describe('function-editor wizarding editing integration', () => { + describe('open create wizard for element SubFunction', () => { + let doc: XMLDocument; + let parent: MockWizardEditor; + let element: FunctionEditor | null; + + let nameField: WizardTextField; + let primaryAction: HTMLElement; + + beforeEach(async () => { + doc = await fetch('/test/testfiles/zeroline/functions.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + parent = ( + await fixture( + html`` + ) + ); + + element = parent.querySelector('function-editor'); + + (( + element?.shadowRoot?.querySelector('mwc-list-item[value="SubFunction"]') + )).click(); + await parent.updateComplete; + + nameField = ( + parent.wizardUI.dialog?.querySelector('wizard-textfield[label="name"]') + ); + + primaryAction = ( + parent.wizardUI.dialog?.querySelector( + 'mwc-button[slot="primaryAction"]' + ) + ); + }); + + it('does not add SubFunction if name attribute is not unique', async () => { + expect( + doc.querySelector( + 'Substation > Function > SubFunction[name="mySubFunc"]' + ) + ).to.exist; + + nameField.value = 'mySubFunc'; + primaryAction.click(); + await parent.updateComplete; + + expect( + doc.querySelectorAll( + 'Substation > Function > SubFunction[name="mySubFunc"]' + ).length + ).to.equal(1); + }); + + it('does add SubFunction if name attribute is unique', async () => { + expect( + doc.querySelector( + 'Substation > Function > SubFunction[name="someNewFunction"]' + ) + ).to.not.exist; + + nameField.value = 'someNewFunction'; + await parent.updateComplete; + primaryAction.click(); + + expect( + doc.querySelector( + 'Substation > Function > SubFunction[name="someNewFunction"]' + ) + ).to.exist; + }); + }); +}); diff --git a/test/integration/editors/substation/powertransformer-editor-wizarding-editing.test.ts b/test/integration/editors/substation/powertransformer-editor-wizarding-editing.test.ts new file mode 100644 index 000000000..4ac0fa7a1 --- /dev/null +++ b/test/integration/editors/substation/powertransformer-editor-wizarding-editing.test.ts @@ -0,0 +1,88 @@ +import { fixture, html, expect } from '@open-wc/testing'; + +import '../../../mock-wizard-editor.js'; +import { MockWizardEditor } from '../../../mock-wizard-editor.js'; + +import '../../../../src/editors/substation/powertransformer-editor.js'; +import { PowerTransformerEditor } from '../../../../src/editors/substation/powertransformer-editor.js'; +import { WizardTextField } from '../../../../src/wizard-textfield.js'; + +describe('powertransformer-editor wizarding editing integration', () => { + describe('open create wizard for element EqFunction', () => { + let doc: XMLDocument; + let parent: MockWizardEditor; + let element: PowerTransformerEditor | null; + + let nameField: WizardTextField; + let primaryAction: HTMLElement; + + beforeEach(async () => { + doc = await fetch('/test/testfiles/zeroline/functions.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + parent = ( + await fixture( + html`` + ) + ); + + element = parent.querySelector('powertransformer-editor'); + + (( + element?.shadowRoot?.querySelector('mwc-list-item[value="EqFunction"]') + )).click(); + await parent.updateComplete; + + nameField = ( + parent.wizardUI.dialog?.querySelector('wizard-textfield[label="name"]') + ); + + primaryAction = ( + parent.wizardUI.dialog?.querySelector( + 'mwc-button[slot="primaryAction"]' + ) + ); + }); + + it('does not add EqFunction if name attribute is not unique', async () => { + expect( + doc.querySelector( + 'PowerTransformer[name="myPtr2"] > EqFunction[name="myEqFuncPtr2"]' + ) + ).to.exist; + + nameField.value = 'myEqFuncPtr2'; + primaryAction.click(); + await parent.updateComplete; + + expect( + doc.querySelectorAll( + 'PowerTransformer[name="myPtr2"] > EqFunction[name="myEqFuncPtr2"]' + ).length + ).to.equal(1); + }); + + it('does add EqFunction if name attribute is unique', async () => { + expect( + doc.querySelector( + 'PowerTransformer[name="myPtr2"] > EqFunction[name="someNewFunction"]' + ) + ).to.not.exist; + + nameField.value = 'someNewFunction'; + await parent.updateComplete; + primaryAction.click(); + + expect( + doc.querySelector( + 'PowerTransformer[name="myPtr2"] > EqFunction[name="someNewFunction"]' + ) + ).to.exist; + }); + }); +}); diff --git a/test/integration/editors/substation/sub-function-editor.test.ts b/test/integration/editors/substation/sub-function-editor.test.ts new file mode 100644 index 000000000..6c7035ad9 --- /dev/null +++ b/test/integration/editors/substation/sub-function-editor.test.ts @@ -0,0 +1,89 @@ +import { fixture, html, expect } from '@open-wc/testing'; + +import '../../../mock-wizard-editor.js'; +import { MockWizardEditor } from '../../../mock-wizard-editor.js'; + +import '../../../../src/editors/substation/sub-function-editor.js'; +import { SubFunctionEditor } from '../../../../src/editors/substation/sub-function-editor.js'; +import { WizardTextField } from '../../../../src/wizard-textfield.js'; + +describe('sub-function-editor wizarding editing integration', () => { + describe('open create wizard for element SubFunction', () => { + let doc: XMLDocument; + let parent: MockWizardEditor; + let element: SubFunctionEditor | null; + + let nameField: WizardTextField; + let primaryAction: HTMLElement; + + beforeEach(async () => { + doc = await fetch('/test/testfiles/zeroline/functions.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + parent = ( + await fixture( + html` SubFunction' + )} + >` + ) + ); + + element = parent.querySelector('sub-function-editor'); + + (( + element?.shadowRoot?.querySelector('mwc-list-item[value="SubFunction"]') + )).click(); + await parent.updateComplete; + + nameField = ( + parent.wizardUI.dialog?.querySelector('wizard-textfield[label="name"]') + ); + + primaryAction = ( + parent.wizardUI.dialog?.querySelector( + 'mwc-button[slot="primaryAction"]' + ) + ); + }); + + it('does not add SubFunction if name attribute is not unique', async () => { + expect( + doc.querySelector( + 'Function[name="voltLvName"] > SubFunction > SubFunction' + ) + ).to.exist; + + nameField.value = 'mySubSubFunction'; + primaryAction.click(); + await parent.updateComplete; + + expect( + doc.querySelectorAll( + 'Function[name="voltLvName"] > SubFunction > SubFunction' + ).length + ).to.equal(1); + }); + + it('does add SubFunction if name attribute is unique', async () => { + expect( + doc.querySelector( + 'Function[name="voltLvName"] > SubFunction > SubFunction[name="someNewSubFunction"]' + ) + ).to.not.exist; + + nameField.value = 'someNewSubFunction'; + await parent.updateComplete; + primaryAction.click(); + + expect( + doc.querySelector( + 'Function[name="voltLvName"] > SubFunction > SubFunction[name="someNewSubFunction"]' + ) + ).to.exist; + }); + }); +}); diff --git a/test/integration/editors/substation/substation-editor-wizarding-editing.test.ts b/test/integration/editors/substation/substation-editor-wizarding-editing.test.ts index 65e7780fa..d1e80b536 100644 --- a/test/integration/editors/substation/substation-editor-wizarding-editing.test.ts +++ b/test/integration/editors/substation/substation-editor-wizarding-editing.test.ts @@ -210,4 +210,70 @@ describe('substation-editor wizarding editing integration', () => { expect(doc.querySelector('Substation')).to.not.exist; }); }); + + describe('open create wizard for element Function', () => { + let doc: XMLDocument; + let parent: MockWizardEditor; + let element: SubstationEditor | null; + + let nameField: WizardTextField; + let primaryAction: HTMLElement; + + beforeEach(async () => { + doc = await fetch('/test/testfiles/zeroline/functions.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + parent = ( + await fixture( + html`` + ) + ); + + element = parent.querySelector('substation-editor'); + + (( + element?.shadowRoot?.querySelector('mwc-list-item[value="Function"]') + )).click(); + await parent.updateComplete; + + nameField = ( + parent.wizardUI.dialog?.querySelector('wizard-textfield[label="name"]') + ); + + primaryAction = ( + parent.wizardUI.dialog?.querySelector( + 'mwc-button[slot="primaryAction"]' + ) + ); + }); + + it('does not add Function if name attribute is not unique', async () => { + expect(doc.querySelector('Substation > Function[name="myFunc"]')).to + .exist; + + nameField.value = 'myFunc'; + primaryAction.click(); + await parent.updateComplete; + + expect( + doc.querySelectorAll('Substation > Function[name="myFunc"]').length + ).to.equal(1); + }); + + it('does add Function if name attribute is unique', async () => { + expect(doc.querySelector('Substation > Function[name="someNewFunction"]')) + .to.not.exist; + + nameField.value = 'someNewFunction'; + await parent.updateComplete; + primaryAction.click(); + + expect(doc.querySelector('Substation > Function[name="someNewFunction"]')) + .to.exist; + }); + }); }); diff --git a/test/integration/editors/substation/voltage-level-editor-wizarding-editing.test.ts b/test/integration/editors/substation/voltage-level-editor-wizarding-editing.test.ts index e2c967003..2f75d96ed 100644 --- a/test/integration/editors/substation/voltage-level-editor-wizarding-editing.test.ts +++ b/test/integration/editors/substation/voltage-level-editor-wizarding-editing.test.ts @@ -428,4 +428,81 @@ describe('voltage-level-editor wizarding editing integration', () => { ); }); }); + + describe('open create wizard for element Function', () => { + let doc: XMLDocument; + let parent: MockWizardEditor; + let element: VoltageLevelEditor | null; + + let nameField: WizardTextField; + let primaryAction: HTMLElement; + + beforeEach(async () => { + doc = await fetch('/test/testfiles/zeroline/functions.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + parent = ( + await fixture( + html`` + ) + ); + + element = parent.querySelector('voltage-level-editor'); + + (( + element?.shadowRoot?.querySelector('mwc-list-item[value="Function"]') + )).click(); + await parent.updateComplete; + + nameField = ( + parent.wizardUI.dialog?.querySelector('wizard-textfield[label="name"]') + ); + + primaryAction = ( + parent.wizardUI.dialog?.querySelector( + 'mwc-button[slot="primaryAction"]' + ) + ); + }); + + it('does not add Function if name attribute is not unique', async () => { + expect( + doc.querySelector( + 'VoltageLevel[name="E1"] > Function[name="voltLvName"]' + ) + ).to.exist; + + nameField.value = 'voltLvName'; + primaryAction.click(); + await parent.updateComplete; + + expect( + doc.querySelectorAll( + 'VoltageLevel[name="E1"] > Function[name="voltLvName"]' + ).length + ).to.equal(1); + }); + + it('does add Function if name attribute is unique', async () => { + expect( + doc.querySelector( + 'VoltageLevel[name="E1"] > Function[name="someNewFunction"]' + ) + ).to.not.exist; + + nameField.value = 'someNewFunction'; + await parent.updateComplete; + primaryAction.click(); + + expect( + doc.querySelector( + 'VoltageLevel[name="E1"] > Function[name="someNewFunction"]' + ) + ).to.exist; + }); + }); }); diff --git a/test/unit/editors/substation/__snapshots__/bay-editor.test.snap.js b/test/unit/editors/substation/__snapshots__/bay-editor.test.snap.js index 658c44e58..2ba509117 100644 --- a/test/unit/editors/substation/__snapshots__/bay-editor.test.snap.js +++ b/test/unit/editors/substation/__snapshots__/bay-editor.test.snap.js @@ -85,6 +85,17 @@ snapshots["bay-editor looks like the latest snapshot"] = ConductingEquipment + + + Function + +
@@ -187,6 +198,17 @@ snapshots["bay-editor with readonly property looks like the latest snapshot"] = ConductingEquipment + + + Function + +
@@ -289,6 +311,17 @@ snapshots["bay-editor with function filter deactivated looks like the latest sna ConductingEquipment + + + Function + + @@ -395,6 +428,17 @@ snapshots["bay-editor with existing LNode children looks like the latest snapsho ConductingEquipment + + + Function + +
diff --git a/test/unit/editors/substation/__snapshots__/conducting-equipment-editor.test.snap.js b/test/unit/editors/substation/__snapshots__/conducting-equipment-editor.test.snap.js index 15e330335..41ee60f01 100644 --- a/test/unit/editors/substation/__snapshots__/conducting-equipment-editor.test.snap.js +++ b/test/unit/editors/substation/__snapshots__/conducting-equipment-editor.test.snap.js @@ -90,6 +90,41 @@ snapshots["conducting-equipment-editor rendered as action pane looks like the la > + + + + + + + LNode + + + + + EqFunction + + + + `; /* end snapshot conducting-equipment-editor rendered as action pane looks like the latest snapshot */ @@ -148,6 +183,41 @@ snapshots["conducting-equipment-editor rendered as action pane with EqFunction c > + + + + + + + LNode + + + + + EqFunction + + + + @@ -208,6 +278,41 @@ snapshots["conducting-equipment-editor rendered as action pane with LNode childr > + + + + + + + LNode + + + + + EqFunction + + + +
diff --git a/test/unit/editors/substation/__snapshots__/eq-function-editor.test.snap.js b/test/unit/editors/substation/__snapshots__/eq-function-editor.test.snap.js index 4c5a18819..b9b1e39f8 100644 --- a/test/unit/editors/substation/__snapshots__/eq-function-editor.test.snap.js +++ b/test/unit/editors/substation/__snapshots__/eq-function-editor.test.snap.js @@ -9,6 +9,41 @@ snapshots["web component rendering EqFunction element with complete attribute se secondary="" tabindex="0" > + + + + + + + LNode + + + + + EqSubFunction + + + + @@ -23,6 +58,41 @@ snapshots["web component rendering EqFunction element with missing desc and type secondary="" tabindex="0" > + + + + + + + LNode + + + + + EqSubFunction + + + + @@ -37,6 +107,41 @@ snapshots["web component rendering EqFunction element with existing LNode childr secondary="" tabindex="0" > + + + + + + + LNode + + + + + EqSubFunction + + + +
diff --git a/test/unit/editors/substation/__snapshots__/eq-sub-function-editor.test.snap.js b/test/unit/editors/substation/__snapshots__/eq-sub-function-editor.test.snap.js index f3df8882d..946c455d8 100644 --- a/test/unit/editors/substation/__snapshots__/eq-sub-function-editor.test.snap.js +++ b/test/unit/editors/substation/__snapshots__/eq-sub-function-editor.test.snap.js @@ -8,6 +8,41 @@ snapshots["web component rendering EqSubFunction element with complete attribute secondary="" tabindex="0" > + + + + + + + LNode + + + + + EqSubFunction + + + + `; /* end snapshot web component rendering EqSubFunction element with complete attribute set and existing children looks like the latest snapshot */ @@ -19,6 +54,41 @@ snapshots["web component rendering EqSubFunction element with missing desc and t secondary="" tabindex="0" > + + + + + + + LNode + + + + + EqSubFunction + + + + @@ -32,6 +102,41 @@ snapshots["web component rendering EqSubFunction element with existing LNode chi secondary="" tabindex="0" > + + + + + + + LNode + + + + + EqSubFunction + + + +
diff --git a/test/unit/editors/substation/__snapshots__/function-editor.test.snap.js b/test/unit/editors/substation/__snapshots__/function-editor.test.snap.js index 819e80c9b..0401253a1 100644 --- a/test/unit/editors/substation/__snapshots__/function-editor.test.snap.js +++ b/test/unit/editors/substation/__snapshots__/function-editor.test.snap.js @@ -9,6 +9,52 @@ snapshots["web component rendering Function element with complete attribute set secondary="" tabindex="0" > + + + + + + + LNode + + + + + SubFunction + + + + + ConductingEquipment + + + + @@ -23,6 +69,52 @@ snapshots["web component rendering Function element with missing desc and type a secondary="" tabindex="0" > + + + + + + + LNode + + + + + SubFunction + + + + + ConductingEquipment + + + + @@ -37,6 +129,52 @@ snapshots["web component rendering Function element with existing LNode children secondary="" tabindex="0" > + + + + + + + LNode + + + + + SubFunction + + + + + ConductingEquipment + + + +
diff --git a/test/unit/editors/substation/__snapshots__/powertransformer-editor.test.snap.js b/test/unit/editors/substation/__snapshots__/powertransformer-editor.test.snap.js index 1dd9a4775..a41d549eb 100644 --- a/test/unit/editors/substation/__snapshots__/powertransformer-editor.test.snap.js +++ b/test/unit/editors/substation/__snapshots__/powertransformer-editor.test.snap.js @@ -91,6 +91,41 @@ snapshots["powertransformer-editor rendered as action pane looks like the latest > + + + + + + + LNode + + + + + EqFunction + + + + `; /* end snapshot powertransformer-editor rendered as action pane looks like the latest snapshot */ @@ -149,6 +184,41 @@ snapshots["powertransformer-editor rendered as action pane with EqFunction child > + + + + + + + LNode + + + + + EqFunction + + + + @@ -209,6 +279,41 @@ snapshots["powertransformer-editor rendered as action pane with LNode childrend > + + + + + + + LNode + + + + + EqFunction + + + +
diff --git a/test/unit/editors/substation/__snapshots__/sub-function-editor.test.snap.js b/test/unit/editors/substation/__snapshots__/sub-function-editor.test.snap.js index 35f8d30ad..6b951a981 100644 --- a/test/unit/editors/substation/__snapshots__/sub-function-editor.test.snap.js +++ b/test/unit/editors/substation/__snapshots__/sub-function-editor.test.snap.js @@ -8,6 +8,52 @@ snapshots["web component rendering SubFunction element with complete attribute s secondary="" tabindex="0" > + + + + + + + LNode + + + + + ConductingEquipment + + + + + SubFunction + + + + @@ -21,6 +67,52 @@ snapshots["web component rendering SubFunction element with missing desc and typ secondary="" tabindex="0" > + + + + + + + LNode + + + + + ConductingEquipment + + + + + SubFunction + + + + `; /* end snapshot web component rendering SubFunction element with missing desc and type attribute looks like the latest snapshot */ @@ -32,6 +124,52 @@ snapshots["web component rendering SubFunction element with existing LNode child secondary="" tabindex="0" > + + + + + + + LNode + + + + + ConductingEquipment + + + + + SubFunction + + + +
diff --git a/test/unit/editors/substation/__snapshots__/substation-editor.test.snap.js b/test/unit/editors/substation/__snapshots__/substation-editor.test.snap.js index d34ce2f4d..7e7d96f79 100644 --- a/test/unit/editors/substation/__snapshots__/substation-editor.test.snap.js +++ b/test/unit/editors/substation/__snapshots__/substation-editor.test.snap.js @@ -85,6 +85,17 @@ snapshots["substation-editor looks like the latest snapshot"] = VoltageLevel + + + Function + + @@ -179,6 +190,17 @@ snapshots["substation-editor with readonly property looks like the latest snapsh VoltageLevel + + + Function + + @@ -273,6 +295,17 @@ snapshots["substation-editor with function filter deactivated looks like the lat VoltageLevel + + + Function + +
diff --git a/test/unit/editors/substation/__snapshots__/voltage-level-editor.test.snap.js b/test/unit/editors/substation/__snapshots__/voltage-level-editor.test.snap.js index 645f50971..cee1779bd 100644 --- a/test/unit/editors/substation/__snapshots__/voltage-level-editor.test.snap.js +++ b/test/unit/editors/substation/__snapshots__/voltage-level-editor.test.snap.js @@ -86,6 +86,17 @@ snapshots["voltage-level-editor looks like the latest snapshot"] = Bay + + + Function + +
@@ -183,6 +194,17 @@ snapshots["voltage-level-editor with readonly property looks like the latest sna Bay + + + Function + +
@@ -280,6 +302,17 @@ snapshots["voltage-level-editor with function filter deactivated looks like the Bay + + + Function + + @@ -383,6 +416,17 @@ snapshots["voltage-level-editor with function filter deactivated and existing LN Bay + + + Function + +
diff --git a/test/unit/wizards/__snapshots__/eqfunction.test.snap.js b/test/unit/wizards/__snapshots__/eqfunction.test.snap.js new file mode 100644 index 000000000..fc5b64d35 --- /dev/null +++ b/test/unit/wizards/__snapshots__/eqfunction.test.snap.js @@ -0,0 +1,52 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["Wizards for SCL EqFunction element define an create wizard that looks like the the latest snapshot"] = +` +
+ + + + + + +
+ + + + +
+`; +/* end snapshot Wizards for SCL EqFunction element define an create wizard that looks like the the latest snapshot */ + diff --git a/test/unit/wizards/__snapshots__/eqsubfunction.test.snap.js b/test/unit/wizards/__snapshots__/eqsubfunction.test.snap.js new file mode 100644 index 000000000..4453caaea --- /dev/null +++ b/test/unit/wizards/__snapshots__/eqsubfunction.test.snap.js @@ -0,0 +1,52 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["Wizards for SCL EqSubFunction element define an create wizard that looks like the the latest snapshot"] = +` +
+ + + + + + +
+ + + + +
+`; +/* end snapshot Wizards for SCL EqSubFunction element define an create wizard that looks like the the latest snapshot */ + diff --git a/test/unit/wizards/__snapshots__/function.test.snap.js b/test/unit/wizards/__snapshots__/function.test.snap.js new file mode 100644 index 000000000..e7e6c0039 --- /dev/null +++ b/test/unit/wizards/__snapshots__/function.test.snap.js @@ -0,0 +1,52 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["Wizards for SCL Function element define an create wizard that looks like the the latest snapshot"] = +` +
+ + + + + + +
+ + + + +
+`; +/* end snapshot Wizards for SCL Function element define an create wizard that looks like the the latest snapshot */ + diff --git a/test/unit/wizards/__snapshots__/subfunction.test.snap.js b/test/unit/wizards/__snapshots__/subfunction.test.snap.js new file mode 100644 index 000000000..e7e6c0039 --- /dev/null +++ b/test/unit/wizards/__snapshots__/subfunction.test.snap.js @@ -0,0 +1,52 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["Wizards for SCL Function element define an create wizard that looks like the the latest snapshot"] = +` +
+ + + + + + +
+ + + + +
+`; +/* end snapshot Wizards for SCL Function element define an create wizard that looks like the the latest snapshot */ + diff --git a/test/unit/wizards/eqfunction.test.ts b/test/unit/wizards/eqfunction.test.ts new file mode 100644 index 000000000..7d1a6fa1a --- /dev/null +++ b/test/unit/wizards/eqfunction.test.ts @@ -0,0 +1,104 @@ +import { expect, fixture, html } from '@open-wc/testing'; +import { SinonSpy, spy } from 'sinon'; + +import '../../mock-wizard.js'; +import { MockWizard } from '../../mock-wizard.js'; + +import { WizardTextField } from '../../../src/wizard-textfield.js'; +import { + Create, + isCreate, + WizardInputElement, +} from '../../../src/foundation.js'; +import { createEqFunctionWizard } from '../../../src/wizards/eqfunction.js'; + +describe('Wizards for SCL EqFunction element', () => { + let doc: XMLDocument; + let element: MockWizard; + let inputs: WizardInputElement[]; + + let primaryAction: HTMLElement; + + let actionEvent: SinonSpy; + + beforeEach(async () => { + element = await fixture(html``); + doc = await fetch('test/testfiles/zeroline/functions.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + + actionEvent = spy(); + window.addEventListener('editor-action', actionEvent); + }); + + describe('define an create wizard that', () => { + beforeEach(async () => { + const wizard = createEqFunctionWizard( + doc.querySelector('ConductingEquipment')! + ); + element.workflow.push(() => wizard); + await element.requestUpdate(); + + inputs = Array.from(element.wizardUI.inputs); + + primaryAction = ( + element.wizardUI.dialog?.querySelector( + 'mwc-button[slot="primaryAction"]' + ) + ); + + await element.wizardUI.requestUpdate(); // make sure wizard is rendered + }); + + it('looks like the the latest snapshot', async () => + expect(element.wizardUI.dialog).dom.to.equalSnapshot()); + + it('does not accept empty name attribute', async () => { + await primaryAction.click(); + + expect(actionEvent).to.not.have.been.called; + }); + + it('triggers simple create action on primary action click', async () => { + inputs[0].value = 'someNonEmptyName'; + await element.requestUpdate(); + await primaryAction.click(); + + expect(actionEvent).to.be.calledOnce; + const action = actionEvent.args[0][0].detail.action; + expect(action).to.satisfy(isCreate); + const createAction = action; + + expect(createAction.new.element).to.have.attribute( + 'name', + 'someNonEmptyName' + ); + expect(createAction.new.element).to.not.have.attribute('desc'); + expect(createAction.new.element).to.not.have.attribute('type'); + }); + + it('allows to create non required attributes desc and type', async () => { + inputs[0].value = 'someNonEmptyName'; + + (inputs[1]).nullSwitch?.click(); + (inputs[2]).nullSwitch?.click(); + inputs[1].value = 'SomeDesc'; + inputs[2].value = 'SomeType'; + + await element.requestUpdate(); + await primaryAction.click(); + + expect(actionEvent).to.be.calledOnce; + const action = actionEvent.args[0][0].detail.action; + expect(action).to.satisfy(isCreate); + const createAction = action; + + expect(createAction.new.element).to.have.attribute( + 'name', + 'someNonEmptyName' + ); + expect(createAction.new.element).to.have.attribute('desc', 'SomeDesc'); + expect(createAction.new.element).to.have.attribute('type', 'SomeType'); + }); + }); +}); diff --git a/test/unit/wizards/eqsubfunction.test.ts b/test/unit/wizards/eqsubfunction.test.ts new file mode 100644 index 000000000..2419558b2 --- /dev/null +++ b/test/unit/wizards/eqsubfunction.test.ts @@ -0,0 +1,104 @@ +import { expect, fixture, html } from '@open-wc/testing'; +import { SinonSpy, spy } from 'sinon'; + +import '../../mock-wizard.js'; +import { MockWizard } from '../../mock-wizard.js'; + +import { WizardTextField } from '../../../src/wizard-textfield.js'; +import { + Create, + isCreate, + WizardInputElement, +} from '../../../src/foundation.js'; +import { createEqSubFunctionWizard } from '../../../src/wizards/eqsubfunction.js'; + +describe('Wizards for SCL EqSubFunction element', () => { + let doc: XMLDocument; + let element: MockWizard; + let inputs: WizardInputElement[]; + + let primaryAction: HTMLElement; + + let actionEvent: SinonSpy; + + beforeEach(async () => { + element = await fixture(html``); + doc = await fetch('test/testfiles/zeroline/functions.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + + actionEvent = spy(); + window.addEventListener('editor-action', actionEvent); + }); + + describe('define an create wizard that', () => { + beforeEach(async () => { + const wizard = createEqSubFunctionWizard( + doc.querySelector('EqFunction')! + ); + element.workflow.push(() => wizard); + await element.requestUpdate(); + + inputs = Array.from(element.wizardUI.inputs); + + primaryAction = ( + element.wizardUI.dialog?.querySelector( + 'mwc-button[slot="primaryAction"]' + ) + ); + + await element.wizardUI.requestUpdate(); // make sure wizard is rendered + }); + + it('looks like the the latest snapshot', async () => + expect(element.wizardUI.dialog).dom.to.equalSnapshot()); + + it('does not accept empty name attribute', async () => { + await primaryAction.click(); + + expect(actionEvent).to.not.have.been.called; + }); + + it('triggers simple create action on primary action click', async () => { + inputs[0].value = 'someNonEmptyName'; + await element.requestUpdate(); + await primaryAction.click(); + + expect(actionEvent).to.be.calledOnce; + const action = actionEvent.args[0][0].detail.action; + expect(action).to.satisfy(isCreate); + const createAction = action; + + expect(createAction.new.element).to.have.attribute( + 'name', + 'someNonEmptyName' + ); + expect(createAction.new.element).to.not.have.attribute('desc'); + expect(createAction.new.element).to.not.have.attribute('type'); + }); + + it('allows to create non required attributes desc and type', async () => { + inputs[0].value = 'someNonEmptyName'; + + (inputs[1]).nullSwitch?.click(); + (inputs[2]).nullSwitch?.click(); + inputs[1].value = 'SomeDesc'; + inputs[2].value = 'SomeType'; + + await element.requestUpdate(); + await primaryAction.click(); + + expect(actionEvent).to.be.calledOnce; + const action = actionEvent.args[0][0].detail.action; + expect(action).to.satisfy(isCreate); + const createAction = action; + + expect(createAction.new.element).to.have.attribute( + 'name', + 'someNonEmptyName' + ); + expect(createAction.new.element).to.have.attribute('desc', 'SomeDesc'); + expect(createAction.new.element).to.have.attribute('type', 'SomeType'); + }); + }); +}); diff --git a/test/unit/wizards/function.test.ts b/test/unit/wizards/function.test.ts new file mode 100644 index 000000000..593a3e0cc --- /dev/null +++ b/test/unit/wizards/function.test.ts @@ -0,0 +1,102 @@ +import { expect, fixture, html } from '@open-wc/testing'; +import { SinonSpy, spy } from 'sinon'; + +import '../../mock-wizard.js'; +import { MockWizard } from '../../mock-wizard.js'; + +import { WizardTextField } from '../../../src/wizard-textfield.js'; +import { + Create, + isCreate, + WizardInputElement, +} from '../../../src/foundation.js'; +import { createFunctionWizard } from '../../../src/wizards/function.js'; + +describe('Wizards for SCL Function element', () => { + let doc: XMLDocument; + let element: MockWizard; + let inputs: WizardInputElement[]; + + let primaryAction: HTMLElement; + + let actionEvent: SinonSpy; + + beforeEach(async () => { + element = await fixture(html``); + doc = await fetch('test/testfiles/zeroline/functions.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + + actionEvent = spy(); + window.addEventListener('editor-action', actionEvent); + }); + + describe('define an create wizard that', () => { + beforeEach(async () => { + const wizard = createFunctionWizard(doc.querySelector('Substation')!); + element.workflow.push(() => wizard); + await element.requestUpdate(); + + inputs = Array.from(element.wizardUI.inputs); + + primaryAction = ( + element.wizardUI.dialog?.querySelector( + 'mwc-button[slot="primaryAction"]' + ) + ); + + await element.wizardUI.requestUpdate(); // make sure wizard is rendered + }); + + it('looks like the the latest snapshot', async () => + expect(element.wizardUI.dialog).dom.to.equalSnapshot()); + + it('does not accept empty name attribute', async () => { + await primaryAction.click(); + + expect(actionEvent).to.not.have.been.called; + }); + + it('triggers simple create action on primary action click', async () => { + inputs[0].value = 'someNonEmptyName'; + await element.requestUpdate(); + await primaryAction.click(); + + expect(actionEvent).to.be.calledOnce; + const action = actionEvent.args[0][0].detail.action; + expect(action).to.satisfy(isCreate); + const createAction = action; + + expect(createAction.new.element).to.have.attribute( + 'name', + 'someNonEmptyName' + ); + expect(createAction.new.element).to.not.have.attribute('desc'); + expect(createAction.new.element).to.not.have.attribute('type'); + }); + + it('allows to create non required attributes desc and type', async () => { + inputs[0].value = 'someNonEmptyName'; + + (inputs[1]).nullSwitch?.click(); + (inputs[2]).nullSwitch?.click(); + inputs[1].value = 'SomeDesc'; + inputs[2].value = 'SomeType'; + + await element.requestUpdate(); + await primaryAction.click(); + + expect(actionEvent).to.be.calledOnce; + const action = actionEvent.args[0][0].detail.action; + expect(action).to.satisfy(isCreate); + const createAction = action; + + expect(createAction.new.element).to.have.attribute( + 'name', + 'someNonEmptyName' + ); + expect(createAction.new.element).to.have.attribute('desc', 'SomeDesc'); + expect(createAction.new.element).to.have.attribute('type', 'SomeType'); + }); + }); +}); diff --git a/test/unit/wizards/subfunction.test.ts b/test/unit/wizards/subfunction.test.ts new file mode 100644 index 000000000..bcf110957 --- /dev/null +++ b/test/unit/wizards/subfunction.test.ts @@ -0,0 +1,102 @@ +import { expect, fixture, html } from '@open-wc/testing'; +import { SinonSpy, spy } from 'sinon'; + +import '../../mock-wizard.js'; +import { MockWizard } from '../../mock-wizard.js'; + +import { WizardTextField } from '../../../src/wizard-textfield.js'; +import { + Create, + isCreate, + WizardInputElement, +} from '../../../src/foundation.js'; +import { createSubFunctionWizard } from '../../../src/wizards/subfunction.js'; + +describe('Wizards for SCL Function element', () => { + let doc: XMLDocument; + let element: MockWizard; + let inputs: WizardInputElement[]; + + let primaryAction: HTMLElement; + + let actionEvent: SinonSpy; + + beforeEach(async () => { + element = await fixture(html``); + doc = await fetch('test/testfiles/zeroline/functions.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + + actionEvent = spy(); + window.addEventListener('editor-action', actionEvent); + }); + + describe('define an create wizard that', () => { + beforeEach(async () => { + const wizard = createSubFunctionWizard(doc.querySelector('Function')!); + element.workflow.push(() => wizard); + await element.requestUpdate(); + + inputs = Array.from(element.wizardUI.inputs); + + primaryAction = ( + element.wizardUI.dialog?.querySelector( + 'mwc-button[slot="primaryAction"]' + ) + ); + + await element.wizardUI.requestUpdate(); // make sure wizard is rendered + }); + + it('looks like the the latest snapshot', async () => + expect(element.wizardUI.dialog).dom.to.equalSnapshot()); + + it('does not accept empty name attribute', async () => { + await primaryAction.click(); + + expect(actionEvent).to.not.have.been.called; + }); + + it('triggers simple create action on primary action click', async () => { + inputs[0].value = 'someNonEmptyName'; + await element.requestUpdate(); + await primaryAction.click(); + + expect(actionEvent).to.be.calledOnce; + const action = actionEvent.args[0][0].detail.action; + expect(action).to.satisfy(isCreate); + const createAction = action; + + expect(createAction.new.element).to.have.attribute( + 'name', + 'someNonEmptyName' + ); + expect(createAction.new.element).to.not.have.attribute('desc'); + expect(createAction.new.element).to.not.have.attribute('type'); + }); + + it('allows to create non required attributes desc and type', async () => { + inputs[0].value = 'someNonEmptyName'; + + (inputs[1]).nullSwitch?.click(); + (inputs[2]).nullSwitch?.click(); + inputs[1].value = 'SomeDesc'; + inputs[2].value = 'SomeType'; + + await element.requestUpdate(); + await primaryAction.click(); + + expect(actionEvent).to.be.calledOnce; + const action = actionEvent.args[0][0].detail.action; + expect(action).to.satisfy(isCreate); + const createAction = action; + + expect(createAction.new.element).to.have.attribute( + 'name', + 'someNonEmptyName' + ); + expect(createAction.new.element).to.have.attribute('desc', 'SomeDesc'); + expect(createAction.new.element).to.have.attribute('type', 'SomeType'); + }); + }); +});