Я попытался создать собственный компонент React с множественным выбором.
interface Props {
name?: string;
placeholder?: string;
options?: Array<string>;
defaultOptions?: Array<string>;
className?: string;
disabled?: boolean;
onChange?: (event: React.ChangeEvent<HTMLSelectElement>) => void;
ref?: Ref<HTMLSelectElement>;
}
const MultiSelect: FC<Props> = forwardRef((props, ref) => {
const { name, className, placeholder, options, defaultOptions, disabled, onChange, ...otherProps } = props;
const [selectedOptions, setSelectedOptions] = useState(defaultOptions || []);
const toggle = useCallback(
(event: React.ChangeEvent<HTMLSelectElement>) => {
const selectedOptionsCollection = event.target.selectedOptions;
let selectedValues: string[] = [];
for (let i = 0; i < selectedOptionsCollection.length; i++) {
const selectedOptionValue = selectedOptionsCollection.item(i)?.value;
if (selectedOptionValue && selectedOptionValue !== '') {
selectedValues = [...selectedValues, selectedOptionValue];
}
console.log(`selected:${selectedValues}`);
}
setSelectedOptions(selectedValues);
if (onChange) {
onChange(event);
}
},
[selectedOptions, onChange],
);
return (
<select
multiple
role='select'
name={name}
className={classNames(styles.select, className)}
disabled={disabled}
onChange={toggle}
value={selectedOptions}
{...otherProps}
>
<option value=''>{placeholder}</option>
{
options?.map((opt) => (
<option
key={opt}
value={opt}
>
{opt}
</option>
))
}
</select>
);
});
export default MultiSelect;
В приведенных выше кодах я использовал console.log
для печати выбранных опций, но при написании для них теста.
it('handles changes in multi select box', () => {
const handleChange = jest.fn();
const { container, getByRole } = render(
<MultiSelect
options={['one', 'two', 'three']}
defaultOptions={['one']}
onChange={handleChange}
/>,
);
const elements = container.querySelectorAll('option');
const select = getByRole('select');
expect(elements.length).toEqual(4);
expect(handleChange).not.toHaveBeenCalled();
expect(elements[1].selected).toBe(true);
userEvent.selectOptions(select, ['two']);
expect(handleChange).toHaveBeenCalledTimes(1);
expect(elements[2].selected).toBe(true);
});
Он печатает selected: one в консоли при запуске тестов. Не то значение ( два ), которое я установил в userEvent.selectOptions
.