react: Triggering events on real DOM nodes doesn't trigger synthetic events

From Twitter: https://twitter.com/Vjeux/status/569985084524081153

When using PhantomJS for testing browser interaction, often times what seems to happen is that values get changed directly on the DOM elements and then the ‘change’ event is triggered on the element. Because of this, interacting with ReactJS elements through PhantomJS and through jQuery doesn’t work for some interactive elements like <input> and <select>.

Of course, the easiest solution is to take the real elements that are mounted and attach event listeners to them like $(this.MyRef.getDOMNode()).on(EVENT, CALLBACK), but it isn’t the most pleasant experience.

Is there any interest in mirroring events on the real nodes to the synthetic events, or is this situation normal? I’d like to be able to interact with my application through PhantomJS, but this seems to be quite the blocker when interacting with input and select elements.

JSBin example here: http://jsbin.com/xawogo/3/edit

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 20 (4 by maintainers)

Most upvoted comments

Trying to get an interactive product tour and was hoping to drive the UI through events (just like the user would).

Just as @bloodyowl said, the problem looks to be with jQuery not React. This issue can probably be closed.

Use the code below instead.

var event = document.createEvent("HTMLEvents");
event.initEvent("click", true, true);
var target = $('.about-page-link')[0];
target.dispatchEvent(event);

If you are working on an end-to-end test suite, there is no need to manually simulate events. Testing tools provide appropriate methods to simulate user input, which dispatch all the necessary events. In PhantomJS the idiomatic way to perform input is through sendEvent, but it’s quite low-level. Instead use PhantomJS together with Selenium or CasperJS. Nightmare is another option. All of these tools include methods for simulating keyboard and mouse input. In this way, React’s synthetic events will be triggered as appropriate.

For unit and integration tests that are run in a browser ReactTestUtils.Simulate should generally be sufficient. If you find yourself writing unit tests against a production bundle, chances are high that you should be writing end-to-end tests using the tools listed above instead.

If you still need to trigger React’s synthetic change events directly for some reason and the bundle is built for production, you can take a look at my react-trigger-change package.

hi @yagudaev How about KeyBoardEvent, I tried keypress, but it does not work…

Is there a good solution for using PhantomJS to trigger things like submitting a form, clicking a button etc…? I’m having the same issue where React listeners never get triggered.

how does react listen for onChange?, if we use the non production react and TestUtils.simulate it works even in ie9. is there a way to replicate that with production react?

seems like its a combination of ObjectDefineProperty and an event for ‘propertychange’: https://github.com/facebook/react/blob/3b96650e39ddda5ba49245713ef16dbc52d25e9e/src/renderers/dom/client/eventPlugins/ChangeEventPlugin.js

For now, I’ve pub/subbed my way around this (rather than use DOM events). In IE9, there is definitely an issue with listening to programmatic propertychange events.

@yagudaev You, sir, just saved us a lot of time. Thank you!

the issue here is that jQuery doesn’t trigger a real DOM event, but tries to find callbacks in its own internal event map (as you can see http://jsbin.com/pesanowoqe/1/edit?js,console,output)