Add `requireExactMatch` prop to `ComboBox` to prevent wrong country/state values being sent to the server (https://github.com/woocommerce/woocommerce-blocks/pull/6426)
* Add requireExactMatch prop to ComboBox & only run onChange if value matches * Set requireExactMatch to true for Country and State inputs * Add unit tests for ComboBox * Update expected value for onChange call * Re-add autocomplete option to country input * Use correct case for autoComplete in country input
This commit is contained in:
parent
22e6394d47
commit
b1f4e35c00
|
@ -34,6 +34,7 @@ export interface ComboboxProps {
|
|||
options: ComboboxControlOption[];
|
||||
required?: boolean;
|
||||
value: string;
|
||||
requireExactMatch?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -54,6 +55,7 @@ const Combobox = ( {
|
|||
errorId: incomingErrorId,
|
||||
instanceId = '0',
|
||||
autoComplete = 'off',
|
||||
requireExactMatch = false,
|
||||
}: ComboboxProps ): JSX.Element => {
|
||||
const {
|
||||
getValidationError,
|
||||
|
@ -136,7 +138,13 @@ const Combobox = ( {
|
|||
normalizedFilterValue
|
||||
);
|
||||
if ( foundOption ) {
|
||||
onChange( foundOption.value );
|
||||
if ( ! requireExactMatch ) {
|
||||
onChange( foundOption.value );
|
||||
return;
|
||||
}
|
||||
if ( foundOption.label === filterValue ) {
|
||||
onChange( foundOption.value );
|
||||
}
|
||||
}
|
||||
}
|
||||
} }
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import Combobox from '@woocommerce/base-components/combobox';
|
||||
|
||||
describe( 'ComboBox', () => {
|
||||
const options = [
|
||||
{ value: 'A', label: 'A value A' },
|
||||
{ value: 'B', label: 'B value B' },
|
||||
{ value: 'C', label: 'C value C' },
|
||||
{ value: 'D', label: 'D value D' },
|
||||
{ value: 'E', label: 'E value E' },
|
||||
{ value: 'F', label: 'F value F' },
|
||||
];
|
||||
|
||||
beforeEach( () => {
|
||||
jest.resetAllMocks();
|
||||
} );
|
||||
|
||||
it( 'calls onChange as soon as a value is changed if requireExactMatch is false or undefined', async () => {
|
||||
const onChange = jest.fn();
|
||||
const label = 'combo-box';
|
||||
render(
|
||||
<Combobox
|
||||
options={ options }
|
||||
value=""
|
||||
onChange={ onChange }
|
||||
label={ label }
|
||||
/>
|
||||
);
|
||||
const input = await screen.findByLabelText( label );
|
||||
await userEvent.type( input, 'A ' );
|
||||
expect( onChange ).toHaveBeenCalledWith( 'A' );
|
||||
} );
|
||||
|
||||
it( 'calls onChange only when the value is equal to one of the options when requireExactMatch is true', async () => {
|
||||
const onChange = jest.fn();
|
||||
const label = 'combo-box';
|
||||
render(
|
||||
<Combobox
|
||||
options={ options }
|
||||
value=""
|
||||
onChange={ onChange }
|
||||
label={ label }
|
||||
requireExactMatch={ true }
|
||||
/>
|
||||
);
|
||||
const input = await screen.findByLabelText( label );
|
||||
await userEvent.type( input, 'A ' );
|
||||
expect( onChange ).not.toHaveBeenCalled();
|
||||
await userEvent.type( input, 'value A' );
|
||||
expect( onChange ).toHaveBeenCalledWith( 'A' );
|
||||
} );
|
||||
} );
|
|
@ -56,6 +56,7 @@ export const CountryInput = ( {
|
|||
errorMessage={ errorMessage }
|
||||
required={ required }
|
||||
autoComplete={ autoComplete }
|
||||
requireExactMatch={ true }
|
||||
/>
|
||||
{ autoComplete !== 'off' && (
|
||||
<input
|
||||
|
|
|
@ -105,6 +105,7 @@ const StateInput = ( {
|
|||
) }
|
||||
required={ required }
|
||||
autoComplete={ autoComplete }
|
||||
requireExactMatch={ true }
|
||||
/>
|
||||
{ autoComplete !== 'off' && (
|
||||
<input
|
||||
|
|
Loading…
Reference in New Issue