From 8a74e33625d1c751ac9cd31ac1399e43d477f10b Mon Sep 17 00:00:00 2001 From: Danny Moerkerke Date: Tue, 9 Aug 2022 13:51:24 +0200 Subject: [PATCH] fix: fixed test for appending content --- packages/accordion/src/LionAccordion.js | 24 +++++--- .../accordion/test/lion-accordion.test.js | 61 +++++++++++++------ 2 files changed, 59 insertions(+), 26 deletions(-) diff --git a/packages/accordion/src/LionAccordion.js b/packages/accordion/src/LionAccordion.js index 31c34717d..0abd92bc4 100644 --- a/packages/accordion/src/LionAccordion.js +++ b/packages/accordion/src/LionAccordion.js @@ -175,12 +175,20 @@ export class LionAccordion extends LitElement { * @private */ __setupStore() { - const invokers = /** @type {HTMLElement[]} */ ( - Array.from(this.querySelectorAll('[slot="invoker"]')) - ); - const contents = /** @type {HTMLElement[]} */ ( - Array.from(this.querySelectorAll('[slot="content"]')) - ); + const accordion = this.shadowRoot?.querySelector('slot[name=accordion]'); + const existingInvokers = accordion ? accordion.querySelectorAll('[slot=invoker]') : []; + const existingContent = accordion ? accordion.querySelectorAll('[slot=content]') : []; + + const invokers = /** @type {HTMLElement[]} */ ([ + ...Array.from(existingInvokers), + ...Array.from(this.querySelectorAll('[slot="invoker"]')), + ]); + + const contents = /** @type {HTMLElement[]} */ ([ + ...Array.from(existingContent), + ...Array.from(this.querySelectorAll('[slot="content"]')), + ]); + if (invokers.length !== contents.length) { // eslint-disable-next-line no-console console.warn( @@ -202,11 +210,12 @@ export class LionAccordion extends LitElement { }; this._setupContent(entry); this._setupInvoker(entry); - this.__rearrangeInvokersAndContent(); this._unfocusInvoker(entry); this._collapse(entry); this.__store.push(entry); }); + + this.__rearrangeInvokersAndContent(); } /** @@ -220,7 +229,6 @@ export class LionAccordion extends LitElement { Array.from(this.querySelectorAll('[slot="content"]')) ); const accordion = this.shadowRoot?.querySelector('slot[name=accordion]'); - if (accordion) { invokers.forEach((invoker, index) => { accordion.insertAdjacentElement('beforeend', invoker); diff --git a/packages/accordion/test/lion-accordion.test.js b/packages/accordion/test/lion-accordion.test.js index d5d715fce..2bce2f235 100644 --- a/packages/accordion/test/lion-accordion.test.js +++ b/packages/accordion/test/lion-accordion.test.js @@ -18,12 +18,33 @@ const basicAccordion = html` `; -function getAccordionChildren(/** @type {Element} */ el) { +/** + * @param {Element} el + */ +function getAccordionChildren(el) { const slot = el.shadowRoot?.querySelector('slot[name=accordion]'); return slot ? slot.children : []; } +/** + * @param {Element} el + */ +function getInvokers(el) { + const slot = el.shadowRoot?.querySelector('slot[name=accordion]'); + + return slot ? slot.querySelectorAll('[slot=invoker]') : []; +} + +/** + * @param {Element} el + */ +function getContents(el) { + const slot = el.shadowRoot?.querySelector('slot[name=accordion]'); + + return slot ? slot.querySelectorAll('[slot=content]') : []; +} + describe('', () => { describe('Accordion', () => { it('sets expanded to [] by default', async () => { @@ -60,7 +81,7 @@ describe('', () => { it('has [expanded] on current expanded invoker which serves as styling hook', async () => { const el = /** @type {LionAccordion} */ (await fixture(basicAccordion)); - const invokers = el.querySelectorAll('[slot=invoker]'); + const invokers = getInvokers(el); el.expanded = [0]; expect(invokers[0]).to.have.attribute('expanded'); expect(invokers[1]).to.not.have.attribute('expanded'); @@ -72,7 +93,7 @@ describe('', () => { it('has [expanded] on current expanded invoker first child which serves as styling hook', async () => { const el = /** @type {LionAccordion} */ (await fixture(basicAccordion)); - const invokers = el.querySelectorAll('[slot=invoker]'); + const invokers = getInvokers(el); el.expanded = [0]; expect(invokers[0].firstElementChild).to.have.attribute('expanded'); expect(invokers[1].firstElementChild).to.not.have.attribute('expanded'); @@ -140,7 +161,7 @@ describe('', () => { it('has [focused] on current focused invoker first child which serves as styling hook', async () => { const el = /** @type {LionAccordion} */ (await fixture(basicAccordion)); - const invokers = el.querySelectorAll('[slot=invoker]'); + const invokers = getInvokers(el); el.focusedIndex = 0; expect(invokers[0]).to.not.have.attribute('focused'); expect(invokers[1]).to.not.have.attribute('focused'); @@ -166,12 +187,15 @@ describe('', () => { describe('Accordion Contents (slot=content)', () => { it('are visible when corresponding invoker is expanded', async () => { const el = /** @type {LionAccordion} */ (await fixture(basicAccordion)); - const contents = el.querySelectorAll('[slot=content]'); el.expanded = [0]; + + const contents = getContents(el); + expect(contents[0]).to.be.visible; expect(contents[1]).to.be.not.visible; el.expanded = [1]; + expect(contents[0]).to.be.not.visible; expect(contents[1]).to.be.visible; }); @@ -190,21 +214,21 @@ describe('', () => { describe('User interaction', () => { it('opens a invoker on click', async () => { const el = /** @type {LionAccordion} */ (await fixture(basicAccordion)); - const invokers = el.querySelectorAll('[slot=invoker]'); + const invokers = getInvokers(el); invokers[1].firstElementChild?.dispatchEvent(new Event('click')); expect(el.expanded).to.deep.equal([1]); }); it('selects a invoker on click', async () => { const el = /** @type {LionAccordion} */ (await fixture(basicAccordion)); - const invokers = el.querySelectorAll('[slot=invoker]'); + const invokers = getInvokers(el); invokers[1].firstElementChild?.dispatchEvent(new Event('click')); expect(el.focusedIndex).to.equal(1); }); it.skip('opens/close invoker on [enter] and [space]', async () => { const el = /** @type {LionAccordion} */ (await fixture(basicAccordion)); - const invokers = el.querySelectorAll('[slot=invoker]'); + const invokers = getInvokers(el); invokers[0].firstElementChild?.dispatchEvent(new KeyboardEvent('keyup', { key: 'Enter' })); expect(el.expanded).to.deep.equal([0]); invokers[0].firstElementChild?.dispatchEvent(new KeyboardEvent('keyup', { key: ' ' })); @@ -213,7 +237,7 @@ describe('', () => { it('selects next invoker on [arrow-right] and [arrow-down]', async () => { const el = /** @type {LionAccordion} */ (await fixture(basicAccordion)); - const invokers = el.querySelectorAll('[slot=invoker]'); + const invokers = getInvokers(el); el.focusedIndex = 0; invokers[0].firstElementChild?.dispatchEvent( new KeyboardEvent('keydown', { key: 'ArrowRight' }), @@ -238,7 +262,7 @@ describe('', () => { `) ); - const invokers = el.querySelectorAll('[slot=invoker]'); + const invokers = getInvokers(el); el.focusedIndex = 2; invokers[2].firstElementChild?.dispatchEvent( new KeyboardEvent('keydown', { key: 'ArrowLeft' }), @@ -261,14 +285,14 @@ describe('', () => { `) ); - const invokers = el.querySelectorAll('[slot=invoker]'); + const invokers = getInvokers(el); invokers[1].firstElementChild?.dispatchEvent(new KeyboardEvent('keydown', { key: 'Home' })); expect(el.focusedIndex).to.equal(0); }); it('selects last invoker on [end]', async () => { const el = /** @type {LionAccordion} */ (await fixture(basicAccordion)); - const invokers = el.querySelectorAll('[slot=invoker]'); + const invokers = getInvokers(el); invokers[0].firstElementChild?.dispatchEvent(new KeyboardEvent('keydown', { key: 'End' })); expect(el.focusedIndex).to.equal(2); }); @@ -286,7 +310,7 @@ describe('', () => { `) ); - const invokers = el.querySelectorAll('[slot=invoker]'); + const invokers = getInvokers(el); invokers[2].firstElementChild?.dispatchEvent( new KeyboardEvent('keydown', { key: 'ArrowRight' }), ); @@ -306,7 +330,7 @@ describe('', () => { `) ); - const invokers = el.querySelectorAll('[slot=invoker]'); + const invokers = getInvokers(el); invokers[0].firstElementChild?.dispatchEvent( new KeyboardEvent('keydown', { key: 'ArrowLeft' }), ); @@ -331,6 +355,7 @@ describe('', () => { } el.expanded = [4]; await el.updateComplete; + expect( Array.from(getAccordionChildren(el)).find( child => child.slot === 'invoker' && child.hasAttribute('expanded'), @@ -400,8 +425,8 @@ describe('', () => {
content 2
`); - const invokers = el.querySelectorAll('[slot=invoker]'); - const contents = el.querySelectorAll('[slot=content]'); + const invokers = getInvokers(el); + const contents = getContents(el); expect(invokers[0].firstElementChild?.getAttribute('aria-controls')).to.equal( contents[0].id, ); @@ -450,8 +475,8 @@ describe('', () => {
content 2
`); - const contents = el.querySelectorAll('[slot=content]'); - const invokers = el.querySelectorAll('[slot=invoker]'); + const contents = getContents(el); + const invokers = getInvokers(el); expect(contents[0]).to.have.attribute('aria-labelledby', invokers[0].firstElementChild?.id); expect(contents[1]).to.have.attribute('aria-labelledby', invokers[1].firstElementChild?.id); });