Mocking Submit of final-form in react

3.1k views Asked by At

I am attempting to test that a callback function is being called by submitting a form. I have mocked an onSubmit function which is passed into react-final-form. As shown in the codesandbox and below, I've got a simple form with an onSubmit callback.

export const MyForm = ({ onSubmit }) => (
  <Form
    onSubmit={onSubmit}
    render={({ handleSubmit }) => (
      <form onSubmit={handleSubmit} autoComplete="off">
        <Field
          label="Email"
          component={Input}
          name="email"
          type="email"
          autoComplete="off"
        />
        <button>Submit</button>
      </form>
    )}
  />
);

When I simulate a click event on the button, I expect it to call the mocked function.


  it("should call onSubmit when the button is click", () => {
    const button = wrapper.find("button");
    expect(button.length).toBeGreaterThan(0);
    button.at(0).simulate("click");
    expect(mockSubmit).toHaveBeenCalled();
  });

Any assistance would be greatly appreciated.

Codesandbox

2

There are 2 answers

1
Brenden On BEST ANSWER

You will need to simulate submit in order to submit the form.

As for the Warning: An update to ReactFinalForm inside a test was not wrapped in act(...)., you are using a promise in your submit handler in the test which causes the form validation, submit, and state updates to be async.

act() provides a scope around expected component updates, and you will get this warning when an component does something outside of this scope. Since in the test the submit handler is async, the updates will happen outside of the act() function and will give you this error.

There are two ways to fix this, make the submit handler sync via jest.fn().

const mockSubmit = jest.fn();

If you need to keep this async, you will need to act/await over a the submit promise. This would mean you would need to create a resolved promise value and have a mock function resolve it.

  const promise = Promise.resolve();
  const mockSubmit = jest.fn(() => promise);

  beforeEach(() => {
    wrapper = mount(<MyForm onSubmit={mockSubmit} />);
  });

  it("should call onSubmit when the button is click 2", async () => {
    const button = wrapper.find("form");
    expect(button.length).toBeGreaterThan(0);
    button.at(0).simulate("submit");
    expect(mockSubmit).toHaveBeenCalled();

    await act(() => promise);
  });
0
Erik R. On

My preferred method is to use <button type="submit">Submit</button> and then fireEvent.click(getByText('Submit')), like this.