Reputation: 6940
Now, there's no way I can be the only one having trouble with this. I have a simple page built with React. In it, I have a simple component which renders a select
and - on change of the value - fires a callback. The shell of this component looks like so:
const Selector = React.createClass({
render: function() {
return (
<select id="selector" onChange={this.props.onChange}>
<option value="1">1</option>
<option value="2">2</option>
</select>
);
}
})
I want to programmatically trigger a change event on the select from within my CasperJS test script to test the subsequent page changing effect, however while I'm able to select alternate options in JS the change event never fires. Additional color on the problem and things I've already tried below:
$('#selector').val('2').change()
$('#selector').val('2').trigger('change')
var el = $('#selector').get(0);
var event = new Event('input', {bubbles: true});
el.dispatchEvent(event);
var el = $('#selector').get(0);
var event = new Event('onSelect', {bubbles: true});
el.dispatchEvent(event);
var el = $('#selector').get(0);
var event = new Event('onChange', {bubbles: true});
el.dispatchEvent(event);
var el = $('#selector').get(0);
var event = new Event('change', {bubbles: true});
el.dispatchEvent(event);
I recognize the suggested way to trigger DOM events on components is by using the Simulate object in the React Test Utilities module. However, due to the fact that PhantomJS and SlimerJS are not node modules I can't simply require the module in my Casper test script.
Right now, I feel like I have two options:
1) Use SpookyJS to drive my script through Node and require the react test utilities module inside the spooky script. I really don't want to do this, though.
2) Give up all hope of a headless browser testing framework and opt for a lower level approach using either Jest or Enzyme instead. I also don't want to do this, though.
Upvotes: 2
Views: 1562
Reputation: 6205
What worked for me was first setting the value (which is what I missed, I believe), then triggering a change event:
const elm = document.getElementById('selector');
elm.value='2';
elm.dispatchEvent(new Event('change', {'view': window,'bubbles': true}))
You might want to have look at https://github.com/vitalyq/react-trigger-change
Upvotes: 0
Reputation: 3186
From what you have described, looks like you have done enough research around Jest and other unit testing frameworks out there, not sure what was your experience that forced you to look out for browser driven tests.
Professionally, I do a lot selenium/browser based e-e a lot in general but in case of React, my level of confidence with TestUtils + mocha + jsdom is high. I was able to simulate browser events, let the app go thru its Flux logic (M & C in MVC), view will update based on the change event from Flux and finally my test can assert the situation.. only catch is the wait time determination, otherwise, I feel pretty confident that this combo works faster than driving the browser using webdriver. Got this sample repo, if that helps https://github.com/sahas-/react-jsdom-mocha-viewTesting
Upvotes: 0
Reputation: 18507
I don't see nothing wrong with your code, since you're using jQuery selector I suppose that you've it in the web page where you're performing the test, then using casper.evaluate
your function must works:
...
casper.evaluate(function() {
$('#selector').val('2').change();
});
...
Alternatively if your <select>
is inside a form
div or another element you can try with casper.fillSelectors
:
...
casper.fillSelectors('yourParentSelector',
{ 'select#selector' : '2'}
,false)
...
Hope it helps,
Upvotes: 0