Combobox: fix check for existing options when creating a custom value (#100123)

This commit is contained in:
Laura Fernández 2025-02-11 14:13:42 +01:00 committed by GitHub
parent 5118e82e8c
commit 43d7d00247
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 18 additions and 4 deletions

View File

@ -243,7 +243,19 @@ describe('Combobox', () => {
await userEvent.keyboard('{Enter}');
expect(screen.getByDisplayValue('Use custom value')).toBeInTheDocument();
expect(onChangeHandler).toHaveBeenCalledWith(expect.objectContaining({ value: 'Use custom value' }));
expect(onChangeHandler).toHaveBeenCalledWith(expect.objectContaining({ description: 'Use custom value' }));
});
it('should not allow creating a custom value when it is an existing value', async () => {
const onChangeHandler = jest.fn();
render(<Combobox options={options} value={null} onChange={onChangeHandler} createCustomValue />);
const input = screen.getByRole('combobox');
await userEvent.type(input, '4');
await userEvent.keyboard('{Enter}');
expect(screen.queryByDisplayValue('Use custom value')).not.toBeInTheDocument();
expect(screen.getByDisplayValue('Option 4')).toBeInTheDocument();
expect(onChangeHandler).toHaveBeenCalledWith(expect.objectContaining({ value: '4' }));
expect(onChangeHandler).not.toHaveBeenCalledWith(expect.objectContaining({ description: 'Use custom value' }));
});
it('should provide custom string when all options are numbers', async () => {

View File

@ -129,9 +129,9 @@ export const Combobox = <T extends string | number>(props: ComboboxProps<T>) =>
let itemsToSet = items;
logOptions(itemsToSet.length, RECOMMENDED_ITEMS_AMOUNT, id, ariaLabelledBy);
if (inputValue && createCustomValue) {
const optionMatchingInput = items.find(
(opt) => opt.label === 'Custom value: ' + inputValue || opt.value === inputValue
);
//Since the label of a normal option does not have to match its value and a custom option has the same value and label,
//we just focus on the value to check if the option already exists
const optionMatchingInput = items.find((opt) => opt.value === inputValue);
if (!optionMatchingInput) {
const customValueOption = {

View File

@ -62,6 +62,8 @@ export function useOptions<T extends string | number>(rawOptions: AsyncOptions<T
(opts: Array<ComboboxOption<T>>) => {
let currentOptions: Array<ComboboxOption<T>> = opts;
if (createCustomValue && userTypedSearch) {
//Since the label of a normal option does not have to match its value and a custom option has the same value and label,
//we just focus on the value to check if the option already exists
const customValueExists = opts.some((opt) => opt.value === userTypedSearch);
if (!customValueExists) {
currentOptions = [