diff --git a/packages/open-scd/src/addons/Layout.ts b/packages/open-scd/src/addons/Layout.ts new file mode 100644 index 0000000000..2df334e75c --- /dev/null +++ b/packages/open-scd/src/addons/Layout.ts @@ -0,0 +1,807 @@ +import { + customElement, + html, + LitElement, + property, + state, + TemplateResult, + query, + css +} from 'lit-element'; +import { get } from 'lit-translate'; +import { newPendingStateEvent } from '@openscd/core/foundation/deprecated/waiter.js'; +import { newSettingsUIEvent } from '@openscd/core/foundation/deprecated/settings.js'; +import { MenuItem, Plugin, Validator, PluginKind, MenuPosition, MenuPlugin, menuPosition, pluginIcons, newResetPluginsEvent, newAddExternalPluginEvent, newSetPluginsEvent } from '../open-scd.js'; +import { HistoryUIKind, newEmptyIssuesEvent, newHistoryUIEvent, newRedoEvent, newUndoEvent, UndoRedoChangedEvent } from './History.js'; +import type { Drawer } from '@material/mwc-drawer'; +import type { ActionDetail } from '@material/mwc-list'; +import { List } from '@material/mwc-list'; +import type { ListItem } from '@material/mwc-list/mwc-list-item'; +import type { Dialog } from '@material/mwc-dialog'; +import type { MultiSelectedEvent } from '@material/mwc-list/mwc-list-foundation.js'; +import type { Select } from '@material/mwc-select'; +import type { Switch } from '@material/mwc-switch'; +import type { TextField } from '@material/mwc-textfield'; + +import '@material/mwc-drawer'; +import '@material/mwc-list'; +import '@material/mwc-dialog'; +import '@material/mwc-switch'; +import '@material/mwc-select'; +import '@material/mwc-textfield'; + +@customElement('oscd-layout') +export class OscdLayout extends LitElement { + + /** The `XMLDocument` to be edited */ + @property({ attribute: false }) + doc: XMLDocument | null = null; + /** The name of the current [[`doc`]] */ + @property({ type: String }) + docName = ''; + /** Index of the last [[`EditorAction`]] applied. */ + @property({ type: Number }) + editCount = -1; + /** The currently active editor tab. */ + @property({ type: Number }) + activeTab = 0; + + /** The plugins to render the layout. */ + @property({ type: Array }) + plugins: Plugin[] = []; + + /** The open-scd host element */ + @property({ type: Object }) + host!: HTMLElement; + + @state() + validated: Promise = Promise.resolve(); + + @state() + shouldValidate = false; + + @state() + canRedo = false; + + @state() + canUndo = false; + + @query('#menu') + menuUI!: Drawer; + @query('#pluginManager') + pluginUI!: Dialog; + @query('#pluginList') + pluginList!: List; + @query('#pluginAdd') + pluginDownloadUI!: Dialog; + + // Computed properties + + get validators(): Plugin[] { + return this.plugins.filter( + plugin => plugin.installed && plugin.kind === 'validator' + ); + } + get menuEntries(): Plugin[] { + return this.plugins.filter( + plugin => plugin.installed && plugin.kind === 'menu' + ); + } + get topMenu(): Plugin[] { + return this.menuEntries.filter(plugin => plugin.position === 'top'); + } + get middleMenu(): Plugin[] { + return this.menuEntries.filter(plugin => plugin.position === 'middle'); + } + get bottomMenu(): Plugin[] { + return this.menuEntries.filter(plugin => plugin.position === 'bottom'); + } + + get menu(): (MenuItem | 'divider')[] { + const topMenu: (MenuItem | 'divider')[] = []; + const middleMenu: (MenuItem | 'divider')[] = []; + const bottomMenu: (MenuItem | 'divider')[] = []; + const validators: (MenuItem | 'divider')[] = []; + + this.topMenu.forEach(plugin => + topMenu.push({ + icon: plugin.icon || pluginIcons['menu'], + name: plugin.name, + action: ae => { + this.dispatchEvent( + newPendingStateEvent( + (( + (( + (ae.target).items[ae.detail.index].nextElementSibling + )) + )).run() + ) + ); + }, + disabled: (): boolean => plugin.requireDoc! && this.doc === null, + content: plugin.content, + kind: 'top', + }) + ); + + this.middleMenu.forEach(plugin => + middleMenu.push({ + icon: plugin.icon || pluginIcons['menu'], + name: plugin.name, + action: ae => { + this.dispatchEvent( + newPendingStateEvent( + (( + (( + (ae.target).items[ae.detail.index].nextElementSibling + )) + )).run() + ) + ); + }, + disabled: (): boolean => plugin.requireDoc! && this.doc === null, + content: plugin.content, + kind: 'middle', + }) + ); + + this.bottomMenu.forEach(plugin => + bottomMenu.push({ + icon: plugin.icon || pluginIcons['menu'], + name: plugin.name, + action: ae => { + this.dispatchEvent( + newPendingStateEvent( + (( + (( + (ae.target).items[ae.detail.index].nextElementSibling + )) + )).run() + ) + ); + }, + disabled: (): boolean => plugin.requireDoc! && this.doc === null, + content: plugin.content, + kind: 'middle', + }) + ); + + this.validators.forEach(plugin => + validators.push({ + icon: plugin.icon || pluginIcons['validator'], + name: plugin.name, + action: ae => { + this.dispatchEvent(newEmptyIssuesEvent(plugin.src)); + + this.dispatchEvent( + newPendingStateEvent( + (( + (( + (ae.target).items[ae.detail.index].nextElementSibling + )) + )).validate() + ) + ); + }, + disabled: (): boolean => this.doc === null, + content: plugin.content, + kind: 'validator', + }) + ); + + if (middleMenu.length > 0) middleMenu.push('divider'); + if (bottomMenu.length > 0) bottomMenu.push('divider'); + + return [ + 'divider', + ...topMenu, + 'divider', + { + icon: 'undo', + name: 'undo', + actionItem: true, + action: (): void => { + this.dispatchEvent(newUndoEvent()) + }, + disabled: (): boolean => !this.canUndo, + kind: 'static', + }, + { + icon: 'redo', + name: 'redo', + actionItem: true, + action: (): void => { + this.dispatchEvent(newRedoEvent()) + }, + disabled: (): boolean => !this.canRedo, + kind: 'static', + }, + ...validators, + { + icon: 'list', + name: 'menu.viewLog', + actionItem: true, + action: (): void => { + this.dispatchEvent(newHistoryUIEvent(true, HistoryUIKind.log)) + }, + kind: 'static', + }, + { + icon: 'history', + name: 'menu.viewHistory', + actionItem: true, + action: (): void => { + this.dispatchEvent(newHistoryUIEvent(true, HistoryUIKind.history)) + }, + kind: 'static', + }, + { + icon: 'rule', + name: 'menu.viewDiag', + actionItem: true, + action: (): void => { + this.dispatchEvent(newHistoryUIEvent(true, HistoryUIKind.diagnostic)) + }, + kind: 'static', + }, + 'divider', + ...middleMenu, + { + icon: 'settings', + name: 'settings.title', + action: (): void => { + this.dispatchEvent(newSettingsUIEvent(true)); + }, + kind: 'static', + }, + ...bottomMenu, + { + icon: 'extension', + name: 'plugins.heading', + action: (): void => this.pluginUI.show(), + kind: 'static', + }, + ]; + } + + get editors(): Plugin[] { + return this.plugins.filter( + plugin => plugin.installed && plugin.kind === 'editor' + ); + } + + + + // Keyboard Shortcuts + private handleKeyPress(e: KeyboardEvent): void { + let handled = false; + const ctrlAnd = (key: string) => + e.key === key && e.ctrlKey && (handled = true); + + if (ctrlAnd('m')) this.menuUI.open = !this.menuUI.open; + if (ctrlAnd('o')) + this.menuUI + .querySelector('mwc-list-item[iconid="folder_open"]') + ?.click(); + if (ctrlAnd('O')) + this.menuUI + .querySelector('mwc-list-item[iconid="create_new_folder"]') + ?.click(); + if (ctrlAnd('s')) + this.menuUI + .querySelector('mwc-list-item[iconid="save"]') + ?.click(); + if (ctrlAnd('P')) this.pluginUI.show(); + + if (handled) e.preventDefault(); + } + + private handleAddPlugin() { + const pluginSrcInput = ( + this.pluginDownloadUI.querySelector('#pluginSrcInput') + ); + const pluginNameInput = ( + this.pluginDownloadUI.querySelector('#pluginNameInput') + ); + const pluginKindList = ( + this.pluginDownloadUI.querySelector('#pluginKindList') + ); + const requireDoc = ( + this.pluginDownloadUI.querySelector('#requireDoc') + ); + const positionList = ( - this.pluginDownloadUI.querySelector('#menuPosition') - ); - - if ( - !( - pluginSrcInput.checkValidity() && - pluginNameInput.checkValidity() && - pluginKindList.selected && - requireDoc && - positionList.selected - ) - ) - return; - - this.addExternalPlugin({ - src: pluginSrcInput.value, - name: pluginNameInput.value, - kind: (pluginKindList.selected).value, - requireDoc: requireDoc.checked, - position: positionList.value, - installed: true, - }); - - this.requestUpdate(); - this.pluginUI.requestUpdate(); - this.pluginDownloadUI.close(); - } - - renderDownloadUI(): TemplateResult { - return html` - -
-

- ${get('plugins.add.warning')} -

- - - ${get('plugins.editor')}${pluginIcons['editor']} - ${get('plugins.menu')}${pluginIcons['menu']} - - - ${get('plugins.validator')}${pluginIcons['validator']} - - -
- - this.handleAddPlugin()} - > -
- `; - } - - renderPluginKind( - type: PluginKind | MenuPosition, - plugins: Plugin[] - ): TemplateResult { - return html` - ${plugins.map( - plugin => - html` - ${plugin.icon || pluginIcons[plugin.kind]} - ${plugin.name} - ` - )} - `; - } - - renderPluginUI(): TemplateResult { - return html` - - - this.setPlugins(e.detail.index)} - > - ${get(`plugins.editor`)}${pluginIcons['editor']} -
  • - ${this.renderPluginKind( - 'editor', - this.plugins.filter(p => p.kind === 'editor') - )} - ${get(`plugins.menu`)}${pluginIcons['menu']} -
  • - ${this.renderPluginKind( - 'top', - this.plugins.filter(p => p.kind === 'menu' && p.position === 'top') - )} -
  • - ${this.renderPluginKind( - 'validator', - this.plugins.filter(p => p.kind === 'validator') - )} -
  • - ${this.renderPluginKind( - 'middle', - this.plugins.filter( - p => p.kind === 'menu' && p.position === 'middle' - ) - )} -
  • - ${this.renderPluginKind( - 'bottom', - this.plugins.filter( - p => p.kind === 'menu' && p.position === 'bottom' - ) - )} -
    - { - resetPlugins(); - this.requestUpdate(); - }} - style="--mdc-theme-primary: var(--mdc-theme-error)" - > - - - this.pluginDownloadUI.show()} - > - -
    - `; - } - - renderPlugging(): TemplateResult { - return html` ${this.renderPluginUI()} ${this.renderDownloadUI()} `; +declare global { + interface ElementEventMap { + 'reset-plugins': CustomEvent; + 'add-external-plugin': CustomEvent; + 'set-plugins': CustomEvent; } } diff --git a/packages/open-scd/test/integration/__snapshots__/open-scd.test.snap.js b/packages/open-scd/test/integration/__snapshots__/open-scd.test.snap.js index 1cba72b889..a866d2a4ec 100644 --- a/packages/open-scd/test/integration/__snapshots__/open-scd.test.snap.js +++ b/packages/open-scd/test/integration/__snapshots__/open-scd.test.snap.js @@ -7,1053 +7,8 @@ snapshots["open-scd looks like its snapshot"] = - - - Menu - - -
  • -
  • - - - folder_open - - - Open project - - - - - - - create_new_folder - - - New project - - - - - - - save - - - Save project - - - - -
  • -
  • - - - rule_folder - - - Validate Schema - - - - - - - rule_folder - - - Validate Templates - - - - -
  • -
  • - - - snippet_folder - - - Import IEDs - - - - - - - play_circle - - - Subscriber Update - - - - - - - merge_type - - - Merge Project - - - - - - - merge_type - - - Update Substation - - - - - - - compare_arrows - - - Compare IED - - - - -
  • -
  • - - - settings - - - Settings - - - - - help - - - Help - - - - - - - history_toggle_off - - - Show SCL History - - - - -
  • -
  • - - - extension - - - Plug-ins - - -
    - - - -
    -
    - - - - - - - - - - -
    -
    -
    - -
    - Open project -
    -
    - -
    - New project -
    -
    -
    - - - - - Editor tab - - - tab - - -
  • -
  • - - - developer_board - - IED - - - - margin - - Substation - - - - edit - - Single Line Diagram - - - - link - - Subscriber Message Binding (GOOSE) - - - - link - - Subscriber Data Binding (GOOSE) - - - - link - - Subscriber Later Binding (GOOSE) - - - - link - - Subscriber Message Binding (SMV) - - - - link - - Subscriber Data Binding (SMV) - - - - link - - Subscriber Later Binding (SMV) - - - - settings_ethernet - - Communication - - - - settings_ethernet - - 104 - - - - copy_all - - Templates - - - - publish - - Publisher - - - - cleaning_services - - Cleanup - - - - Menu entry - - - - play_circle - - - -
  • -
  • - - - folder_open - - Open project - - - - create_new_folder - - New project - - - - save - - Save project - -
  • -
  • - - - rule_folder - - Validate Schema - - - - rule_folder - - Validate Templates - -
  • -
  • - - - snippet_folder - - Import IEDs - - - - developer_board - - Create Virtual IED - - - - play_circle - - Subscriber Update - - - - play_circle - - Update desc (ABB) - - - - play_circle - - Update desc (SEL) - - - - merge_type - - Merge Project - - - - merge_type - - Update Substation - - - - compare_arrows - - Compare IED - - - - sim_card_download - - Export Communication Section - -
  • -
  • - - - help - - Help - - - - history_toggle_off - - Show SCL History - -
    - - - - - - -
    - -
    -

    - Here you may add remote plug-ins directly from a custom URL. - You do this at your own risk. -

    - - - - - Editor tab - - tab - - - - Menu entry - - play_circle - - - - - Validator - - rule_folder - - - - - -
    - - - - -
    + +
    @@ -1062,3 +17,1056 @@ snapshots["open-scd looks like its snapshot"] = `; /* end snapshot open-scd looks like its snapshot */ +snapshots["open-scd layout looks like its snapshot"] = +` + + + + +
    +
    + + + + + + + + + + +
    + + + Menu + + +
  • +
  • + + + folder_open + + + Open project + + + + + + + create_new_folder + + + New project + + + + + + + save + + + Save project + + + + +
  • +
  • + + + rule_folder + + + Validate Schema + + + + + + + rule_folder + + + Validate Templates + + + + +
  • +
  • + + + snippet_folder + + + Import IEDs + + + + + + + play_circle + + + Subscriber Update + + + + + + + merge_type + + + Merge Project + + + + + + + merge_type + + + Update Substation + + + + + + + compare_arrows + + + Compare IED + + + + +
  • +
  • + + + settings + + + Settings + + + + + help + + + Help + + + + + + + history_toggle_off + + + Show SCL History + + + + +
  • +
  • + + + extension + + + Plug-ins + + +
    +
    +
    + +
    + Open project +
    +
    + +
    + New project +
    +
    +
    + + + + + Editor tab + + + tab + + +
  • +
  • + + + developer_board + + IED + + + + margin + + Substation + + + + edit + + Single Line Diagram + + + + link + + Subscriber Message Binding (GOOSE) + + + + link + + Subscriber Data Binding (GOOSE) + + + + link + + Subscriber Later Binding (GOOSE) + + + + link + + Subscriber Message Binding (SMV) + + + + link + + Subscriber Data Binding (SMV) + + + + link + + Subscriber Later Binding (SMV) + + + + settings_ethernet + + Communication + + + + settings_ethernet + + 104 + + + + copy_all + + Templates + + + + publish + + Publisher + + + + cleaning_services + + Cleanup + + + + Menu entry + + + + play_circle + + + +
  • +
  • + + + folder_open + + Open project + + + + create_new_folder + + New project + + + + save + + Save project + +
  • +
  • + + + rule_folder + + Validate Schema + + + + rule_folder + + Validate Templates + +
  • +
  • + + + snippet_folder + + Import IEDs + + + + developer_board + + Create Virtual IED + + + + play_circle + + Subscriber Update + + + + play_circle + + Update desc (ABB) + + + + play_circle + + Update desc (SEL) + + + + merge_type + + Merge Project + + + + merge_type + + Update Substation + + + + compare_arrows + + Compare IED + + + + sim_card_download + + Export Communication Section + +
  • +
  • + + + help + + Help + + + + history_toggle_off + + Show SCL History + +
    + + + + + + +
    + +
    +

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

    + + + + + Editor tab + + tab + + + + Menu entry + + play_circle + + + + + Validator + + rule_folder + + + + + +
    + + + + +
    +`; +/* end snapshot open-scd layout looks like its snapshot */ + diff --git a/packages/open-scd/test/integration/open-scd.test.ts b/packages/open-scd/test/integration/open-scd.test.ts index e13468c24c..c1ce20c5ff 100644 --- a/packages/open-scd/test/integration/open-scd.test.ts +++ b/packages/open-scd/test/integration/open-scd.test.ts @@ -5,10 +5,12 @@ import { newEmptySCD } from '../../src/schemas.js'; import { OpenSCD } from '../../src/open-scd.js'; import { OscdWaiter } from '../../src/addons/Waiter.js'; import { OscdHistory } from '../../src/addons/History.js'; +import { OscdLayout } from '../../src/addons/Layout.js'; describe('open-scd', () => { let element: OpenSCD; let historyAddon: OscdHistory; + let layoutAddon: OscdLayout; beforeEach(async () => { localStorage.clear(); @@ -24,18 +26,24 @@ describe('open-scd', () => { `); await element.updateComplete; historyAddon = element.shadowRoot?.querySelector('oscd-history') as OscdHistory; - + layoutAddon = element.shadowRoot?.querySelector('oscd-layout') as OscdLayout; }); it('looks like its snapshot', async () => { await expect(element).shadowDom.to.equalSnapshot(); }); + describe('layout', () => { + it('looks like its snapshot', async () => { + await expect(layoutAddon).shadowDom.to.equalSnapshot(); + }); + }); + it('opens the menu on navigation icon click', async () => { - const menu = element.shadowRoot!.querySelector('mwc-drawer')!; + const menu = layoutAddon.shadowRoot!.querySelector('mwc-drawer')!; expect(menu).property('open').to.be.false; const menuButton = ( - element.shadowRoot!.querySelector( + layoutAddon.shadowRoot!.querySelector( 'mwc-icon-button[slot="navigationIcon"]' ) ); @@ -46,7 +54,7 @@ describe('open-scd', () => { it('opens the log on log icon click', async () => { expect(historyAddon.logUI).to.have.property('open', false); await (( - element.shadowRoot!.querySelector('mwc-icon-button[icon="list"]')! + layoutAddon.shadowRoot!.querySelector('mwc-icon-button[icon="list"]')! )).click(); expect(historyAddon.logUI).to.have.property('open', true); }); @@ -54,7 +62,7 @@ describe('open-scd', () => { it('opens the history on history icon click', async () => { expect(historyAddon.historyUI).to.have.property('open', false); await (( - element.shadowRoot!.querySelector('mwc-icon-button[icon="history"]')! + layoutAddon.shadowRoot!.querySelector('mwc-icon-button[icon="history"]')! )).click(); expect(historyAddon.historyUI).to.have.property('open', true); }); diff --git a/packages/open-scd/test/mock-open-scd.ts b/packages/open-scd/test/mock-open-scd.ts index 4edf4db6c1..597d549a3a 100644 --- a/packages/open-scd/test/mock-open-scd.ts +++ b/packages/open-scd/test/mock-open-scd.ts @@ -10,6 +10,7 @@ import { WizardFactory } from '../src/foundation.js'; import { OpenSCD } from '../src/open-scd.js'; import { WizardDialog } from '../src/wizard-dialog.js'; import { OscdHistory } from '../src/addons/History.js'; +import { OscdLayout } from '../src/addons/Layout.js'; @customElement('mock-open-scd') export class MockOpenSCD extends OpenSCD { @@ -22,10 +23,19 @@ export class MockOpenSCD extends OpenSCD { @query('oscd-history') historyAddon!: OscdHistory; + @query('oscd-layout') + layout!: OscdLayout; + renderHosting(): TemplateResult { return html``; } + render(): TemplateResult { + return html` + ${this.renderHosting()} + ${super.render()}`; + } + getPlugin(name: string): T | undefined { return this._plugins.find( p => p.tagName.toLowerCase() === name.toLowerCase() diff --git a/packages/open-scd/test/unit/Plugging.test.ts b/packages/open-scd/test/unit/Plugging.test.ts index 7f4c7f4f06..60a5605585 100644 --- a/packages/open-scd/test/unit/Plugging.test.ts +++ b/packages/open-scd/test/unit/Plugging.test.ts @@ -27,7 +27,7 @@ describe('OpenSCD-Plugin', () => { }); it('stores default plugins on load', () => - expect(element).property('editors').to.have.lengthOf(6)); + expect(element.layout).property('editors').to.have.lengthOf(6)); it('has Locale property', async () => { expect(element).to.have.property('locale'); @@ -44,48 +44,48 @@ describe('OpenSCD-Plugin', () => { let primaryAction: HTMLElement; beforeEach(async () => { - element.pluginUI.show(); - await element.pluginUI.updateComplete; + element.layout.pluginUI.show(); + await element.layout.pluginUI.updateComplete; firstEditorPlugin = ( - element.pluginList.querySelector( + element.layout.pluginList.querySelector( 'mwc-check-list-item:not([noninteractive])' ) ); resetAction = ( - element.pluginUI.querySelector('mwc-button[slot="secondaryAction"]') + element.layout.pluginUI.querySelector('mwc-button[slot="secondaryAction"]') ); primaryAction = ( - element.pluginUI.querySelector('mwc-button[slot="primaryAction"]') + element.layout.pluginUI.querySelector('mwc-button[slot="primaryAction"]') ); }); it('disables deselected plugins', async () => { firstEditorPlugin.click(); await element.updateComplete; - expect(element).property('editors').to.have.lengthOf(5); + expect(element.layout).property('editors').to.have.lengthOf(5); }); it('enables selected plugins', async () => { - (element.pluginList.firstElementChild).click(); + (element.layout.pluginList.firstElementChild).click(); await element.updateComplete; - (element.pluginList.firstElementChild).click(); + (element.layout.pluginList.firstElementChild).click(); await element.updateComplete; - expect(element).property('editors').to.have.lengthOf(6); + expect(element.layout).property('editors').to.have.lengthOf(6); }); it('resets plugins to default on reset button click', async () => { - (element.pluginList.firstElementChild).click(); + (element.layout.pluginList.firstElementChild).click(); await element.updateComplete; resetAction.click(); await element.updateComplete; - expect(element).property('editors').to.have.lengthOf(6); + expect(element.layout).property('editors').to.have.lengthOf(6); }); it('opens the custom plugin dialog on add button click', async () => { primaryAction.click(); await element.updateComplete; - expect(element) + expect(element.layout) .property('pluginDownloadUI') .to.have.property('open', true); }); @@ -100,25 +100,26 @@ describe('OpenSCD-Plugin', () => { beforeEach(async () => { src = ( - element.pluginDownloadUI.querySelector('#pluginSrcInput') + element.layout.pluginDownloadUI.querySelector('#pluginSrcInput') ); name = ( - element.pluginDownloadUI.querySelector('#pluginNameInput') + element.layout.pluginDownloadUI.querySelector('#pluginNameInput') ); primaryAction = ( - element.pluginDownloadUI.querySelector( + element.layout.pluginDownloadUI.querySelector( 'mwc-button[slot="primaryAction"]' ) ); - element.pluginDownloadUI.show(); - await element.pluginDownloadUI.updateComplete; + element.layout.pluginDownloadUI.show(); + await element.layout.pluginDownloadUI.updateComplete; + await element.updateComplete; menuKindOption = ( - element.pluginDownloadUI.querySelector( + element.layout.pluginDownloadUI.querySelector( '#pluginKindList > mwc-radio-list-item[value="menu"]' ) ); validatorKindOption = ( - element.pluginDownloadUI.querySelector( + element.layout.pluginDownloadUI.querySelector( '#pluginKindList > mwc-radio-list-item[id="validator"]' ) ); @@ -126,24 +127,24 @@ describe('OpenSCD-Plugin', () => { it('requires a name and a valid URL to add a plugin', async () => { primaryAction.click(); - expect(element.pluginDownloadUI).to.have.property('open', true); + expect(element.layout.pluginDownloadUI).to.have.property('open', true); src.value = 'http://example.com/plugin.js'; await src.updateComplete; primaryAction.click(); - expect(element.pluginDownloadUI).to.have.property('open', true); + expect(element.layout.pluginDownloadUI).to.have.property('open', true); src.value = 'notaURL'; name.value = 'testName'; await src.updateComplete; await name.updateComplete; primaryAction.click(); - expect(element.pluginDownloadUI).to.have.property('open', true); + expect(element.layout.pluginDownloadUI).to.have.property('open', true); src.value = 'http://example.com/plugin.js'; await src.updateComplete; primaryAction.click(); - expect(element.pluginDownloadUI).to.have.property('open', false); + expect(element.layout.pluginDownloadUI).to.have.property('open', false); }); it('adds a new editor kind plugin on add button click', async () => { @@ -153,10 +154,10 @@ describe('OpenSCD-Plugin', () => { await name.updateComplete; primaryAction.click(); await element.updateComplete; - expect(element.editors).to.have.lengthOf(7); + expect(element.layout.editors).to.have.lengthOf(7); }); it('adds a new menu kind plugin on add button click', async () => { - const lengthMenuKindPlugins = element.menuEntries.length; + const lengthMenuKindPlugins = element.layout.menuEntries.length; src.value = 'http://example.com/plugin.js'; name.value = 'testName'; menuKindOption.click(); @@ -164,7 +165,7 @@ describe('OpenSCD-Plugin', () => { await name.updateComplete; primaryAction.click(); await element.updateComplete; - expect(element.menuEntries).to.have.lengthOf(lengthMenuKindPlugins + 1); + expect(element.layout.menuEntries).to.have.lengthOf(lengthMenuKindPlugins + 1); }); it('sets requireDoc and position for new menu kind plugin', async () => { src.value = 'http://example.com/plugin.js'; @@ -176,14 +177,14 @@ describe('OpenSCD-Plugin', () => { await element.updateComplete; expect( - element.menuEntries[element.menuEntries.length - 1] + element.layout.menuEntries[element.layout.menuEntries.length - 1] ).to.have.property('requireDoc'); expect( - element.menuEntries[element.menuEntries.length - 1] + element.layout.menuEntries[element.layout.menuEntries.length - 1] ).to.have.property('position'); }); it('adds a new validator kind plugin on add button click', async () => { - expect(element.validators).to.have.lengthOf(2); + expect(element.layout.validators).to.have.lengthOf(2); src.value = 'http://example.com/plugin.js'; name.value = 'testName'; validatorKindOption.click(); @@ -191,7 +192,7 @@ describe('OpenSCD-Plugin', () => { await name.updateComplete; primaryAction.click(); await element.updateComplete; - expect(element.validators).to.have.lengthOf(3); + expect(element.layout.validators).to.have.lengthOf(3); }); }); });