From d81fdb9cb72b2ce583fb88c77c7dd58c24acc375 Mon Sep 17 00:00:00 2001 From: mariohamann Date: Tue, 12 May 2026 14:39:10 +0200 Subject: [PATCH] test: add regression test for dropdown open/close behavior in nested shadow roots --- .changeset/chilly-birds-write.md | 2 + .../src/components/dropdown/dropdown.test.ts | 41 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 .changeset/chilly-birds-write.md diff --git a/.changeset/chilly-birds-write.md b/.changeset/chilly-birds-write.md new file mode 100644 index 0000000000..a845151cc8 --- /dev/null +++ b/.changeset/chilly-birds-write.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/packages/components/src/components/dropdown/dropdown.test.ts b/packages/components/src/components/dropdown/dropdown.test.ts index 8b924edac9..1e81a11fc8 100644 --- a/packages/components/src/components/dropdown/dropdown.test.ts +++ b/packages/components/src/components/dropdown/dropdown.test.ts @@ -461,4 +461,45 @@ describe('', () => { // expect(el.open).to.be.false; // expect(hideHandler).to.not.have.been.called; // }); + + it('should open and close correctly when nested in a double shadow root (regression #648)', async () => { + // Declarative shadow DOM isn't processed by innerHTML/lit-html, so attach shadow roots imperatively + const outerHost = await fixture(html`
`); + const outerShadow = outerHost.attachShadow({ mode: 'open' }); + + const innerHost = document.createElement('div'); + outerShadow.appendChild(innerHost); + const innerShadow = innerHost.attachShadow({ mode: 'open' }); + + innerShadow.innerHTML = ` + + Toggle + + Item 1 + Item 2 + Item 3 + + + `; + + const el = innerShadow.querySelector('sd-dropdown')!; + await el.updateComplete; + const panel = el.shadowRoot!.querySelector('[part~="panel"]')!; + + // Wait for the component to fully settle after innerHTML upgrade + await waitUntil(() => panel.hidden); + + const afterShowHandler = sinon.spy(); + const afterHideHandler = sinon.spy(); + el.addEventListener('sd-after-show', afterShowHandler); + el.addEventListener('sd-after-hide', afterHideHandler); + + el.show(); + await waitUntil(() => afterShowHandler.calledOnce); + expect(panel.hidden).to.be.false; + + el.hide(); + await waitUntil(() => afterHideHandler.calledOnce); + expect(panel.hidden).to.be.true; + }); });