From 2747745891ea68e01b034de8baf3cd0df3a0823b Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 25 Sep 2020 16:09:40 +0200 Subject: [PATCH] ensure that you can not click disabled items --- .../src/components/menu/menu.test.tsx | 68 +++++++++++++++++-- .../@headlessui-react/src/utils/render.ts | 39 ++++++++++- .../src/components/menu/menu.test.tsx | 8 ++- 3 files changed, 108 insertions(+), 7 deletions(-) diff --git a/packages/@headlessui-react/src/components/menu/menu.test.tsx b/packages/@headlessui-react/src/components/menu/menu.test.tsx index 9733e95..11bdf3d 100644 --- a/packages/@headlessui-react/src/components/menu/menu.test.tsx +++ b/packages/@headlessui-react/src/components/menu/menu.test.tsx @@ -643,7 +643,9 @@ describe('Keyboard interactions', () => { Item B - Item C + + + ) @@ -673,6 +675,18 @@ describe('Keyboard interactions', () => { // Verify the button got "clicked" expect(clickHandler).toHaveBeenCalledTimes(1) + + // Click the menu button again + await click(getMenuButton()) + + // Active the last menu item + await hover(getMenuItems()[2]) + + // Close menu, and invoke the item + await press(Keys.Enter) + + // Verify the button got "clicked" + expect(clickHandler).toHaveBeenCalledTimes(2) }) ) @@ -2467,6 +2481,48 @@ describe('Mouse interactions', () => { }) ) + it( + 'should be possible to click a menu item, which closes the menu and invokes the @click handler', + suppressConsoleLogs(async () => { + const clickHandler = jest.fn() + render( + + Trigger + + alice + + bob + + + + + + + ) + + // Open menu + await click(getMenuButton()) + assertMenu(getMenu(), { state: MenuState.Open }) + + // We should be able to click the first item + await click(getMenuItems()[1]) + assertMenu(getMenu(), { state: MenuState.Closed }) + + // Verify the callback has been called + expect(clickHandler).toHaveBeenCalledTimes(1) + + // Let's re-open the window for now + await click(getMenuButton()) + + // Click the last item, which should close and invoke the handler + await click(getMenuItems()[2]) + assertMenu(getMenu(), { state: MenuState.Closed }) + + // Verify the callback has been called + expect(clickHandler).toHaveBeenCalledTimes(2) + }) + ) + it( 'should be possible to click a disabled menu item, which is a no-op', suppressConsoleLogs(async () => { @@ -2567,8 +2623,8 @@ describe('Mouse interactions', () => { bob - - charlie + + @@ -2581,9 +2637,11 @@ describe('Mouse interactions', () => { const items = getMenuItems() await focus(items[0]) - await focus(items[1]) - await press(Keys.Enter) + await click(items[1]) + expect(clickHandler).not.toHaveBeenCalled() + // Activate the last item + await click(getMenuItems()[2]) expect(clickHandler).not.toHaveBeenCalled() }) ) diff --git a/packages/@headlessui-react/src/utils/render.ts b/packages/@headlessui-react/src/utils/render.ts index 60cf47f..342ab44 100644 --- a/packages/@headlessui-react/src/utils/render.ts +++ b/packages/@headlessui-react/src/utils/render.ts @@ -32,7 +32,7 @@ export function render( resolvedChildren, // Filter out undefined values so that they don't override the existing values - compact(passThroughProps) + mergeEventFunctions(compact(passThroughProps), resolvedChildren.props, ['onClick']) ) } } @@ -40,6 +40,43 @@ export function render( return React.createElement(Component, passThroughProps, resolvedChildren) } +/** + * We can use this function for the following useCase: + * + * + `, @@ -2542,7 +2544,11 @@ describe('Mouse interactions', () => { await focus(items[0]) await focus(items[1]) await press(Keys.Enter) + expect(clickHandler).not.toHaveBeenCalled() + // Activate the last item + await focus(items[2]) + await press(Keys.Enter) expect(clickHandler).not.toHaveBeenCalled() }) })