Reputation: 1232
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
Upvotes: 3
Views: 1937
Reputation: 3806
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);
Upvotes: 2