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,