I have a form created with React Hook Form that has a required text input field and a submit button. If the user doesn't enter a value to the field before submitting the form, an error message (from formState: { errors }
of RHF's useForm
hook) is shown to the user in a div
element that is otherwise hidden.
This code checks this functionality correctly in my test, using (React) Testing Library and its fireEvent
function:
render(<MyPage />);
const submitButton = screen.getByRole("button", { name: "Submit form" });
await act(async () => {
fireEvent.click(submitButton);
});
const errorMessage = screen.queryByText("This value is required");
expect(errorMessage).toBeVisible();
However, I thought I'd start using the @testing-library/user-event library in my tests to better simulate an actual user.
Following its documentation, I tried the following:
const user = userEvent.setup();
render(<MyPage />);
const submitButton = screen.getByRole("button", { name: "Submit form" });
await user.click(submitButton);
const errorMessage = screen.queryByText("This value is required");
expect(errorMessage).toBeVisible();
This doesn't work, i.e. the query doesn't find any elements.
Neither does this:
await act(async () => {
user.click(submitButton);
});
This DOES work:
await act(async () => {
await user.click(submitButton);
});
but gives a warning "The current testing environment is not configured to support act".
Interestingly what works best is calling the event twice (and not wrapping it in act
):
await user.click(submitButton);
await user.click(submitButton);
It seems that actually any two events make the test pass without warnings, e.g.
await user.click(submitButton);
await user.tab();
I also have @testing-library/jest-dom
imported in the file which I guess might cause the act
-related warning.
So I know there are a lot of moving parts here that might cause the issue, but does anyone see any logical reason why I have to call these user-event
events twice to trigger the same effect that I get with a single fireEvent
call?
Just to be clear, the error message is shown correctly – and immediately after the button click – in the browser when I test this manually.