4

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();
});
1
  • 1
    Defining a locally scoped function onSubmit with just the same name in your test will not do anything. For the interpreter this is a completely different function. You need to mock the actual function that gets called in you component. Also this is testing implementation details and is generally not recommended. A better way to test it would be to mock the actual fetch that happens on submit. Commented Jan 31, 2021 at 14:58

1 Answer 1

5

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();
});
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.