Reputation: 5179
I am writing a test to ensure my form is submitting using react testing library and I am also using react hook form. My submit method is failing to be called within my test. I am greeting with the following error when this test runs:
● reset password should send
expect(jest.fn()).toHaveBeenCalled()
Expected number of calls: >= 1
Received number of calls: 0
Can someone explain what I am doing incorrectly?
My component
const ResetPassword = () => {
const { handleSubmit } = useForm();
const onSubmit = (resetFormData: { email: string }) => {
const { email } = resetFormData;
// sends email using external API
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input
name="email"
type="text"
placeholder="Email Address"
/>
<button type="submit">
Send Email
</button>
</form>
);
};
export default ResetPassword;
My Test File
import userEvent from '@testing-library/user-event';
import { render, cleanup, screen, act } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
afterEach(cleanup);
it('reset password should send', async () => {
render(<ResetPassword />);
const handleSubmit = jest.fn();
const onSubmit = jest.fn();
const value = '[email protected]';
const input = screen.getByPlaceholderText(/Email Address/i);
await userEvent.type(input, value);
await act(async () => {
userEvent.click(screen.getByRole('button', { name: /Send Email/i }));
});
expect(onSubmit).toHaveBeenCalled();
});
Upvotes: 4
Views: 7131
Reputation: 5179
For anyone who stumbles upon this in the future, I read the article commented by Trixin and rewrote my unit test. Here's a slim version of it now. Basically, I'm testing for what the user would experience rather than the developer to avoid false positives/negatives
Component
const ResetPassword = () => {
const { handleSubmit } = useForm();
const [message, setMessage] = useState(''); // I alert the
// user of a successful sent message
const onSubmit = (resetFormData: { email: string }) => {
const { email } = resetFormData;
// sends email using external API
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input
name="email"
type="text"
placeholder="Email Address"
/>
<button type="submit">
Send Email
</button>
{message}
</form>
);
};
export default ResetPassword;
Test File
it('reset password should send', async () => {
render(<ResetPassword />);
const value = '[email protected]';
const input = screen.getByPlaceholderText(/Email Address/i);
await userEvent.type(input, value);
await act(async () => {
fireEvent.click(screen.getByText(/Send Email/i));
});
expect(screen.getByText('Message Sent!')).toBeInTheDocument();
});
it('reset password should not send', async () => {
render(<ResetPassword />);
const input = screen.getByPlaceholderText(/Email Address/i);
const inValidEmail = 'user.com';
await userEvent.type(input, inValidEmail);
await act(async () => {
fireEvent.click(screen.getByText(/Send Email/i));
});
expect(screen.getByText('Invalid email address')).toBeInTheDocument();
// reset input value
fireEvent.change(input, { target: { value: '' } });
await userEvent.type(input, '');
// user hits spacebar and tries to submit
await act(async () => {
fireEvent.keyDown(input, {
charCode: 62,
code: 62,
key: 'Space Bar',
keyCode: 62,
});
});
await act(async () => {
fireEvent.click(screen.getByText(/Send Email/i));
});
expect(screen.getByText('Email is required')).toBeInTheDocument();
});
Upvotes: 5