Using react-testing-library I am doing a very simple test : just rendering a component and clicking on a button.
it('tests a button click', async () => {
render(<Test/>)
await screen.findAllByRole('heading')
let buttons = await screen.findAllByRole("button");
fireEvent.click(buttons[0]);
});
My component "Test" is very simple, containing just a heading and form with a button.
The form uses react-hook-form, and I would like to react to the submitting of the form. I would like to change the value of my "foobar" object.
However in the following code the "console.info" will never be called.
export default function Test() {
const { handleSubmit } = useForm();
const [foobar, setFoobar] = React.useState<string>("foo");
if (foobar) {
console.info("this will never get called if onSubmit is called from handleSubmit")
}
const onSubmit = () => {
setFoobar("bar")
}
return (
<>
<h1>Test</h1>
<form onSubmit={handleSubmit(onSubmit)}>
<button type={"submit"}>Hi</button>
</form>
</>
);
}
I do not understand this behaviour, because if I just have a normal button like in the code below, the "console.info" WILL be called.
export default function Test() {
const { handleSubmit } = useForm();
const [foobar, setFoobar] = React.useState<string>("foo");
if (foobar) {
console.info("this will never get called if onSubmit is called from handleSubmit")
}
const onSubmit = () => {
setFoobar("bar")
}
return (
<>
<h1>Test</h1>
<form onSubmit={handleSubmit(onSubmit)}>
</form>
<button onClick={()=>onSubmit()}>Hi</button>
</>
);
}
Strangely, this seems to only happen when I use "react testing library".
If I use both these examples in my actual application then BOTH "console.info" will be called.
So, at this stage I am not sure if the problem lies with react-hook-form or with react-testing-library.
Any help much appreciated.
If you wrap the fireEvent
call inside an act(...)
it should work:
it('tests a button click', async () => {
render(<Test/>)
await screen.findAllByRole('heading');
let buttons = await screen.findAllByRole('button');
await act(async () => {
fireEvent.click(buttons[0]);
});
});