From 47e85384025448e8796f8c058be541b3a4755ec3 Mon Sep 17 00:00:00 2001 From: Sergey Ilinsky Date: Wed, 11 Oct 2023 17:10:19 +0200 Subject: [PATCH] feat(lion-tabs): introduced before-selected-changed cancelable event --- packages/ui/components/tabs/src/LionTabs.js | 10 ++++ .../ui/components/tabs/test/lion-tabs.test.js | 46 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/packages/ui/components/tabs/src/LionTabs.js b/packages/ui/components/tabs/src/LionTabs.js index d98ed9b378..42f40faa5c 100644 --- a/packages/ui/components/tabs/src/LionTabs.js +++ b/packages/ui/components/tabs/src/LionTabs.js @@ -364,6 +364,16 @@ export class LionTabs extends LitElement { if (value === -1) { return; } + + const beforeSelectedChangedEvent = new CustomEvent('before-selected-changed', { + cancelable: true, + detail: { selectedIndex: value }, + }); + this.dispatchEvent(beforeSelectedChangedEvent); + if (beforeSelectedChangedEvent.defaultPrevented) { + return; + } + const stale = this.__selectedIndex; this.__selectedIndex = value; this.__updateSelected(true); diff --git a/packages/ui/components/tabs/test/lion-tabs.test.js b/packages/ui/components/tabs/test/lion-tabs.test.js index d3f8b4979e..2f7a64c1ad 100644 --- a/packages/ui/components/tabs/test/lion-tabs.test.js +++ b/packages/ui/components/tabs/test/lion-tabs.test.js @@ -75,6 +75,14 @@ describe('', () => { expect(spy).to.have.been.calledOnce; }); + it('does not send event "before-selected-changed" when selectedIndex is set programmatically', async () => { + const el = /** @type {LionTabs} */ (await fixture(basicTabs)); + const spy = sinon.spy(); + el.addEventListener('before-selected-changed', spy); + el.selectedIndex = 1; + expect(spy).to.not.have.been.calledOnce; + }); + it('logs warning if unequal amount of tabs and panels', async () => { const stub = sinon.stub(console, 'warn'); await fixture(html` @@ -345,6 +353,44 @@ describe('', () => { tabs[2].dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowRight' })); expect(el.selectedIndex).to.equal(1); }); + + describe('when interacted with it sends "before-selected-changed" event', () => { + it('and sets new selectedIndex if event default action was not prevented', async () => { + const el = /** @type {LionTabs} */ (await fixture(basicTabs)); + const beforeSelectedChangedSpy = sinon.spy(); + const selectedChangedSpy = sinon.spy(); + + el.addEventListener('before-selected-changed', beforeSelectedChangedSpy); + el.addEventListener('selected-changed', selectedChangedSpy); + + const tabs = el.querySelectorAll('[slot=tab]'); + tabs[1].dispatchEvent(new Event('click')); + expect(selectedChangedSpy).to.have.been.calledOnce; + expect(beforeSelectedChangedSpy).to.have.been.calledWithMatch({ + cancelable: true, + detail: { selectedIndex: 1 }, + }); + expect(el.selectedIndex).to.equal(1); + }); + + it('and does not set new selectedIndex if event default action was prevented', async () => { + const el = /** @type {LionTabs} */ (await fixture(basicTabs)); + const beforeSelectedChangedSpy = sinon.spy(e => e.preventDefault()); + const selectedChangedSpy = sinon.spy(); + + el.addEventListener('before-selected-changed', beforeSelectedChangedSpy); + el.addEventListener('selected-changed', selectedChangedSpy); + + const tabs = el.querySelectorAll('[slot=tab]'); + tabs[1].dispatchEvent(new Event('click')); + expect(selectedChangedSpy).to.not.have.been.called; + expect(beforeSelectedChangedSpy).to.have.been.calledWithMatch({ + cancelable: true, + detail: { selectedIndex: 1 }, + }); + expect(el.selectedIndex).to.equal(0); + }); + }); }); describe('Content distribution', () => {