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:
Thomas Roberts 2022-05-18 18:32:42 +01:00 committed by GitHub
parent 22e6394d47
commit b1f4e35c00
4 changed files with 67 additions and 1 deletions

View File

@ -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 );
}
}
}
} }

View File

@ -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' );
} );
} );

View File

@ -56,6 +56,7 @@ export const CountryInput = ( {
errorMessage={ errorMessage }
required={ required }
autoComplete={ autoComplete }
requireExactMatch={ true }
/>
{ autoComplete !== 'off' && (
<input

View File

@ -105,6 +105,7 @@ const StateInput = ( {
) }
required={ required }
autoComplete={ autoComplete }
requireExactMatch={ true }
/>
{ autoComplete !== 'off' && (
<input