enzyme icon indicating copy to clipboard operation
enzyme copied to clipboard

Can't check if form submit works

Open floodico opened this issue 5 years ago • 7 comments

Hello! I want to test my registration form submit, but can't check if submit handler is called. Here is my form:

     <form onSubmit={this.handleSubmit}>
        <label htmlFor="email">Email: </label> 
        <input
          name="email"
          id="email"
          type="email" />
        <label htmlFor="password">Password:</label>
        <input
          name="password"
          id="password"
          type="password" />
        <label htmlFor="password">Confirm password:</label>
        <input
          name="confirm"
          id="confirm"
          type="password" />
        <input type="submit" value="Sign Up"/>
      </form>
  

There is my test:

  it('submit works', () => {
    let submit = jest.fn();
    let wrapper = mount(<SignupForm onSubmit={submit}/>);
    wrapper.simulate('submit', { submit });
    expect(submit).toBeCalled()
  })

I get FAIL - Expected mock function to have been called.

debug()

I use mount because i can set props and this is how looks wrapper.debug():

SignupForm onSubmit={[Function: mockConstructor]}>
      <form onSubmit={[Function]}>
      ....
      </form>
    </SignupForm>

floodico avatar Jul 23 '18 14:07 floodico

Hey @floodico,

I dont think its an enzyme issue.

You need to get the form element in order to simulate something on it (right now you're on SignupForm). const form = wrapper.find('form');

Also I dont think you need to give your mocked function, inside simulate function.

emuraton avatar Jul 23 '18 15:07 emuraton

You don’t have to test if onSubmit works - that’d be testing React itself, and the browser, which isn’t your concern.

All you have to test is that the form has an onSubmit prop, that when invoked (explicitly, not using simulate) does what you expect.

Separately, I’d need to see your component code to be sure how to recommend testing that.

ljharb avatar Jul 23 '18 16:07 ljharb

Hello @emuraton! You are right, it's not enzyme issue. But i did not know how to pass mocked function into form. Actually i need to give my mocked function inside simulate function, cause i expect it will be called.

Hey @ljharb! All i wanted to test is that my mocked submitHandler(which is setted to onSubmit prop) is called at submit simulation.

How this worked

Now i set my prop in form something differently:

<form onSubmit={this.props.signUp}>
    ....
</form>

And using shallow rendering:

let submit = jest.fn();
let wrapper = shallow(<SignupForm signUp={submit}/>);

Now i provide my mocked function submit to onSubmit prop right. Cause wrapper.debug() returns:

<form onSubmit={[Function: mockConstructor]}>
   ...
</form>

After that my test worked successfully.

Maybe I called the issue a bit wrong. I meant i want to test my submit handler. Thank you guys for your responses! If you have some advices then text to me here

floodico avatar Jul 24 '18 08:07 floodico

@floodico right, you don't need to test that - React and the browser will be sure it's called. All you need to assert is that the onSubmit is set to the function you expect, and that the function you expect behaves the way you expect.

So, in your case, all you need to do is wrapper.prop('onSubmit') === submit, and you've tested everything about that that you need to for SignupForm.

ljharb avatar Jul 24 '18 15:07 ljharb

wrapper.find("form").simulate("submit");

works fine.

But it would be nicer if I could simply send a keyDown event to the input-element inside the form.

<form onSubmit={[Function: mockConstructor]}>
    <input type="text" />
</form>

wrapper.find("input").simulate("keydown", { keyCode: 13, which: 13 });

But that does not call the submit handler.

ReneCode avatar Oct 03 '18 09:10 ReneCode

Hello! I want to test my registration form submit, but can't check if submit handler is called. Here is my form:

     <form onSubmit={this.handleSubmit}>
        <label htmlFor="email">Email: </label> 
        <input
          name="email"
          id="email"
          type="email" />
        <label htmlFor="password">Password:</label>
        <input
          name="password"
          id="password"
          type="password" />
        <label htmlFor="password">Confirm password:</label>
        <input
          name="confirm"
          id="confirm"
          type="password" />
        <input type="submit" value="Sign Up"/>
      </form>
  

There is my test:

  it('submit works', () => {
    let submit = jest.fn();
    let wrapper = mount(<SignupForm onSubmit={submit}/>);
    wrapper.simulate('submit', { submit });
    expect(submit).toBeCalled()
  })

I get FAIL - Expected mock function to have been called.

debug()

I use mount because i can set props and this is how looks wrapper.debug():

SignupForm onSubmit={[Function: mockConstructor]}>
      <form onSubmit={[Function]}>
      ....
      </form>
    </SignupForm>

I have this same issue. Has anyone cracked it?

azeezat avatar Apr 23 '19 14:04 azeezat

Found solution for me:

Switched onFinish form callback to onClick callback on submit button:

onClick={() => form.validateFields().then(<onFinishCallback>, ()=>{})}

In test:

it('', async() => {
  ...
  // without await not working, you can switch it to await new Promise((res) => setTimeout(res, 50)); after act also wotk
  await act(async () => {
    <submitButton>.simulate("click");
  });
});

MeroVinggen avatar Sep 06 '22 12:09 MeroVinggen