From 58bea9ce079ca01cc67d9e55767d28dd21558082 Mon Sep 17 00:00:00 2001 From: 43081j <43081j@users.noreply.github.com> Date: Sun, 10 Sep 2023 18:28:32 +0100 Subject: [PATCH] fix(select): close select on menu close There are some situations where the menu can close when the outer select is still open and unaware. For example, clicking the field will open the menu, then clicking it again will close the menu **but not the select**. This is because the menu observes outside clicks in order to close itself. We don't currently observe those closes to update our own state inside `md-select`, so the UI still shows as if it is open but without a menu. The fix here is to always reflect the state of the menu on `closed`. --- select/harness.ts | 15 +++++++++++++++ select/select_test.ts | 31 ++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/select/harness.ts b/select/harness.ts index 88637fe18..cbaa28bd8 100644 --- a/select/harness.ts +++ b/select/harness.ts @@ -20,6 +20,9 @@ export class SelectHarness extends Harness { field.click(); } + async clickAndWaitForMenu() { + const menu = this.getMenu(); + const menuOpen = menu.open === true; + const waitForMenu = new Promise((resolve) => { + menu.addEventListener(menuOpen ? 'closed' : 'opened', () => { + resolve(); + }, {once: true}); + }); + await this.click(); + await waitForMenu; + } + async clickOption(index: number) { const menu = this.element.renderRoot.querySelector('md-menu')!; if (!menu.open) { diff --git a/select/select_test.ts b/select/select_test.ts index 89f870679..7b7d2f87b 100644 --- a/select/select_test.ts +++ b/select/select_test.ts @@ -47,7 +47,9 @@ describe('', () => { const selectEl = root.querySelector('md-outlined-select')!; await selectEl.updateComplete; - await new SelectHarness(selectEl).clickOption(1); + const harness = new SelectHarness(selectEl); + await harness.clickAndWaitForMenu(); + await harness.clickOption(1); expect(changed).toBeTrue(); }); @@ -177,6 +179,33 @@ describe('', () => { ], }); }); + + it('closes select when field re-clicked', async () => { + render( + html` + + + + `, + root); + const selectEl = root.querySelector('md-outlined-select')!; + await selectEl.updateComplete; + + const spanEl = selectEl.shadowRoot!.querySelector( + 'span.select' + )!; + const menuEl = selectEl.shadowRoot!.querySelector('md-menu')!; + + const harness = new SelectHarness(selectEl); + await harness.clickAndWaitForMenu(); + expect(spanEl.classList.contains('open')).toBeTrue(); + expect(menuEl.open).toBeTrue(); + + await harness.clickAndWaitForMenu(); + + expect(menuEl.open).toBeFalse(); + expect(spanEl.classList.contains('open')).toBeFalse(); + }); }); describe('', () => {