Jest: React TestUtils Simulate change doesn't change checked state of checkbox

Created on 8 Feb 2015  路  6Comments  路  Source: facebook/jest

I'm not sure if this is a React Simulate thing or if it's something to do with how the DOM works in Jest.

I have a simple test to click a checkbox and report the new state back to the component. It worked fine in the browser but the Simulate.change didn't report the new state.

This example shows the error happening on just the checkbox:

describe('Checkbox', function() {
  it('should change the "checked" state of the checkbox', function() {
    var changeHandler = function(e) {
      console.log(e.currentTarget.checked);
    };

    var checkbox = TestUtils.renderIntoDocument(<input type="checkbox" defaultChecked={false} onChange={changeHandler} />);
    TestUtils.Simulate.change(checkbox.getDOMNode());
  });
});

I expect to see 'true' in the console and that's what happens in the browser (Chrome & FireFox), but not in the test.

In my understanding the change handler is supposed to happen after the state change on the element.

The test shows the same behaviour if I use a "controlled" or an "uncontrolled" component. And shows the same behaviour if I simulate a click event and use a click handler.

Most helpful comment

ran into this issue to. the trick is that you need to set all the event data that your handler expects to be there as part of the second argument to the change command.

i.e. if your event handler is checking e.target.checked then you need to pass that along.

All 6 comments

Not a bug.

I didn't understand that there was another value you could send to the Simulate functions to pass in the event.

To get the click to show that the checkbox changed I can do this:

TestUtils.Simulate.change(checkbox.getDOMNode(), {"target": {"checked": true}});

ran into this issue to. the trick is that you need to set all the event data that your handler expects to be there as part of the second argument to the change command.

i.e. if your event handler is checking e.target.checked then you need to pass that along.

@richard-flosi Thanks for the explanation! That let me finally solve my issue with checkbox testing! ;-)

@richard-flosi please provide a short example

@kurumkan I think @dangerbell example looks right.

TestUtils.Simulate.change(checkbox.getDOMNode(), {"target": {"checked": true}});

So, just make sure the second argument, the object, contains all the data that your onChange handler needs.

With the example above my handler receives a dummy target, this won't pass Flow type checks needed to access eventTarget.checked

const eventTarget = e.target;
if(eventTarget instanceof HTMLInputElement) { // will never pass
  eventTarget.checked; // can finally access it without a warning
}

Even if I hack target parameter the state of input won't change:

input.checked; // false
Simulate.change(input, { target: { checked: true } }); // input.checked = false, target.checked = true
input.checked; // false
Was this page helpful?
0 / 5 - 0 ratings