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

Block Editor: Improve ImageSizeControl tests #46765

Merged
merged 6 commits into from
Dec 23, 2022
Merged
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
226 changes: 147 additions & 79 deletions packages/block-editor/src/components/image-size-control/test/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/**
* External dependencies
*/
import { render, screen, fireEvent } from '@testing-library/react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

/**
* Internal dependencies
Expand All @@ -11,8 +12,6 @@ import ImageSizeControl from '../index';
describe( 'ImageSizeControl', () => {
const mockOnChange = jest.fn();
const mockOnChangeImage = jest.fn();
const getHeightInput = () => screen.getByLabelText( 'Height' );
const getWidthInput = () => screen.getByLabelText( 'Width' );

afterEach( () => {
// Cleanup on exiting.
Expand All @@ -31,8 +30,12 @@ describe( 'ImageSizeControl', () => {
/>
);

expect( getHeightInput().value ).toBe( '300' );
expect( getWidthInput().value ).toBe( '400' );
expect(
screen.getByRole( 'spinbutton', { name: 'Height' } )
).toHaveValue( 300 );
expect(
screen.getByRole( 'spinbutton', { name: 'Width' } )
).toHaveValue( 400 );
} );

it( 'returns default dimensions when custom dimensions are undefined', () => {
Expand All @@ -44,15 +47,23 @@ describe( 'ImageSizeControl', () => {
/>
);

expect( getHeightInput().value ).toBe( '100' );
expect( getWidthInput().value ).toBe( '200' );
expect(
screen.getByRole( 'spinbutton', { name: 'Height' } )
).toHaveValue( 100 );
expect(
screen.getByRole( 'spinbutton', { name: 'Width' } )
).toHaveValue( 200 );
} );

it( 'returns empty string when custom and default dimensions are undefined', () => {
it( 'returns no value when custom and default dimensions are undefined', () => {
render( <ImageSizeControl onChange={ mockOnChange } /> );

expect( getHeightInput().value ).toBe( '' );
expect( getWidthInput().value ).toBe( '' );
expect(
screen.getByRole( 'spinbutton', { name: 'Height' } )
).toHaveValue( null );
expect(
screen.getByRole( 'spinbutton', { name: 'Width' } )
).toHaveValue( null );
} );

it( 'returns default dimensions when initially undefined defaults are defined on rerender', () => {
Expand All @@ -62,12 +73,14 @@ describe( 'ImageSizeControl', () => {
<ImageSizeControl onChange={ mockOnChange } />
);

const heightInput = getHeightInput();
const widthInput = getWidthInput();
const heightInput = screen.getByRole( 'spinbutton', {
name: 'Height',
} );
const widthInput = screen.getByRole( 'spinbutton', { name: 'Width' } );

// The dimensions are initially set to an empty string.
expect( heightInput.value ).toBe( '' );
expect( widthInput.value ).toBe( '' );
expect( heightInput ).toHaveValue( null );
expect( widthInput ).toHaveValue( null );

// When new default dimensions are passed on a rerender (for example after they
// are calculated following an image upload), update values to the new defaults.
Expand All @@ -80,48 +93,66 @@ describe( 'ImageSizeControl', () => {
);

// The dimensions should update to the defaults.
expect( heightInput.value ).toBe( '300' );
expect( widthInput.value ).toBe( '400' );
expect( heightInput ).toHaveValue( 300 );
expect( widthInput ).toHaveValue( 400 );
} );

describe( 'updating dimension inputs', () => {
it( 'updates height and calls onChange', () => {
it( 'updates height and calls onChange', async () => {
const user = userEvent.setup();
render( <ImageSizeControl onChange={ mockOnChange } /> );

const heightInput = getHeightInput();
const widthInput = getWidthInput();
const heightInput = screen.getByRole( 'spinbutton', {
name: 'Height',
} );
const widthInput = screen.getByRole( 'spinbutton', {
name: 'Width',
} );

expect( heightInput.value ).toBe( '' );
expect( widthInput.value ).toBe( '' );
expect( heightInput ).toHaveValue( null );
expect( widthInput ).toHaveValue( null );

fireEvent.change( heightInput, { target: { value: '500' } } );
const newHeight = '500';

expect( mockOnChange ).toHaveBeenCalledTimes( 1 );
expect( mockOnChange ).toHaveBeenCalledWith( { height: 500 } );
await user.clear( heightInput );
await user.type( heightInput, newHeight );

expect( heightInput.value ).toBe( '500' );
expect( widthInput.value ).toBe( '' );
expect( mockOnChange ).toHaveBeenCalledTimes( newHeight.length );
expect( mockOnChange ).toHaveBeenLastCalledWith( { height: 500 } );

expect( heightInput ).toHaveValue( 500 );
expect( widthInput ).toHaveValue( null );
} );

it( 'updates width and calls onChange', () => {
it( 'updates width and calls onChange', async () => {
const user = userEvent.setup();

render( <ImageSizeControl onChange={ mockOnChange } /> );

const heightInput = getHeightInput();
const widthInput = getWidthInput();
const heightInput = screen.getByRole( 'spinbutton', {
name: 'Height',
} );
const widthInput = screen.getByRole( 'spinbutton', {
name: 'Width',
} );

expect( heightInput.value ).toBe( '' );
expect( widthInput.value ).toBe( '' );
expect( heightInput ).toHaveValue( null );
expect( widthInput ).toHaveValue( null );

fireEvent.change( widthInput, { target: { value: '500' } } );
const newWidth = '500';
await user.clear( widthInput );
await user.type( widthInput, newWidth );

expect( mockOnChange ).toHaveBeenCalledTimes( 1 );
expect( mockOnChange ).toHaveBeenCalledWith( { width: 500 } );
expect( mockOnChange ).toHaveBeenCalledTimes( newWidth.length );
expect( mockOnChange ).toHaveBeenLastCalledWith( { width: 500 } );

expect( heightInput.value ).toBe( '' );
expect( widthInput.value ).toBe( '500' );
expect( heightInput ).toHaveValue( null );
expect( widthInput ).toHaveValue( 500 );
} );

it( 'updates height and calls onChange for empty value', () => {
it( 'updates height and calls onChange for empty value', async () => {
const user = userEvent.setup();

render(
<ImageSizeControl
imageHeight="100"
Expand All @@ -130,27 +161,33 @@ describe( 'ImageSizeControl', () => {
/>
);

const heightInput = getHeightInput();
const widthInput = getWidthInput();
const heightInput = screen.getByRole( 'spinbutton', {
name: 'Height',
} );
const widthInput = screen.getByRole( 'spinbutton', {
name: 'Width',
} );

expect( heightInput.value ).toBe( '100' );
expect( widthInput.value ).toBe( '100' );
expect( heightInput ).toHaveValue( 100 );
expect( widthInput ).toHaveValue( 100 );

fireEvent.change( heightInput, { target: { value: '' } } );
await user.clear( heightInput );

// onChange is called and sets the dimension to undefined rather than
// the empty string.
expect( mockOnChange ).toHaveBeenCalledTimes( 1 );
expect( mockOnChange ).toHaveBeenCalledWith( {
expect( mockOnChange ).toHaveBeenLastCalledWith( {
height: undefined,
} );

// Height is updated to empty value and does not reset to default.
expect( heightInput.value ).toBe( '' );
expect( widthInput.value ).toBe( '100' );
expect( heightInput ).toHaveValue( null );
expect( widthInput ).toHaveValue( 100 );
} );

it( 'updates width and calls onChange for empty value', () => {
it( 'updates width and calls onChange for empty value', async () => {
const user = userEvent.setup();

render(
<ImageSizeControl
imageHeight="100"
Expand All @@ -159,29 +196,35 @@ describe( 'ImageSizeControl', () => {
/>
);

const heightInput = getHeightInput();
const widthInput = getWidthInput();
const heightInput = screen.getByRole( 'spinbutton', {
name: 'Height',
} );
const widthInput = screen.getByRole( 'spinbutton', {
name: 'Width',
} );

expect( heightInput.value ).toBe( '100' );
expect( widthInput.value ).toBe( '100' );
expect( heightInput ).toHaveValue( 100 );
expect( widthInput ).toHaveValue( 100 );

fireEvent.change( widthInput, { target: { value: '' } } );
await user.clear( widthInput );

// onChange is called and sets the dimension to undefined rather than
// the empty string.
expect( mockOnChange ).toHaveBeenCalledTimes( 1 );
expect( mockOnChange ).toHaveBeenCalledWith( {
expect( mockOnChange ).toHaveBeenLastCalledWith( {
width: undefined,
} );

// Width is updated to empty value and does not reset to default.
expect( heightInput.value ).toBe( '100' );
expect( widthInput.value ).toBe( '' );
expect( heightInput ).toHaveValue( 100 );
expect( widthInput ).toHaveValue( null );
} );
} );

describe( 'reset button', () => {
it( 'resets both height and width to default values', () => {
it( 'resets both height and width to default values', async () => {
const user = userEvent.setup();

render(
<ImageSizeControl
imageHeight="100"
Expand All @@ -192,29 +235,35 @@ describe( 'ImageSizeControl', () => {
/>
);

const heightInput = getHeightInput();
const widthInput = getWidthInput();
const heightInput = screen.getByRole( 'spinbutton', {
name: 'Height',
} );
const widthInput = screen.getByRole( 'spinbutton', {
name: 'Width',
} );

// The initial dimension values display first.
expect( heightInput.value ).toBe( '300' );
expect( widthInput.value ).toBe( '400' );
expect( heightInput ).toHaveValue( 300 );
expect( widthInput ).toHaveValue( 400 );

fireEvent.click( screen.getByText( 'Reset' ) );
await user.click( screen.getByRole( 'button', { name: 'Reset' } ) );

// Both attributes are set to undefined to clear custom values.
expect( mockOnChange ).toHaveBeenCalledWith( {
expect( mockOnChange ).toHaveBeenLastCalledWith( {
height: undefined,
width: undefined,
} );

// The inputs display the default values once more.
expect( heightInput.value ).toBe( '100' );
expect( widthInput.value ).toBe( '200' );
expect( heightInput ).toHaveValue( 100 );
expect( widthInput ).toHaveValue( 200 );
} );
} );

describe( 'image size percentage presets', () => {
it( 'updates height and width attributes on selection', () => {
it( 'updates height and width attributes on selection', async () => {
const user = userEvent.setup();

render(
<ImageSizeControl
imageHeight="100"
Expand All @@ -223,18 +272,25 @@ describe( 'ImageSizeControl', () => {
/>
);

fireEvent.click( screen.getByText( '50%' ) );
const button = screen.getByRole( 'button', {
name: '50%',
pressed: false,
} );

await user.click( button );

expect( screen.getByText( '50%' ) ).toHaveClass( 'is-pressed' );
expect( button ).toHaveClass( 'is-pressed' );

// Both attributes are set to the rounded scaled value.
expect( mockOnChange ).toHaveBeenCalledWith( {
expect( mockOnChange ).toHaveBeenLastCalledWith( {
height: 50,
width: 101,
} );
} );

it( 'updates height and width inputs on selection', () => {
it( 'updates height and width inputs on selection', async () => {
const user = userEvent.setup();

render(
<ImageSizeControl
imageHeight="100"
Expand All @@ -243,11 +299,20 @@ describe( 'ImageSizeControl', () => {
/>
);

fireEvent.click( screen.getByText( '50%' ) );
const button = screen.getByRole( 'button', {
name: '50%',
pressed: false,
} );

await user.click( button );

// Both attributes are set to the rounded scaled value.
expect( getHeightInput().value ).toBe( '50' );
expect( getWidthInput().value ).toBe( '101' );
expect(
screen.getByRole( 'spinbutton', { name: 'Height' } )
).toHaveValue( 50 );
expect(
screen.getByRole( 'spinbutton', { name: 'Width' } )
).toHaveValue( 101 );
} );
} );

Expand All @@ -268,12 +333,14 @@ describe( 'ImageSizeControl', () => {
/>
);

expect( screen.getByLabelText( 'Image size' ).value ).toBe(
'medium'
);
expect(
screen.getByRole( 'combobox', { name: 'Image size' } )
).toHaveValue( 'medium' );
} );

it( 'calls onChangeImage with selected slug on selection', () => {
it( 'calls onChangeImage with selected slug on selection', async () => {
const user = userEvent.setup();

render(
<ImageSizeControl
imageSizeOptions={ IMAGE_SIZE_OPTIONS }
Expand All @@ -283,12 +350,13 @@ describe( 'ImageSizeControl', () => {
/>
);

fireEvent.change( screen.getByLabelText( 'Image size' ), {
target: { value: 'thumbnail' },
} );
await user.selectOptions(
screen.getByRole( 'combobox', { name: 'Image size' } ),
'thumbnail'
);

// onChangeImage is called with the slug and the event.
expect( mockOnChangeImage ).toHaveBeenCalledWith(
expect( mockOnChangeImage ).toHaveBeenLastCalledWith(
'thumbnail',
expect.any( Object )
);
Expand Down