Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test a form with Jest and React JS TestUtils

I have a form with 3 radio buttons like follows (fake names):

<form className="myForm" onSubmit={this.done}>
  <input className="myRadio" checked={ŧrue} type="radio" name="myRadio" onChange={this.change} value="value1"
  <input className="myRadio" type="radio" name="myRadio" onChange={this.change} value="value2"
  <input className="myRadio" type="radio" name="myRadio" onChange={this.change} value="value3"
<input type="submit" className="submit" />
</form>

And I am having very hard time trying to test the onChange and the onSubmit events.

inputs = TestUtils.scryRenderedDOMComponentsWithClass(MyComponentRendered, 'myRadio');
myForm = TestUtils.findRenderedDOMComponentWithClass(MyComponentRendered, 'myForm');

I have a test like:

it("changes the checked state when clicked", function() {
  MyComponent.change = jest.genMockFunction();

  expect(inputs[0].getDOMNode().checked).toBe(true);
  TestUtils.Simulate.change(inputs[1], {target: {value: 'value2'}});
  expect(inputs[0].getDOMNode().checked).toBe(false);
  expect(inputs[1].getDOMNode().checked).toBe(true);
  expect(inputs[2].getDOMNode().checked).toBe(false);

  expect(MyComponent.change).toBeCalled(); //Fails
  expect(MyComponent.change.mock.calls.length).toBe(1); //Fails too
});

That works except for the function (MyComponent.change) that should be called but it is not.

I also have one test for onSubmit:

it("saves on submit", function()
  MyComponent.done = jest.genMockFunction();
  MyComponent.insideDone = jest.genMockFunction();
  TestUtils.Simulate.submit(myForm);
  expect(MyComponent.done).toBeCalled(); //Fails
  expect(MyComponent.insideDone).toBeCalled(); //Success
});

Notice: MyComponent.insideDone is a function that is called by 'done' function.

Which fails too. I am pretty sure that the problem here is that I am not simulating the events in a correct way. However, I didn't find example of this using Jest and TestUtils from React.

like image 872
Ferran Negre Avatar asked Oct 20 '14 16:10

Ferran Negre


1 Answers

The problem is that you are replacing the function after you have already given the original function to React. The expression onSubmit={this.done} is that function, and that is set as the event handler. After the render function finishes, you replace instance.done but React already got the old function. What you should do is instead:

<form className="myForm" onSubmit={() => this.done()}>

This makes sure that the event handler always invokes the method on the instance (the one you replaced). This has the nice side effect of being future compatible with React, since they will stop autobinding all methods to the instance.

like image 179
Anders Ekdahl Avatar answered Oct 23 '22 03:10

Anders Ekdahl