I've taken a ReactJS component (rendering the latest gist URL for a given user) from the React docs, and was wondering what is the best way to unit test such a component :
The goals are
- Test in isolation (using mocked http calls)
- Use our existing test setup (mocha)
- Keep things simple
- Verify that eventually, when the http call in the component success, the state change triggered a re-render, and an anchor element is rendered the proper url in it.
Here's the component I want to test:
import React from 'react'
import $ from 'jquery'
export default React.createClass({
getInitialState: function() {
return {
username: '',
lastGistUrl: ''
};
},
componentDidMount: function() {
fetch(this.props.source).then(function(response) {
return response.json()
}).then(function(json) {
this.setState({
username: json[0].owner.login,
lastGistUrl: json[0].html_url
});
}.bind(this)).catch(function(ex) {
console.log('parsing failed', ex)
})
},
render: function() {
return (
<div>
{this.state.username}'s last gist is
<a href={ this.state.lastGistUrl}>here</a>.
</div>
);
}
});
And here is my first attempt at testing it:
import TestUtils from 'react-addons-test-utils'
import React from 'react'
import { expect } from 'chai'
import { findDOMNode } from 'react-dom'
import UserGist from '../assets/js/components/UserGistWithFetch'
import nock from 'nock'
describe('UserGistWithFetch', () => {
it('Displays the correct url', (done) => {
nock.disableNetConnect();
nock('https://api.github.com')
.get('/users/octocat/gists')
.reply(200, [{owner:"octocat",html_url:"https://gist.github.com/6cad326836d38bd3a7ae"}])
const gist = TestUtils.renderIntoDocument(<UserGist source="https://api.github.com/users/octocat/gists"/>)
let a = TestUtils.scryRenderedDOMComponentsWithTag(gist, 'a')[0]
expect(a.getAttribute('href')).to.be.equal("https://gist.github.com/6cad326836d38bd3a7ae")
done()
})
})
This test obviously fails, as the component is initially rendered before the mock callback is executed, not rendering the anchor correctly.
The test fails before the mocked http call returns, and the component doesn't get a chance to re-render.
From what I understand, Mocha provides ways to do async testing (using the done()
function), but I can't find a hook in my test to put this.
What tools / frameworks would I need to accomplish that ?