diff --git a/src/components/selectable/selectable_templates/__snapshots__/selectable_template_sitewide.test.tsx.snap b/src/components/selectable/selectable_templates/__snapshots__/selectable_template_sitewide.test.tsx.snap index fe816f28dfd..290e89d5692 100644 --- a/src/components/selectable/selectable_templates/__snapshots__/selectable_template_sitewide.test.tsx.snap +++ b/src/components/selectable/selectable_templates/__snapshots__/selectable_template_sitewide.test.tsx.snap @@ -51,56 +51,6 @@ exports[`EuiSelectableTemplateSitewide is rendered 1`] = ` `; -exports[`EuiSelectableTemplateSitewide props popoverButton is not rendered with popoverButtonBreakpoints xs 1`] = ` -
-
-
-
-
- - -
- -
-
-

- - Use the Up and Down arrow keys to move focus over options. Press Enter to select. Press Escape to collapse options. -

-
-
-`; - exports[`EuiSelectableTemplateSitewide props popoverButton is rendered 1`] = `
- -
- -`; - -exports[`EuiSelectableTemplateSitewide props popoverButton is rendered with popoverButtonBreakpoints m 1`] = ` -
-
- + + +
`; diff --git a/src/components/selectable/selectable_templates/selectable_template_sitewide.test.tsx b/src/components/selectable/selectable_templates/selectable_template_sitewide.test.tsx index a5a6be21213..075e143f4f2 100644 --- a/src/components/selectable/selectable_templates/selectable_template_sitewide.test.tsx +++ b/src/components/selectable/selectable_templates/selectable_template_sitewide.test.tsx @@ -7,9 +7,11 @@ */ import React from 'react'; +import { fireEvent } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { render, waitForEuiPopoverOpen } from '../../../test/rtl'; import { shouldRenderCustomStyles } from '../../../test/internal'; import { requiredProps } from '../../../test/required_props'; -import { render } from '../../../test/rtl'; import { EuiSelectableTemplateSitewide } from './selectable_template_sitewide'; import { EuiSelectableTemplateSitewideOption } from './selectable_template_sitewide_option'; @@ -127,11 +129,15 @@ describe('EuiSelectableTemplateSitewide', () => { beforeAll(() => (window.innerWidth = 670)); afterAll(() => 1024); // reset to jsdom's default + const button = ( + + ); + test('is rendered', () => { const { container } = render( Button} + popoverButton={button} /> ); @@ -139,27 +145,57 @@ describe('EuiSelectableTemplateSitewide', () => { }); test('is rendered with popoverButtonBreakpoints m', () => { - const { container } = render( + const { getByTestSubject } = render( Button} + popoverButton={button} popoverButtonBreakpoints={['xs', 's', 'm']} /> ); - expect(container.firstChild).toMatchSnapshot(); + expect(getByTestSubject('mobilePopoverButton')).toBeInTheDocument(); }); test('is not rendered with popoverButtonBreakpoints xs', () => { - const { container } = render( + const { queryByTestSubject } = render( Button} + popoverButton={button} popoverButtonBreakpoints={['xs']} /> ); - expect(container.firstChild).toMatchSnapshot(); + expect( + queryByTestSubject('mobilePopoverButton') + ).not.toBeInTheDocument(); + }); + + test('toggles the selectable popover for keyboard users', () => { + const { getByTestSubject } = render( + {button}} + /> + ); + // fireEvent doesn't seem to work: https://github.com/testing-library/user-event/issues/179#issuecomment-1125146667 + getByTestSubject('mobilePopoverButton').focus(); + userEvent.keyboard('{enter}'); + waitForEuiPopoverOpen(); + + expect(getByTestSubject('euiSelectableList')).toBeInTheDocument(); + }); + + test('toggles the selectable popover even when a wrapper exists around the button', () => { + const { getByTestSubject } = render( + {button}} + /> + ); + fireEvent.click(getByTestSubject('mobilePopoverButton')); + waitForEuiPopoverOpen(); + + expect(getByTestSubject('euiSelectableList')).toBeInTheDocument(); }); }); }); diff --git a/src/components/selectable/selectable_templates/selectable_template_sitewide.tsx b/src/components/selectable/selectable_templates/selectable_template_sitewide.tsx index 64b0e0293fb..eaabd225c02 100644 --- a/src/components/selectable/selectable_templates/selectable_template_sitewide.tsx +++ b/src/components/selectable/selectable_templates/selectable_template_sitewide.tsx @@ -11,6 +11,7 @@ import React, { ReactNode, useState, useMemo, + useCallback, CSSProperties, ReactElement, } from 'react'; @@ -106,9 +107,9 @@ export const EuiSelectableTemplateSitewide: FunctionComponent< _closePopover && _closePopover(); }; - const togglePopover = () => { - setPopoverIsOpen(!popoverIsOpen); - }; + const togglePopover = useCallback(() => { + setPopoverIsOpen((isOpen) => !isOpen); + }, []); // Width applied to the internal div const popoverWidth: CSSProperties['width'] = width || 600; @@ -195,17 +196,18 @@ export const EuiSelectableTemplateSitewide: FunctionComponent< return popoverButtonBreakpoints.includes(currentBreakpoint); }, [currentBreakpoint, popoverButtonBreakpoints]); - let popoverTrigger: ReactElement; - if (popoverButton && canShowPopoverButton) { - popoverTrigger = React.cloneElement(popoverButton, { - ...popoverButton.props, - onClick: togglePopover, - onKeyDown: (e: KeyboardEvent) => { - // Selectable preventsDefault on Enter which kills browser controls for pressing the button - e.stopPropagation(); - }, - }); - } + const popoverTrigger = useMemo(() => { + if (!popoverButton || !canShowPopoverButton) return; + return ( + e.stopPropagation()} + > + {popoverButton} + + ); + }, [popoverButton, canShowPopoverButton, togglePopover]); return (