import { aTimeout, expect, fixture, html, waitUntil } from '@open-wc/testing'; import { sendKeys, sendMouse } from '@web/test-runner-commands'; import sinon from 'sinon'; import type SlDropdown from './dropdown'; describe('', () => { it('should be visible with the open attribute', async () => { const el = await fixture(html` Toggle Item 1 Item 2 Item 3 `); const panel = el.shadowRoot!.querySelector('[part~="panel"]')!; expect(panel.hidden).to.be.false; }); it('should not be visible without the open attribute', async () => { const el = await fixture(html` Toggle Item 1 Item 2 Item 3 `); const panel = el.shadowRoot!.querySelector('[part~="panel"]')!; expect(panel.hidden).to.be.true; }); it('should emit sl-show and sl-after-show when calling show()', async () => { const el = await fixture(html` Toggle Item 1 Item 2 Item 3 `); const panel = el.shadowRoot!.querySelector('[part~="panel"]')!; const showHandler = sinon.spy(); const afterShowHandler = sinon.spy(); el.addEventListener('sl-show', showHandler); el.addEventListener('sl-after-show', afterShowHandler); el.show(); await waitUntil(() => showHandler.calledOnce); await waitUntil(() => afterShowHandler.calledOnce); expect(showHandler).to.have.been.calledOnce; expect(afterShowHandler).to.have.been.calledOnce; expect(panel.hidden).to.be.false; }); it('should emit sl-hide and sl-after-hide when calling hide()', async () => { const el = await fixture(html` Toggle Item 1 Item 2 Item 3 `); const panel = el.shadowRoot!.querySelector('[part~="panel"]')!; const hideHandler = sinon.spy(); const afterHideHandler = sinon.spy(); el.addEventListener('sl-hide', hideHandler); el.addEventListener('sl-after-hide', afterHideHandler); el.hide(); await waitUntil(() => hideHandler.calledOnce); await waitUntil(() => afterHideHandler.calledOnce); expect(hideHandler).to.have.been.calledOnce; expect(afterHideHandler).to.have.been.calledOnce; expect(panel.hidden).to.be.true; }); it('should emit sl-show and sl-after-show when setting open = true', async () => { const el = await fixture(html` Toggle Item 1 Item 2 Item 3 `); const panel = el.shadowRoot!.querySelector('[part~="panel"]')!; const showHandler = sinon.spy(); const afterShowHandler = sinon.spy(); el.addEventListener('sl-show', showHandler); el.addEventListener('sl-after-show', afterShowHandler); el.open = true; await waitUntil(() => showHandler.calledOnce); await waitUntil(() => afterShowHandler.calledOnce); expect(showHandler).to.have.been.calledOnce; expect(afterShowHandler).to.have.been.calledOnce; expect(panel.hidden).to.be.false; }); it('should emit sl-hide and sl-after-hide when setting open = false', async () => { const el = await fixture(html` Toggle Item 1 Item 2 Item 3 `); const panel = el.shadowRoot!.querySelector('[part~="panel"]')!; const hideHandler = sinon.spy(); const afterHideHandler = sinon.spy(); el.addEventListener('sl-hide', hideHandler); el.addEventListener('sl-after-hide', afterHideHandler); el.open = false; await waitUntil(() => hideHandler.calledOnce); await waitUntil(() => afterHideHandler.calledOnce); expect(hideHandler).to.have.been.calledOnce; expect(afterHideHandler).to.have.been.calledOnce; expect(panel.hidden).to.be.true; }); it('should still open on arrow navigation when no menu items', async () => { const el = await fixture(html` Toggle `); const trigger = el.querySelector('sl-button')!; trigger.focus(); await sendKeys({ press: 'ArrowDown' }); await el.updateComplete; expect(el.open).to.be.true; }); it('should open on arrow navigation', async () => { const el = await fixture(html` Toggle Item 1 Item 2 `); const trigger = el.querySelector('sl-button')!; trigger.focus(); await sendKeys({ press: 'ArrowDown' }); await el.updateComplete; expect(el.open).to.be.true; }); it('should navigate to first focusable item on arrow navigation', async () => { const el = await fixture(html` Toggle Top Label Item 1 `); const trigger = el.querySelector('sl-button')!; const item = el.querySelector('sl-menu-item')!; trigger.focus(); await trigger.updateComplete; await sendKeys({ press: 'ArrowDown' }); await el.updateComplete; await aTimeout(500); // sigh, Safari const itemFocused = document.activeElement === item; expect(itemFocused).to.be.true; }); it('should close on escape key', async () => { const el = await fixture(html` Toggle Item 1 Item 2 `); const trigger = el.querySelector('sl-button')!; trigger.focus(); await sendKeys({ press: 'Escape' }); await el.updateComplete; expect(el.open).to.be.false; }); it('should not open on arrow navigation when no menu exists', async () => { const el = await fixture(html` Toggle
Some custom content
`); const trigger = el.querySelector('sl-button')!; trigger.focus(); await sendKeys({ press: 'ArrowDown' }); await el.updateComplete; expect(el.open).to.be.false; }); it('should open on enter key', async () => { const el = await fixture(html` Toggle Item 1 `); const trigger = el.querySelector('sl-button')!; trigger.focus(); await el.updateComplete; await sendKeys({ press: 'Enter' }); await el.updateComplete; expect(el.open).to.be.true; }); it('should open on enter key when no menu exists', async () => { const el = await fixture(html` Toggle
Some custom content
`); const trigger = el.querySelector('sl-button')!; trigger.focus(); await el.updateComplete; await sendKeys({ press: 'Enter' }); await el.updateComplete; expect(el.open).to.be.true; }); it('should hide when clicked outside container and initially open', async () => { const el = await fixture(html` Toggle Item 1 `); await sendMouse({ type: 'click', position: [0, 0] }); await el.updateComplete; expect(el.open).to.be.false; }); it('should hide when clicked outside container', async () => { const el = await fixture(html` Toggle Item 1 `); const trigger = el.querySelector('sl-button')!; trigger.click(); await el.updateComplete; await sendMouse({ type: 'click', position: [0, 0] }); await el.updateComplete; expect(el.open).to.be.false; }); it('should close and stop propagating the keydown event when Escape is pressed and the dropdown is open ', async () => { const el = await fixture(html` Toggle Dropdown Item 1 Dropdown Item 2 Dropdown Item 3 `); const firstMenuItem = el.querySelector('sl-menu-item')!; const hideHandler = sinon.spy(); document.body.addEventListener('keydown', hideHandler); firstMenuItem.focus(); await sendKeys({ press: 'Escape' }); await el.updateComplete; expect(el.open).to.be.false; expect(hideHandler).to.not.have.been.called; }); });