diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 53fed935584c17..362e2d26a3d7be 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -18,6 +18,7 @@ ### Internal - `Composite`: Convert to TypeScript ([#54028](https://github.com/WordPress/gutenberg/pull/54028)). +- `BorderControl`: Refactor unit tests to use `userEvent` ([#54155](https://github.com/WordPress/gutenberg/pull/54155)) ## 25.7.0 (2023-08-31) diff --git a/packages/components/src/border-control/test/index.js b/packages/components/src/border-control/test/index.js index 0652beefee0ff6..172eaa481ffec2 100644 --- a/packages/components/src/border-control/test/index.js +++ b/packages/components/src/border-control/test/index.js @@ -1,13 +1,8 @@ /** * External dependencies */ -import { - act, - fireEvent, - render, - screen, - waitFor, -} from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; /** * Internal dependencies @@ -47,9 +42,9 @@ function getWrappingPopoverElement( element ) { return element.closest( '.components-popover' ); } -const openPopover = async () => { +const openPopover = async ( user ) => { const toggleButton = screen.getByLabelText( toggleLabelRegex ); - fireEvent.click( toggleButton ); + await user.click( toggleButton ); // Wait for color picker popover to fully appear const pickerButton = screen.getByRole( 'button', { @@ -67,22 +62,14 @@ const getButton = ( name ) => { return screen.getByRole( 'button', { name } ); }; -const getColorOption = ( name ) => { - return screen.getByRole( 'option', { name } ); +const getColorOption = ( color ) => { + return screen.getByRole( 'option', { name: `Color: ${ color }` } ); }; const queryButton = ( name ) => { return screen.queryByRole( 'button', { name } ); }; -const clickButton = ( name ) => { - fireEvent.click( getButton( name ) ); -}; - -const selectColorOption = ( name ) => { - fireEvent.click( getColorOption( name ) ); -}; - const getSliderInput = () => { return screen.getByRole( 'slider', { name: 'Border width' } ); }; @@ -90,15 +77,6 @@ const getSliderInput = () => { const getWidthInput = () => { return screen.getByRole( 'spinbutton', { name: 'Border width' } ); }; -const setWidthInput = ( value ) => { - const widthInput = getWidthInput(); - act( () => { - widthInput.focus(); - } ); - fireEvent.change( widthInput, { target: { value } } ); -}; - -const clearWidthInput = () => setWidthInput( '' ); describe( 'BorderControl', () => { describe( 'basic rendering', () => { @@ -154,9 +132,10 @@ describe( 'BorderControl', () => { } ); it( 'should render color and style popover', async () => { + const user = userEvent.setup(); const props = createProps(); render( ); - await openPopover(); + await openPopover( user ); const customColorPicker = getButton( /Custom color picker/ ); const colorSwatchButtons = screen.getAllByRole( 'option', { @@ -178,9 +157,10 @@ describe( 'BorderControl', () => { } ); it( 'should render color and style popover header', async () => { + const user = userEvent.setup(); const props = createProps( { showDropdownHeader: true } ); render( ); - await openPopover(); + await openPopover( user ); const headerLabel = screen.getByText( 'Border color' ); const closeButton = getButton( 'Close border color' ); @@ -190,9 +170,10 @@ describe( 'BorderControl', () => { } ); it( 'should not render style options when opted out of', async () => { + const user = userEvent.setup(); const props = createProps( { enableStyle: false } ); render( ); - await openPopover(); + await openPopover( user ); const styleLabel = screen.queryByText( 'Style' ); const solidButton = queryButton( 'Solid' ); @@ -315,6 +296,10 @@ describe( 'BorderControl', () => { const { rerender } = render( ); const slider = getSliderInput(); + // As per [1], it is not currently possible to reasonably + // replicate this interaction using `userEvent`, so leaving + // `fireEvent` in place to cover it. + // [1]: https://github.com/testing-library/user-event/issues/871 fireEvent.change( slider, { target: { value: '5' } } ); expect( props.onChange ).toHaveBeenNthCalledWith( 1, { @@ -329,10 +314,11 @@ describe( 'BorderControl', () => { } ); it( 'should update color selection', async () => { + const user = userEvent.setup(); const props = createProps(); render( ); - await openPopover(); - selectColorOption( 'Color: Green' ); + await openPopover( user ); + await user.click( getColorOption( 'Green' ) ); expect( props.onChange ).toHaveBeenNthCalledWith( 1, { ...defaultBorder, @@ -341,10 +327,11 @@ describe( 'BorderControl', () => { } ); it( 'should clear color selection when toggling swatch off', async () => { + const user = userEvent.setup(); const props = createProps(); render( ); - await openPopover(); - selectColorOption( 'Color: Blue' ); + await openPopover( user ); + await user.click( getColorOption( 'Blue' ) ); expect( props.onChange ).toHaveBeenNthCalledWith( 1, { ...defaultBorder, @@ -353,10 +340,11 @@ describe( 'BorderControl', () => { } ); it( 'should update style selection', async () => { + const user = userEvent.setup(); const props = createProps(); render( ); - await openPopover(); - clickButton( 'Dashed' ); + await openPopover( user ); + await user.click( getButton( 'Dashed' ) ); expect( props.onChange ).toHaveBeenNthCalledWith( 1, { ...defaultBorder, @@ -365,19 +353,21 @@ describe( 'BorderControl', () => { } ); it( 'should take no action when color and style popover is closed', async () => { + const user = userEvent.setup(); const props = createProps( { showDropdownHeader: true } ); render( ); - await openPopover(); - clickButton( 'Close border color' ); + await openPopover( user ); + await user.click( getButton( 'Close border color' ) ); expect( props.onChange ).not.toHaveBeenCalled(); } ); it( 'should reset color and style only when popover reset button clicked', async () => { + const user = userEvent.setup(); const props = createProps(); render( ); - await openPopover(); - clickButton( 'Reset to default' ); + await openPopover( user ); + await user.click( getButton( 'Reset to default' ) ); expect( props.onChange ).toHaveBeenNthCalledWith( 1, { color: undefined, @@ -387,25 +377,27 @@ describe( 'BorderControl', () => { } ); it( 'should sanitize border when width and color are undefined', async () => { + const user = userEvent.setup(); const props = createProps(); const { rerender } = render( ); - clearWidthInput(); + await user.clear( getWidthInput() ); rerender( ); - await openPopover(); - selectColorOption( 'Color: Blue' ); + await openPopover( user ); + await user.click( getColorOption( 'Blue' ) ); expect( props.onChange ).toHaveBeenCalledWith( undefined ); } ); it( 'should not sanitize border when requested', async () => { + const user = userEvent.setup(); const props = createProps( { shouldSanitizeBorder: false, } ); const { rerender } = render( ); - clearWidthInput(); + await user.clear( getWidthInput() ); rerender( ); - await openPopover(); - selectColorOption( 'Color: Blue' ); + await openPopover( user ); + await user.click( getColorOption( 'Blue' ) ); expect( props.onChange ).toHaveBeenNthCalledWith( 2, { color: undefined, @@ -415,12 +407,16 @@ describe( 'BorderControl', () => { } ); it( 'should clear color and set style to `none` when setting zero width', async () => { + const user = userEvent.setup(); const props = createProps(); render( ); - await openPopover(); - selectColorOption( 'Color: Green' ); - clickButton( 'Dotted' ); - setWidthInput( '0' ); + await openPopover( user ); + await user.click( getColorOption( 'Green' ) ); + await user.click( getButton( 'Dotted' ) ); + await user.type( getWidthInput(), '0', { + initialSelectionStart: 0, + initialSelectionEnd: 1, + } ); expect( props.onChange ).toHaveBeenNthCalledWith( 3, { color: undefined, @@ -430,15 +426,23 @@ describe( 'BorderControl', () => { } ); it( 'should reselect color and style selections when changing to non-zero width', async () => { + const user = userEvent.setup(); const props = createProps(); const { rerender } = render( ); - await openPopover(); - selectColorOption( 'Color: Green' ); + await openPopover( user ); + await user.click( getColorOption( 'Green' ) ); rerender( ); - clickButton( 'Dotted' ); + await user.click( getButton( 'Dotted' ) ); rerender( ); - setWidthInput( '0' ); - setWidthInput( '5' ); + const widthInput = getWidthInput(); + await user.type( widthInput, '0', { + initialSelectionStart: 0, + initialSelectionEnd: 1, + } ); + await user.type( widthInput, '5', { + initialSelectionStart: 0, + initialSelectionEnd: 1, + } ); expect( props.onChange ).toHaveBeenNthCalledWith( 4, { color: '#00a32a', @@ -448,10 +452,11 @@ describe( 'BorderControl', () => { } ); it( 'should set a non-zero width when applying color to zero width border', async () => { + const user = userEvent.setup(); const props = createProps( { value: undefined } ); const { rerender } = render( ); - await openPopover(); - selectColorOption( 'Color: Yellow' ); + await openPopover( user ); + await user.click( getColorOption( 'Yellow' ) ); expect( props.onChange ).toHaveBeenCalledWith( { color: '#bd8600', @@ -459,9 +464,11 @@ describe( 'BorderControl', () => { width: undefined, } ); - setWidthInput( '0' ); + await user.type( getWidthInput(), '0' ); + rerender( ); - selectColorOption( 'Color: Green' ); + await openPopover( user ); + await user.click( getColorOption( 'Green' ) ); expect( props.onChange ).toHaveBeenCalledWith( { color: '#00a32a', @@ -471,13 +478,14 @@ describe( 'BorderControl', () => { } ); it( 'should set a non-zero width when applying style to zero width border', async () => { + const user = userEvent.setup(); const props = createProps( { value: undefined, shouldSanitizeBorder: false, } ); const { rerender } = render( ); - await openPopover(); - clickButton( 'Dashed' ); + await openPopover( user ); + await user.click( getButton( 'Dashed' ) ); expect( props.onChange ).toHaveBeenCalledWith( { color: undefined, @@ -485,9 +493,11 @@ describe( 'BorderControl', () => { width: undefined, } ); - setWidthInput( '0' ); + await user.type( getWidthInput(), '0' ); + rerender( ); - clickButton( 'Dotted' ); + await openPopover( user ); + await user.click( getButton( 'Dotted' ) ); expect( props.onChange ).toHaveBeenCalledWith( { color: undefined,