I have a React component that I'm using shadcn/ui in, specifically in this case, the Select:
<div className='flex-1'>
<FormField
control={form.control}
name='clientType'
render={({ field }) => (
<FormItem>
<FormLabel>
Client Type <span className='text-red-500 text-xs'>*</span>
</FormLabel>
<Select onValueChange={field.onChange} value={field.value}>
<FormControl>
<SelectTrigger className='w-full px-3 py-2 border rounded shadow-sm focus:outline-none focus:ring-1 focus:ring-indigo-500'>
<SelectValue placeholder='Select a Client Type' />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value='Direct'>Direct</SelectItem>
<SelectItem value='VMS'>VMS</SelectItem>
<SelectItem value='Lm'>Lm</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</div>
I'm writing unit tests (Jest, React Testing Library), but I haven't been able to change the value of this select from my test. I've tried getting the reference as a combo box and a button and tried userEvent and fireEvent. Nothing seems to work.
I'm also using react-hook-forms, just fyi.
Has anyone done this, and can you show me the technique you used?
Thanks, James
You need to use fireEvent.pointerDown to open up the select options in your unit test. You'll also need to mock a few things. I'm using vitest but you can use jest as well.
// required mocks to open Shadcn Select component
export class MockPointerEvent extends Event {
button: number | undefined;
ctrlKey: boolean | undefined;
constructor(type: string, props: PointerEventInit | undefined) {
super(type, props);
if (props) {
if (props.button != null) {
this.button = props.button;
}
if (props.ctrlKey != null) {
this.ctrlKey = props.ctrlKey;
}
}
}
}
window.PointerEvent = MockPointerEvent as any;
window.HTMLElement.prototype.scrollIntoView = vi.fn();
window.HTMLElement.prototype.hasPointerCapture = vi.fn();
window.HTMLElement.prototype.releasePointerCapture = vi.fn();
Then in your test code, use
fireEvent.pointerDown(
selectElementTrigger,
new MockPointerEvent('pointerdown', {
ctrlKey: false,
button: 0,
})
);
And finally, to select the option from you Select component, do:
const selectedOption = await waitFor(() => findByText("You_option_here"));
fireEvent.click(selectedOption);
When using Next.js instead of React Native, I found that you need to use fireEvent.click() instead of fireEvent.pointerDown().
const selectElement = await screen.findByTestId("color-select");
fireEvent.click(selectElement);
const greenOption = await waitFor(() => screen.findByText("Green"));
fireEvent.click(greenOption);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With