fix: fixed test for appending content

This commit is contained in:
Danny Moerkerke 2022-08-09 13:51:24 +02:00
parent d597892a87
commit 8a74e33625
2 changed files with 59 additions and 26 deletions

View file

@ -175,12 +175,20 @@ export class LionAccordion extends LitElement {
* @private * @private
*/ */
__setupStore() { __setupStore() {
const invokers = /** @type {HTMLElement[]} */ ( const accordion = this.shadowRoot?.querySelector('slot[name=accordion]');
Array.from(this.querySelectorAll('[slot="invoker"]')) const existingInvokers = accordion ? accordion.querySelectorAll('[slot=invoker]') : [];
); const existingContent = accordion ? accordion.querySelectorAll('[slot=content]') : [];
const contents = /** @type {HTMLElement[]} */ (
Array.from(this.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) { if (invokers.length !== contents.length) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.warn( console.warn(
@ -202,11 +210,12 @@ export class LionAccordion extends LitElement {
}; };
this._setupContent(entry); this._setupContent(entry);
this._setupInvoker(entry); this._setupInvoker(entry);
this.__rearrangeInvokersAndContent();
this._unfocusInvoker(entry); this._unfocusInvoker(entry);
this._collapse(entry); this._collapse(entry);
this.__store.push(entry); this.__store.push(entry);
}); });
this.__rearrangeInvokersAndContent();
} }
/** /**
@ -220,7 +229,6 @@ export class LionAccordion extends LitElement {
Array.from(this.querySelectorAll('[slot="content"]')) Array.from(this.querySelectorAll('[slot="content"]'))
); );
const accordion = this.shadowRoot?.querySelector('slot[name=accordion]'); const accordion = this.shadowRoot?.querySelector('slot[name=accordion]');
if (accordion) { if (accordion) {
invokers.forEach((invoker, index) => { invokers.forEach((invoker, index) => {
accordion.insertAdjacentElement('beforeend', invoker); accordion.insertAdjacentElement('beforeend', invoker);

View file

@ -18,12 +18,33 @@ const basicAccordion = html`
</lion-accordion> </lion-accordion>
`; `;
function getAccordionChildren(/** @type {Element} */ el) { /**
* @param {Element} el
*/
function getAccordionChildren(el) {
const slot = el.shadowRoot?.querySelector('slot[name=accordion]'); const slot = el.shadowRoot?.querySelector('slot[name=accordion]');
return slot ? slot.children : []; 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('<lion-accordion>', () => { describe('<lion-accordion>', () => {
describe('Accordion', () => { describe('Accordion', () => {
it('sets expanded to [] by default', async () => { it('sets expanded to [] by default', async () => {
@ -60,7 +81,7 @@ describe('<lion-accordion>', () => {
it('has [expanded] on current expanded invoker which serves as styling hook', async () => { it('has [expanded] on current expanded invoker which serves as styling hook', async () => {
const el = /** @type {LionAccordion} */ (await fixture(basicAccordion)); const el = /** @type {LionAccordion} */ (await fixture(basicAccordion));
const invokers = el.querySelectorAll('[slot=invoker]'); const invokers = getInvokers(el);
el.expanded = [0]; el.expanded = [0];
expect(invokers[0]).to.have.attribute('expanded'); expect(invokers[0]).to.have.attribute('expanded');
expect(invokers[1]).to.not.have.attribute('expanded'); expect(invokers[1]).to.not.have.attribute('expanded');
@ -72,7 +93,7 @@ describe('<lion-accordion>', () => {
it('has [expanded] on current expanded invoker first child which serves as styling hook', async () => { it('has [expanded] on current expanded invoker first child which serves as styling hook', async () => {
const el = /** @type {LionAccordion} */ (await fixture(basicAccordion)); const el = /** @type {LionAccordion} */ (await fixture(basicAccordion));
const invokers = el.querySelectorAll('[slot=invoker]'); const invokers = getInvokers(el);
el.expanded = [0]; el.expanded = [0];
expect(invokers[0].firstElementChild).to.have.attribute('expanded'); expect(invokers[0].firstElementChild).to.have.attribute('expanded');
expect(invokers[1].firstElementChild).to.not.have.attribute('expanded'); expect(invokers[1].firstElementChild).to.not.have.attribute('expanded');
@ -140,7 +161,7 @@ describe('<lion-accordion>', () => {
it('has [focused] on current focused invoker first child which serves as styling hook', async () => { it('has [focused] on current focused invoker first child which serves as styling hook', async () => {
const el = /** @type {LionAccordion} */ (await fixture(basicAccordion)); const el = /** @type {LionAccordion} */ (await fixture(basicAccordion));
const invokers = el.querySelectorAll('[slot=invoker]'); const invokers = getInvokers(el);
el.focusedIndex = 0; el.focusedIndex = 0;
expect(invokers[0]).to.not.have.attribute('focused'); expect(invokers[0]).to.not.have.attribute('focused');
expect(invokers[1]).to.not.have.attribute('focused'); expect(invokers[1]).to.not.have.attribute('focused');
@ -166,12 +187,15 @@ describe('<lion-accordion>', () => {
describe('Accordion Contents (slot=content)', () => { describe('Accordion Contents (slot=content)', () => {
it('are visible when corresponding invoker is expanded', async () => { it('are visible when corresponding invoker is expanded', async () => {
const el = /** @type {LionAccordion} */ (await fixture(basicAccordion)); const el = /** @type {LionAccordion} */ (await fixture(basicAccordion));
const contents = el.querySelectorAll('[slot=content]');
el.expanded = [0]; el.expanded = [0];
const contents = getContents(el);
expect(contents[0]).to.be.visible; expect(contents[0]).to.be.visible;
expect(contents[1]).to.be.not.visible; expect(contents[1]).to.be.not.visible;
el.expanded = [1]; el.expanded = [1];
expect(contents[0]).to.be.not.visible; expect(contents[0]).to.be.not.visible;
expect(contents[1]).to.be.visible; expect(contents[1]).to.be.visible;
}); });
@ -190,21 +214,21 @@ describe('<lion-accordion>', () => {
describe('User interaction', () => { describe('User interaction', () => {
it('opens a invoker on click', async () => { it('opens a invoker on click', async () => {
const el = /** @type {LionAccordion} */ (await fixture(basicAccordion)); const el = /** @type {LionAccordion} */ (await fixture(basicAccordion));
const invokers = el.querySelectorAll('[slot=invoker]'); const invokers = getInvokers(el);
invokers[1].firstElementChild?.dispatchEvent(new Event('click')); invokers[1].firstElementChild?.dispatchEvent(new Event('click'));
expect(el.expanded).to.deep.equal([1]); expect(el.expanded).to.deep.equal([1]);
}); });
it('selects a invoker on click', async () => { it('selects a invoker on click', async () => {
const el = /** @type {LionAccordion} */ (await fixture(basicAccordion)); const el = /** @type {LionAccordion} */ (await fixture(basicAccordion));
const invokers = el.querySelectorAll('[slot=invoker]'); const invokers = getInvokers(el);
invokers[1].firstElementChild?.dispatchEvent(new Event('click')); invokers[1].firstElementChild?.dispatchEvent(new Event('click'));
expect(el.focusedIndex).to.equal(1); expect(el.focusedIndex).to.equal(1);
}); });
it.skip('opens/close invoker on [enter] and [space]', async () => { it.skip('opens/close invoker on [enter] and [space]', async () => {
const el = /** @type {LionAccordion} */ (await fixture(basicAccordion)); 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' })); invokers[0].firstElementChild?.dispatchEvent(new KeyboardEvent('keyup', { key: 'Enter' }));
expect(el.expanded).to.deep.equal([0]); expect(el.expanded).to.deep.equal([0]);
invokers[0].firstElementChild?.dispatchEvent(new KeyboardEvent('keyup', { key: ' ' })); invokers[0].firstElementChild?.dispatchEvent(new KeyboardEvent('keyup', { key: ' ' }));
@ -213,7 +237,7 @@ describe('<lion-accordion>', () => {
it('selects next invoker on [arrow-right] and [arrow-down]', async () => { it('selects next invoker on [arrow-right] and [arrow-down]', async () => {
const el = /** @type {LionAccordion} */ (await fixture(basicAccordion)); const el = /** @type {LionAccordion} */ (await fixture(basicAccordion));
const invokers = el.querySelectorAll('[slot=invoker]'); const invokers = getInvokers(el);
el.focusedIndex = 0; el.focusedIndex = 0;
invokers[0].firstElementChild?.dispatchEvent( invokers[0].firstElementChild?.dispatchEvent(
new KeyboardEvent('keydown', { key: 'ArrowRight' }), new KeyboardEvent('keydown', { key: 'ArrowRight' }),
@ -238,7 +262,7 @@ describe('<lion-accordion>', () => {
</lion-accordion> </lion-accordion>
`) `)
); );
const invokers = el.querySelectorAll('[slot=invoker]'); const invokers = getInvokers(el);
el.focusedIndex = 2; el.focusedIndex = 2;
invokers[2].firstElementChild?.dispatchEvent( invokers[2].firstElementChild?.dispatchEvent(
new KeyboardEvent('keydown', { key: 'ArrowLeft' }), new KeyboardEvent('keydown', { key: 'ArrowLeft' }),
@ -261,14 +285,14 @@ describe('<lion-accordion>', () => {
</lion-accordion> </lion-accordion>
`) `)
); );
const invokers = el.querySelectorAll('[slot=invoker]'); const invokers = getInvokers(el);
invokers[1].firstElementChild?.dispatchEvent(new KeyboardEvent('keydown', { key: 'Home' })); invokers[1].firstElementChild?.dispatchEvent(new KeyboardEvent('keydown', { key: 'Home' }));
expect(el.focusedIndex).to.equal(0); expect(el.focusedIndex).to.equal(0);
}); });
it('selects last invoker on [end]', async () => { it('selects last invoker on [end]', async () => {
const el = /** @type {LionAccordion} */ (await fixture(basicAccordion)); 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' })); invokers[0].firstElementChild?.dispatchEvent(new KeyboardEvent('keydown', { key: 'End' }));
expect(el.focusedIndex).to.equal(2); expect(el.focusedIndex).to.equal(2);
}); });
@ -286,7 +310,7 @@ describe('<lion-accordion>', () => {
</lion-accordion> </lion-accordion>
`) `)
); );
const invokers = el.querySelectorAll('[slot=invoker]'); const invokers = getInvokers(el);
invokers[2].firstElementChild?.dispatchEvent( invokers[2].firstElementChild?.dispatchEvent(
new KeyboardEvent('keydown', { key: 'ArrowRight' }), new KeyboardEvent('keydown', { key: 'ArrowRight' }),
); );
@ -306,7 +330,7 @@ describe('<lion-accordion>', () => {
</lion-accordion> </lion-accordion>
`) `)
); );
const invokers = el.querySelectorAll('[slot=invoker]'); const invokers = getInvokers(el);
invokers[0].firstElementChild?.dispatchEvent( invokers[0].firstElementChild?.dispatchEvent(
new KeyboardEvent('keydown', { key: 'ArrowLeft' }), new KeyboardEvent('keydown', { key: 'ArrowLeft' }),
); );
@ -331,6 +355,7 @@ describe('<lion-accordion>', () => {
} }
el.expanded = [4]; el.expanded = [4];
await el.updateComplete; await el.updateComplete;
expect( expect(
Array.from(getAccordionChildren(el)).find( Array.from(getAccordionChildren(el)).find(
child => child.slot === 'invoker' && child.hasAttribute('expanded'), child => child.slot === 'invoker' && child.hasAttribute('expanded'),
@ -400,8 +425,8 @@ describe('<lion-accordion>', () => {
<div id="p2" slot="content">content 2</div> <div id="p2" slot="content">content 2</div>
</lion-accordion> </lion-accordion>
`); `);
const invokers = el.querySelectorAll('[slot=invoker]'); const invokers = getInvokers(el);
const contents = el.querySelectorAll('[slot=content]'); const contents = getContents(el);
expect(invokers[0].firstElementChild?.getAttribute('aria-controls')).to.equal( expect(invokers[0].firstElementChild?.getAttribute('aria-controls')).to.equal(
contents[0].id, contents[0].id,
); );
@ -450,8 +475,8 @@ describe('<lion-accordion>', () => {
<div slot="content">content 2</div> <div slot="content">content 2</div>
</lion-accordion> </lion-accordion>
`); `);
const contents = el.querySelectorAll('[slot=content]'); const contents = getContents(el);
const invokers = el.querySelectorAll('[slot=invoker]'); const invokers = getInvokers(el);
expect(contents[0]).to.have.attribute('aria-labelledby', invokers[0].firstElementChild?.id); expect(contents[0]).to.have.attribute('aria-labelledby', invokers[0].firstElementChild?.id);
expect(contents[1]).to.have.attribute('aria-labelledby', invokers[1].firstElementChild?.id); expect(contents[1]).to.have.attribute('aria-labelledby', invokers[1].firstElementChild?.id);
}); });