Skip to content

Commit

Permalink
Use event.target.validity.valid in docs, storybook and unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ciampo committed Mar 9, 2022
1 parent ee4336a commit d91e6a4
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 7 deletions.
14 changes: 14 additions & 0 deletions packages/components/src/number-control/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,20 @@ The minimum `value` allowed.
- Required: No
- Default: `-Infinity`

### onChange

Callback fired whenever the value of the input changes.

The callback receives two arguments:

1. `newValue`: the new value of the input
2. `extra`: an object containing, under the `event` key, the original browser event.

Note that the value received as the first argument of the callback is _not_ guaranteed to be a valid value (e.g. it could be outside of the range defined by the [`min`, `max`] props). In order to check the value's validity, check the `event.target.validity.valid` property from the callback's second argument.

- Type: `(newValue, extra) => void`
- Required: No

### required

If `true` enforces a valid number within the control's min/max range. If `false` allows an empty string as a valid value.
Expand Down
21 changes: 14 additions & 7 deletions packages/components/src/number-control/stories/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default {

function Example() {
const [ value, setValue ] = useState( '0' );
const [ isValidValue, setIsValidValue ] = useState( true );

const props = {
disabled: boolean( 'disabled', false ),
Expand All @@ -32,18 +33,24 @@ function Example() {
label: text( 'label', 'Number' ),
min: number( 'min', 0 ),
max: number( 'max', 100 ),
placeholder: text( 'placeholder', 0 ),
placeholder: text( 'placeholder', '0' ),
required: boolean( 'required', false ),
shiftStep: number( 'shiftStep', 10 ),
step: text( 'step', 1 ),
step: text( 'step', '1' ),
};

return (
<NumberControl
{ ...props }
value={ value }
onChange={ ( v ) => setValue( v ) }
/>
<>
<NumberControl
{ ...props }
value={ value }
onChange={ ( v, extra ) => {
setValue( v );
setIsValidValue( extra.event.target.validity.valid );
} }
/>
<p>Is valid? { isValidValue ? 'Yes' : 'No' }</p>
</>
);
}

Expand Down
31 changes: 31 additions & 0 deletions packages/components/src/number-control/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,37 @@ describe( 'NumberControl', () => {
expect( spy ).toHaveBeenNthCalledWith( 2, 4 );
} );
} );

it( 'should call onChange callback when value is not valid', () => {
const spy = jest.fn();
render(
<NumberControl
value={ 5 }
min={ 1 }
max={ 10 }
onChange={ ( v, extra ) =>
spy( v, extra.event.target.validity.valid )
}
/>
);

const input = getInput();
input.focus();
fireEvent.change( input, { target: { value: 14 } } );

expect( input.value ).toBe( '14' );

fireKeyDown( { keyCode: ENTER } );

expect( input.value ).toBe( '10' );

expect( spy ).toHaveBeenCalledTimes( 2 );

// First call: invalid, unclamped value
expect( spy ).toHaveBeenNthCalledWith( 1, '14', false );
// Second call: valid, clamped value
expect( spy ).toHaveBeenNthCalledWith( 2, 10, true );
} );
} );

describe( 'Validation', () => {
Expand Down

0 comments on commit d91e6a4

Please sign in to comment.