TJBlackman
TJBlackman

Reputation: 2313

React + Jest + Enzyme form onSubmit test fails unless I use timeout

I have a React form wrapper that takes an onSubmit prop of type function, and I want to test if it's being called with the correct form values. If I check it right away, it fails, but if I put the check behind a 100ms timeout, it passes.

So it appears as if there needs to be some kind of processing time for the functions to be executed, but the timeout is so janky...

Example

test('onSubmit function is called with correct form values', () => {
    const defaults = {
        email: '[email protected]',
        password: 'soSoSecret!'
    };
    const submitFunction = jest.fn();
    const wrapper = mount(<LoginForm onSubmit={submitFunction} />);

    // input form values
    wrapper
        .find('input[name="email"]')
        .simulate('change', { target: { value: defaults.email } });
    wrapper
        .find('input[name="password"]')
        .simulate('change', { target: { value: defaults.password } });

    expect(submitFunction.mock.calls.length).toBe(0);
    wrapper.find('form button[type="submit"]').simulate('click');

    // if I test right away, it fails, but if I set timeout for 100ms, it passes
    // does the form take time to process and the function be called????

    jest.useFakeTimers();
    setTimeout(() => {
        expect(submitFunction.mock.calls.length).toBe(1);
        const args = submitFunction.mock.calls[0][0];
        expect(args).toEqual(defaults);
    }, 100);
});

Is it possible to write a test like this without a timeout? Seems like an issue to me.

Thanks for reading! :D

Upvotes: 0

Views: 433

Answers (1)

Anuradha Kumari
Anuradha Kumari

Reputation: 703

One reason that I could think of is that you are trying to test something that happens asynchronously, and not right away. In that case, you can try using async await PFB example:

test('onSubmit function is called with correct form values', async () => {
    const defaults = {
        email: '[email protected]',
        password: 'soSoSecret!'
    };
    const submitFunction = jest.fn();
    const wrapper = mount(<LoginForm onSubmit={submitFunction} />);

    // input form values
    wrapper
        .find('input[name="email"]')
        .simulate('change', { target: { value: defaults.email } });
    wrapper
        .find('input[name="password"]')
        .simulate('change', { target: { value: defaults.password } });

    expect(submitFunction.mock.calls.length).toBe(0);
    await wrapper.find('form button[type="submit"]').simulate('click');

        expect(submitFunction.mock.calls.length).toBe(1);
        const args = submitFunction.mock.calls[0][0];
        expect(args).toEqual(defaults);
});

Notice the async keyword before the test case callback begins, and the await keyword before the submit button click is simulated.

Upvotes: 1

Related Questions