I've set up some tests of a React ponent that displays a table using Mocha. I can assert on its initial state but I have a click event which sorts the data that I'd like to test.
If I use React.addons.TestUtils.Simulate.click(theComponent)
to try to test the sort.
- I can see that the event is handled,
- that the state change is fired
- the data is sorted before calling
setState
but when I assert against the ponent nothing has changed.
it('sorts the data when the year header is clicked', function() {
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;
var payTable = TestUtils.renderIntoDocument(
<PayTable payYears={data} />
);
var headers = TestUtils.scryRenderedDOMComponentsWithTag(payTable, 'th');
var yearHeader = headers[0];
TestUtils.Simulate.click(yearHeader.getDOMNode());
var columnValues = getYearColumnValues(payTable, TestUtils);
columnValues.should.match([ 'Year', '1066', '1067', '1068' ]);
});
Do I need to force an update? Re-read the ponent?
The code is available on Github.
I can test other aspects of the Component but not the Component values after setState
I've set up some tests of a React ponent that displays a table using Mocha. I can assert on its initial state but I have a click event which sorts the data that I'd like to test.
If I use React.addons.TestUtils.Simulate.click(theComponent)
to try to test the sort.
- I can see that the event is handled,
- that the state change is fired
- the data is sorted before calling
setState
but when I assert against the ponent nothing has changed.
it('sorts the data when the year header is clicked', function() {
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;
var payTable = TestUtils.renderIntoDocument(
<PayTable payYears={data} />
);
var headers = TestUtils.scryRenderedDOMComponentsWithTag(payTable, 'th');
var yearHeader = headers[0];
TestUtils.Simulate.click(yearHeader.getDOMNode());
var columnValues = getYearColumnValues(payTable, TestUtils);
columnValues.should.match([ 'Year', '1066', '1067', '1068' ]);
});
Do I need to force an update? Re-read the ponent?
The code is available on Github.
I can test other aspects of the Component but not the Component values after setState
- If you are using Mocha to test DOM changes you could use mochify to help. I wrote an example on the wiki on how to test ReactJS ponents which may be of help: github./mantoni/mochify.js/wiki/… – T. Junghans Commented Mar 18, 2015 at 11:59
- If you don't want to use the setTimeout hack, or another library. Try creating callbacks for your events. Such as YearHeaderSelected or similar on Paytable. You can then pass that in and respond to it in your test – MrJD Commented Jul 13, 2015 at 13:03
2 Answers
Reset to default 4I had the same issue. The thing is, TestUtils.Simulate.click(yearHeader.getDOMNode())
is making a click on the DOM, which brings about sorting data and DOM manipulation. Even if you use jsDom and not a real dom, this manipulation itself is an async event. So, just by checking the DOM state right after the click event you are making a syncronous call, within which the DOM state has not been changed yet.
The solution is, use a setTimeout
with 0 milliseconds timeout, and check the DOM state there. As for you example :
setTimeout(function() {
var columnValues = getYearColumnValues(payTable, TestUtils);
columnValues.should.match([ 'Year', '1066', '1067', '1068' ]);
},0)
This would make your DOM update its state and you will be able to test your ponent.
I've been spending a lot of time trying to find a clean way to work with the asynchronousity... Ended up making this for testing:
https://github./yormi/test-them-all
Under the hood, it uses ponentDidUpdate
lifecycle to listen on props/state/route changes.
Hopefully, it'll help you guys. Anyhow your opinion would be greatly appreciated :)