Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring BorderControl's unit tests #54155

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
138 changes: 74 additions & 64 deletions packages/components/src/border-control/test/index.js
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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', {
Expand All @@ -67,38 +62,21 @@ 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' } );
};

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', () => {
Expand Down Expand Up @@ -154,9 +132,10 @@ describe( 'BorderControl', () => {
} );

it( 'should render color and style popover', async () => {
const user = userEvent.setup();
const props = createProps();
render( <BorderControl { ...props } /> );
await openPopover();
await openPopover( user );

const customColorPicker = getButton( /Custom color picker/ );
const colorSwatchButtons = screen.getAllByRole( 'option', {
Expand All @@ -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( <BorderControl { ...props } /> );
await openPopover();
await openPopover( user );

const headerLabel = screen.getByText( 'Border color' );
const closeButton = getButton( 'Close border color' );
Expand All @@ -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( <BorderControl { ...props } /> );
await openPopover();
await openPopover( user );

const styleLabel = screen.queryByText( 'Style' );
const solidButton = queryButton( 'Solid' );
Expand Down Expand Up @@ -315,6 +296,10 @@ describe( 'BorderControl', () => {
const { rerender } = render( <BorderControl { ...props } /> );

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, {
Expand All @@ -329,10 +314,11 @@ describe( 'BorderControl', () => {
} );

it( 'should update color selection', async () => {
const user = userEvent.setup();
const props = createProps();
render( <BorderControl { ...props } /> );
await openPopover();
selectColorOption( 'Color: Green' );
await openPopover( user );
await user.click( getColorOption( 'Green' ) );

expect( props.onChange ).toHaveBeenNthCalledWith( 1, {
...defaultBorder,
Expand All @@ -341,10 +327,11 @@ describe( 'BorderControl', () => {
} );

it( 'should clear color selection when toggling swatch off', async () => {
const user = userEvent.setup();
const props = createProps();
render( <BorderControl { ...props } /> );
await openPopover();
selectColorOption( 'Color: Blue' );
await openPopover( user );
await user.click( getColorOption( 'Blue' ) );

expect( props.onChange ).toHaveBeenNthCalledWith( 1, {
...defaultBorder,
Expand All @@ -353,10 +340,11 @@ describe( 'BorderControl', () => {
} );

it( 'should update style selection', async () => {
const user = userEvent.setup();
const props = createProps();
render( <BorderControl { ...props } /> );
await openPopover();
clickButton( 'Dashed' );
await openPopover( user );
await user.click( getButton( 'Dashed' ) );

expect( props.onChange ).toHaveBeenNthCalledWith( 1, {
...defaultBorder,
Expand All @@ -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( <BorderControl { ...props } /> );
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( <BorderControl { ...props } /> );
await openPopover();
clickButton( 'Reset to default' );
await openPopover( user );
await user.click( getButton( 'Reset to default' ) );

expect( props.onChange ).toHaveBeenNthCalledWith( 1, {
color: undefined,
Expand All @@ -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( <BorderControl { ...props } /> );
clearWidthInput();
await user.clear( getWidthInput() );
rerender( <BorderControl { ...props } /> );
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( <BorderControl { ...props } /> );
clearWidthInput();
await user.clear( getWidthInput() );
rerender( <BorderControl { ...props } /> );
await openPopover();
selectColorOption( 'Color: Blue' );
await openPopover( user );
await user.click( getColorOption( 'Blue' ) );

expect( props.onChange ).toHaveBeenNthCalledWith( 2, {
color: undefined,
Expand All @@ -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( <BorderControl { ...props } /> );
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,
Expand All @@ -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( <BorderControl { ...props } /> );
await openPopover();
selectColorOption( 'Color: Green' );
await openPopover( user );
await user.click( getColorOption( 'Green' ) );
rerender( <BorderControl { ...props } /> );
clickButton( 'Dotted' );
await user.click( getButton( 'Dotted' ) );
rerender( <BorderControl { ...props } /> );
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',
Expand All @@ -448,20 +452,23 @@ 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( <BorderControl { ...props } /> );
await openPopover();
selectColorOption( 'Color: Yellow' );
await openPopover( user );
await user.click( getColorOption( 'Yellow' ) );

expect( props.onChange ).toHaveBeenCalledWith( {
color: '#bd8600',
style: undefined,
width: undefined,
} );

setWidthInput( '0' );
await user.type( getWidthInput(), '0' );

rerender( <BorderControl { ...props } /> );
selectColorOption( 'Color: Green' );
await openPopover( user );
await user.click( getColorOption( 'Green' ) );

expect( props.onChange ).toHaveBeenCalledWith( {
color: '#00a32a',
Expand All @@ -471,23 +478,26 @@ 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( <BorderControl { ...props } /> );
await openPopover();
clickButton( 'Dashed' );
await openPopover( user );
await user.click( getButton( 'Dashed' ) );

expect( props.onChange ).toHaveBeenCalledWith( {
color: undefined,
style: 'dashed',
width: undefined,
} );

setWidthInput( '0' );
await user.type( getWidthInput(), '0' );

rerender( <BorderControl { ...props } /> );
clickButton( 'Dotted' );
await openPopover( user );
await user.click( getButton( 'Dotted' ) );

expect( props.onChange ).toHaveBeenCalledWith( {
color: undefined,
Expand Down