Skip to content

Commit

Permalink
UnitControl: Revamp support for changing unit by typing (#39303)
Browse files Browse the repository at this point in the history
* Use a simpler way to allow changing units from the text input

* Change default of `isPressEnterToChange` in `BoxControl`

* Update tests

* Avoid potential undefined

* Remove extraneous null typing

Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com>

* Make key matching regex case-insensitive

Co-authored-by: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>

* Revert removed condtional type="text" on `UnitControl`

* Forward __unstableStateReducer through `UnitControl`

* Avoid intefering with paste or other shortcuts

* Revert `BoxControl` changes

* Update unit tests for `BoxControl`

* Optimize and guard creation of regex

Reduce starting from the second unit and cover null safety

* Revise style

* Make test of unit switching convenience run for each css unit

* Add changelog entry

* Remove custom `onChange` callback on Storybook, as it interferes with the actions tab

* Improve tests by avoiding local `state` variables and using onChange spies instead

* Clarify comments about js-dom not updating select inputs when using the keyboard

* Update README

---------

Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com>
Co-authored-by: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
  • Loading branch information
3 people authored Jun 21, 2023
1 parent 6278cbf commit 82d99b9
Show file tree
Hide file tree
Showing 6 changed files with 229 additions and 392 deletions.
1 change: 1 addition & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Enhancements

- `UnitControl`: Revamp support for changing unit by typing ([#39303](https://github.com/WordPress/gutenberg/pull/39303)).
- `Modal`: Update corner radius to be between buttons and the site view frame, in a 2-4-8 system. ([#51254](https://github.com/WordPress/gutenberg/pull/51254)).
- `ItemGroup`: Update button focus state styles to be inline with other button focus states in the editor. ([#51576](https://github.com/WordPress/gutenberg/pull/51576)).

Expand Down
88 changes: 28 additions & 60 deletions packages/components/src/box-control/test/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,10 @@ describe( 'BoxControl', () => {
name: 'Box Control',
} );

await user.type( input, '100%' );
await user.type( input, '100' );
await user.keyboard( '{Enter}' );

expect( input ).toHaveValue( '100' );
expect(
screen.getByRole( 'combobox', {
name: 'Select unit',
} )
).toHaveValue( '%' );
} );
} );

Expand All @@ -67,20 +62,15 @@ describe( 'BoxControl', () => {
const input = screen.getByRole( 'textbox', {
name: 'Box Control',
} );
const select = screen.getByRole( 'combobox', {
name: 'Select unit',
} );

await user.type( input, '100px' );
await user.type( input, '100' );
await user.keyboard( '{Enter}' );

expect( input ).toHaveValue( '100' );
expect( select ).toHaveValue( 'px' );

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

expect( input ).toHaveValue( '' );
expect( select ).toHaveValue( 'px' );
} );

it( 'should reset values when clicking Reset, if controlled', async () => {
Expand All @@ -91,20 +81,15 @@ describe( 'BoxControl', () => {
const input = screen.getByRole( 'textbox', {
name: 'Box Control',
} );
const select = screen.getByRole( 'combobox', {
name: 'Select unit',
} );

await user.type( input, '100px' );
await user.type( input, '100' );
await user.keyboard( '{Enter}' );

expect( input ).toHaveValue( '100' );
expect( select ).toHaveValue( 'px' );

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

expect( input ).toHaveValue( '' );
expect( select ).toHaveValue( 'px' );
} );

it( 'should reset values when clicking Reset, if controlled <-> uncontrolled state changes', async () => {
Expand All @@ -115,20 +100,15 @@ describe( 'BoxControl', () => {
const input = screen.getByRole( 'textbox', {
name: 'Box Control',
} );
const select = screen.getByRole( 'combobox', {
name: 'Select unit',
} );

await user.type( input, '100px' );
await user.type( input, '100' );
await user.keyboard( '{Enter}' );

expect( input ).toHaveValue( '100' );
expect( select ).toHaveValue( 'px' );

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

expect( input ).toHaveValue( '' );
expect( select ).toHaveValue( 'px' );
} );

it( 'should persist cleared value when focus changes', async () => {
Expand All @@ -141,15 +121,10 @@ describe( 'BoxControl', () => {
name: 'Box Control',
} );

await user.type( input, '100%' );
await user.type( input, '100' );
await user.keyboard( '{Enter}' );

expect( input ).toHaveValue( '100' );
expect(
screen.getByRole( 'combobox', {
name: 'Select unit',
} )
).toHaveValue( '%' );

await user.clear( input );
expect( input ).toHaveValue( '' );
Expand Down Expand Up @@ -178,9 +153,8 @@ describe( 'BoxControl', () => {

await user.type(
screen.getByRole( 'textbox', { name: 'Top' } ),
'100px'
'100'
);
await user.keyboard( '{Enter}' );

expect(
screen.getByRole( 'textbox', { name: 'Top' } )
Expand All @@ -194,12 +168,6 @@ describe( 'BoxControl', () => {
expect(
screen.getByRole( 'textbox', { name: 'Left' } )
).not.toHaveValue();

screen
.getAllByRole( 'combobox', { name: 'Select unit' } )
.forEach( ( combobox ) => {
expect( combobox ).toHaveValue( 'px' );
} );
} );

it( 'should update a whole axis when value is changed when unlinked', async () => {
Expand All @@ -215,22 +183,15 @@ describe( 'BoxControl', () => {
screen.getByRole( 'textbox', {
name: 'Vertical',
} ),
'100px'
'100'
);
await user.keyboard( '{Enter}' );

expect(
screen.getByRole( 'textbox', { name: 'Vertical' } )
).toHaveValue( '100' );
expect(
screen.getByRole( 'textbox', { name: 'Horizontal' } )
).not.toHaveValue();

screen
.getAllByRole( 'combobox', { name: 'Select unit' } )
.forEach( ( combobox ) => {
expect( combobox ).toHaveValue( 'px' );
} );
} );
} );

Expand Down Expand Up @@ -321,23 +282,30 @@ describe( 'BoxControl', () => {
describe( 'onChange updates', () => {
it( 'should call onChange when values contain more than just CSS units', async () => {
const user = userEvent.setup();
const setState = jest.fn();
const onChangeSpy = jest.fn();

render( <BoxControl onChange={ setState } /> );
render( <BoxControl onChange={ onChangeSpy } /> );

await user.type(
screen.getByRole( 'textbox', {
name: 'Box Control',
} ),
'7.5rem'
);
await user.keyboard( '{Enter}' );
const valueInput = screen.getByRole( 'textbox', {
name: 'Box Control',
} );
const unitSelect = screen.getByRole( 'combobox', {
name: 'Select unit',
} );

expect( setState ).toHaveBeenCalledWith( {
top: '7.5rem',
right: '7.5rem',
bottom: '7.5rem',
left: '7.5rem',
// Typing the first letter of a unit blurs the input and focuses the combobox.
await user.type( valueInput, '7r' );

expect( unitSelect ).toHaveFocus();

// The correct expected behavior would be for the values to have "rem"
// as their unit, but the test environment doesn't seem to change
// values on `select` elements when using the keyboard.
expect( onChangeSpy ).toHaveBeenLastCalledWith( {
top: '7px',
right: '7px',
bottom: '7px',
left: '7px',
} );
} );

Expand Down
Loading

0 comments on commit 82d99b9

Please sign in to comment.