4

Here is the example:

http://jsfiddle.net/hulufei/twr4thuh/7/

It just worked when bind onClick in virtual dom(like line 18), but If I comment line 18 and comment off line 8 to bind click with addEventListener, it failed.

So what's the problem?

2 Answers 2

2

TestUtils triggers events within react's synthetic event system, so the native event that addEventListener listens for is never going to be triggered. You will need to use the native click method on the element in your test:

    var events = Events();
    ReactTestUtils.renderIntoDocument(events);
    events.refs.button.getDOMNode().click();

    events.state.event.should.equal('click');

Additionally, you've misspelled clickHandler in your addEventListener definition.

jsfiddle

You can also simplify adding your event listener by reusing your prop definition:

componentDidMount: function () {
    this.refs.button.getDOMNode().addEventListener('click', this.clickHandler);
},

Note:

Is there a reason why you want to use addEventListener instead of just passing an onClick attribute for your button? Unless there's a specific and good reason otherwise, i'd suggest doing things the react way when handling events for sanity :)

Edit

I originally mentioned that I did not know what TestUtils' SimulateNative.click did not trigger the event. I was wrong in thinking that it ever would since it would be simulating a native click event within the react even system. @thilo pointed me in the right direction :)

Sign up to request clarification or add additional context in comments.

3 Comments

thanks for your answer, it's really helpful to point out react's synthetic event system. I'm a little confused about your last mentioned SimulateNative.Click, is that mean SimulateNative.Click can trigger native events, instead Simulate.Click only triggers events within react's synthetic event system?
About why I use addEventListener. I defined a mixin, I wanted to bind some events in mixin instead of manually bind these events in every component using the mixin, and some other events binded dynamically in some triggered event handler. Is there a better way to do this?
@hulufei SimulateNative just dispatches a "native" event through react's synthetic event system, rather than a "react" event source. So it's never going to trigger a native event listener. As for an approach to share behavior between components, It's hard to say without seeing what you are trying to accomplish. I would start another SO question.
1

I had many problems while testing addEventListener, and I got the following conclusion.

You can create the events listener with pure javascript, jquery, but when running the tests with Jest I always had a problem.

The rendering of ReactTestUtils does not work directly with the document, and when we do:

For example, our events were added in the document, when rendering with ReactTestUtils it creates a div and renders it in the div, This way I could not get Simulate to trigger the call.

My first solution was to use jquery to create the listener and to test I did the render manually by appending the div in document.body, and triggered the events with the dispachEvent of javascript. But I thought the code was dirty, not the best way to work.

I made a sample code by adding the event and testing it with Jest, also have a test teaching to get all the listener that were created.

You can find the code here: https://github.com/LVCarnevalli/create-react-app/tree/master/src/components/datepicker

Component:

componentDidMount() {   
 ReactDOM.findDOMNode(this.datePicker.refs.input).addEventListener("change", (event) => {
    const value = event.target.value;
    this.handleChange(Moment(value).toISOString(), value);
  });
}

Test:

it('change empty value date picker', () => {
    const app = ReactTestUtils.renderIntoDocument(<Datepicker />);
    const datePicker = ReactDOM.findDOMNode(app.datePicker.refs.input);
    const value = "";

    const event = new Event("change");
    datePicker.value = value;
    datePicker.dispatchEvent(event);

    expect(app.state.formattedValue).toEqual(value);
});

Links:

window.addEventListener not triggered by simulated events: https://github.com/airbnb/enzyme/issues/426

Creating and triggering events: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events

1 Comment

Thank you! .dispatchEvent(event); fixed it for me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.