From 7d32bf516215a107f4e9adec34572995d5438e83 Mon Sep 17 00:00:00 2001
From: Jakob Vogelsang <jakob-vogelsang@posteo.de>
Date: Mon, 4 Jul 2022 10:54:48 +0200
Subject: [PATCH] fix(editors/template): make sure that edit wizards are always
 opened

---
 src/editors/Templates.ts                      |  10 +-
 .../editors/templates/Templates.test.ts       | 161 +++++++++++++++++-
 2 files changed, 163 insertions(+), 8 deletions(-)

diff --git a/src/editors/Templates.ts b/src/editors/Templates.ts
index 93044a62bc..92d89767a3 100644
--- a/src/editors/Templates.ts
+++ b/src/editors/Templates.ts
@@ -51,7 +51,7 @@ const nsd7420 = fetch('public/xml/IEC_61850-7-420_2019A4.nsd')
 /** An editor [[`plugin`]] for editing the `DataTypeTemplates` section. */
 export default class TemplatesPlugin extends LitElement {
   /** The document being edited as provided to plugins by [[`OpenSCD`]]. */
-  @property()
+  @property({ attribute: false })
   doc!: XMLDocument;
 
   async openCreateLNodeTypeWizard(): Promise<void> {
@@ -181,7 +181,7 @@ export default class TemplatesPlugin extends LitElement {
           </h1>
           <filtered-list
             id="lnodetypelist"
-            @selected=${(e: SingleSelectedEvent) =>
+            @action=${(e: SingleSelectedEvent) =>
               this.openLNodeTypeWizard(
                 (<ListItem>(<List>e.target).selected).value
               )}
@@ -221,7 +221,7 @@ export default class TemplatesPlugin extends LitElement {
           </h1>
           <filtered-list
             id="dotypelist"
-            @selected=${(e: SingleSelectedEvent) =>
+            @action=${(e: SingleSelectedEvent) =>
               this.openDOTypeWizard(
                 (<ListItem>(<List>e.target).selected).value
               )}
@@ -260,7 +260,7 @@ export default class TemplatesPlugin extends LitElement {
           </h1>
           <filtered-list
             id="datypelist"
-            @selected=${(e: SingleSelectedEvent) =>
+            @action=${(e: SingleSelectedEvent) =>
               this.openDATypeWizard(
                 (<ListItem>(<List>e.target).selected).value
               )}
@@ -296,7 +296,7 @@ export default class TemplatesPlugin extends LitElement {
           </h1>
           <filtered-list
             id="enumtypelist"
-            @selected=${(e: SingleSelectedEvent) =>
+            @action=${(e: SingleSelectedEvent) =>
               this.openEnumTypeWizard(
                 (<ListItem>(<List>e.target).selected).value
               )}
diff --git a/test/integration/editors/templates/Templates.test.ts b/test/integration/editors/templates/Templates.test.ts
index b045200043..e2e61ce680 100644
--- a/test/integration/editors/templates/Templates.test.ts
+++ b/test/integration/editors/templates/Templates.test.ts
@@ -3,18 +3,30 @@ import { html, fixture, expect } from '@open-wc/testing';
 import '../../../mock-wizard-editor.js';
 import { MockWizardEditor } from '../../../mock-wizard-editor.js';
 
+import TemplatesPlugin from '../../../../src/editors/Templates.js';
 import { Editing, EditingElement } from '../../../../src/Editing.js';
 import { Wizarding, WizardingElement } from '../../../../src/Wizarding.js';
-import TemplatesPlugin from '../../../../src/editors/Templates.js';
+import { newWizardEvent } from '../../../../src/foundation.js';
 
 describe('Templates Plugin', () => {
   customElements.define(
     'templates-plugin',
     Wizarding(Editing(TemplatesPlugin))
   );
+
   let element: TemplatesPlugin;
+  let parent: MockWizardEditor;
+
   beforeEach(async () => {
-    element = await fixture(html`<templates-plugin></templates-plugin>`);
+    parent = <MockWizardEditor>(
+      await fixture(
+        html`<mock-wizard-editor
+          ><templates-plugin></templates-plugin
+        ></mock-wizard-editor>`
+      )
+    );
+
+    element = parent.querySelector<TemplatesPlugin>('templates-plugin')!;
   });
 
   describe('without a doc loaded', () => {
@@ -29,12 +41,150 @@ describe('Templates Plugin', () => {
       doc = await fetch('/test/testfiles/templates/datypes.scd')
         .then(response => response.text())
         .then(str => new DOMParser().parseFromString(str, 'application/xml'));
+
       element.doc = doc;
-      await element.updateComplete;
+      await element.requestUpdate();
     });
+
     it('looks like the latest snapshot', async () => {
       await expect(element).shadowDom.to.equalSnapshot();
     });
+
+    describe('having a LNodeType element list that', () => {
+      beforeEach(async () => {
+        parent.workflow.length = 0;
+        (<HTMLElement>(
+          element?.shadowRoot
+            ?.querySelectorAll('filtered-list')[0]
+            .querySelector('mwc-list-item')
+        )).click();
+
+        await parent.requestUpdate();
+      });
+
+      it('opens a LNodeType edit wizard on list element click', () =>
+        expect(
+          parent.wizardUI.dialog?.querySelector(
+            'wizard-textfield[label="lnClass"]'
+          )
+        ).to.exist);
+
+      it('allows to reopen the LNodeType edit wizard for the same element', async () => {
+        parent.dispatchEvent(newWizardEvent());
+
+        await parent.requestUpdate();
+
+        (<HTMLElement>(
+          element?.shadowRoot?.querySelector(
+            'filtered-list:nth-of-type(1) > mwc-list-item'
+          )
+        )).click();
+        await parent.requestUpdate();
+
+        expect(
+          parent.wizardUI.dialog?.querySelector(
+            'wizard-textfield[label="lnClass"]'
+          )
+        ).to.exist;
+      });
+    });
+
+    describe('having a DOType element list that', () => {
+      beforeEach(async () => {
+        parent.workflow.length = 0;
+        (<HTMLElement>(
+          element?.shadowRoot
+            ?.querySelectorAll('filtered-list')[1]
+            .querySelector('mwc-list-item')
+        )).click();
+
+        await parent.requestUpdate();
+      });
+
+      it('opens a DOType edit wizard on list element click', () =>
+        expect(
+          parent.wizardUI.dialog?.querySelector('wizard-textfield[label="CDC"]')
+        ).to.exist);
+
+      it('allows to reopen the DOType edit wizard for the same element', async () => {
+        parent.dispatchEvent(newWizardEvent());
+
+        await parent.requestUpdate();
+
+        (<HTMLElement>(
+          element?.shadowRoot
+            ?.querySelectorAll('filtered-list')[1]
+            .querySelector('mwc-list-item')
+        )).click();
+        await parent.requestUpdate();
+
+        expect(
+          parent.wizardUI.dialog?.querySelector('wizard-textfield[label="CDC"]')
+        ).to.exist;
+      });
+    });
+
+    describe('having a DAType element list that', () => {
+      beforeEach(async () => {
+        parent.workflow.length = 0;
+        (<HTMLElement>(
+          element?.shadowRoot
+            ?.querySelectorAll('filtered-list')[2]
+            .querySelector('mwc-list-item')
+        )).click();
+
+        await parent.requestUpdate();
+      });
+
+      it('opens a DAType edit wizard on list element click', () =>
+        expect(parent.wizardUI.dialog).to.exist);
+
+      it('allows to reopen the DAType edit wizard for the same element', async () => {
+        parent.dispatchEvent(newWizardEvent());
+
+        await parent.requestUpdate();
+
+        (<HTMLElement>(
+          element?.shadowRoot
+            ?.querySelectorAll('filtered-list')[3]
+            .querySelector('mwc-list-item')
+        )).click();
+        await parent.requestUpdate();
+
+        expect(parent.wizardUI.dialog).to.exist;
+      });
+    });
+
+    describe('having a EnumType element list that', () => {
+      beforeEach(async () => {
+        parent.workflow.length = 0;
+        (<HTMLElement>(
+          element?.shadowRoot
+            ?.querySelectorAll('filtered-list')[3]
+            .querySelector('mwc-list-item')
+        )).click();
+
+        await parent.requestUpdate();
+      });
+
+      it('opens a EnumType edit wizard on list element click', () =>
+        expect(parent.wizardUI.dialog).to.exist);
+
+      it('allows to reopen the EnumType edit wizard for the same element', async () => {
+        parent.dispatchEvent(newWizardEvent());
+
+        await parent.requestUpdate();
+
+        (<HTMLElement>(
+          element?.shadowRoot
+            ?.querySelectorAll('filtered-list')[3]
+            .querySelector('mwc-list-item')
+        )).click();
+        await parent.requestUpdate();
+
+        expect(parent.wizardUI.dialog).to.exist;
+      });
+    });
   });
 
   describe('with a doc loaded missing a datatypetemplates section', () => {
@@ -55,9 +205,11 @@ describe('Templates Plugin', () => {
       );
       await element.updateComplete;
     });
+
     it('has a mwc-fab', () => {
       expect(element.shadowRoot?.querySelector('mwc-fab')).to.exist;
     });
+
     it('adds a DataTypeTemplates on floating action button click', async () => {
       expect(doc.querySelector('DataTypeTemplates')).to.not.exist;
       (<HTMLElement>(
@@ -73,6 +225,7 @@ describe('Templates Plugin', () => {
       ).to.exist;
     });
   });
+
   describe('with a doc loaded having a datatypetemplates section', () => {
     let doc: XMLDocument;
     let parent: WizardingElement & EditingElement;
@@ -90,6 +243,7 @@ describe('Templates Plugin', () => {
       );
       await element.updateComplete;
     });
+
     it('opens an add enumtype wizard', async () => {
       expect(parent.wizardUI.dialogs.length).to.equal(0);
       (<HTMLElement>(
@@ -103,6 +257,7 @@ describe('Templates Plugin', () => {
       await new Promise(resolve => setTimeout(resolve, 100)); // await animation
       expect(parent.wizardUI.dialogs.length).to.equal(1);
     });
+
     it('adding an EnumType with the enumtype wizard', async () => {
       expect(doc.querySelectorAll('EnumType').length).to.equal(4);
       (<HTMLElement>(