Reputation: 1409
Component.js
import React from 'react'
import request from 'superagent'
export default React.createClass({
getInitialState() {
return {cats: []}
},
componentDidMount() {
request('/api', (err, res) => {
if (err) return;
this.setState({
cats: res.body.results
})
})
},
render() {
let cats = this.state.cats
let catsList = (
<ul>
{cats.map((c) => <li key={c.id}>cat</li>)}
</ul>
)
return (
<div>
{cats.length ? catsList : null}
</div>
)
}
})
Component.test.js
jest.unmock('../app.js')
jest.unmock('superagent')
import React from 'react'
import {mount} from 'enzyme'
import nock from 'nock'
import App from '../app.js'
describe('App', () => {
let ajaxFn
beforeEach(() => {
ajaxFn = nock('http://localhost')
.get('/api')
.reply(200, {
results: [{id: 1}, {id: 2}, {id: 3}]
})
})
it('renders correct number of cats', () => {
let wrapper = mount(<App />)
expect(wrapper.state('cats').length).toBe(3)
})
})
The test does not pass. wrapper.state('cats').length
is always 0
.
I understand that setState
doesn't guarantee to update state immediately,
however if I log 'cats' in the component, I can see it updating.
Upvotes: 14
Views: 8065
Reputation: 4857
I am not familiar with all the libraries you are using, but since your code is being executed asynchronously the test is finishing before the state can be updated. I was able to solve this problem by adding async/await to the test:
it('renders correct number of cats', async () => {
let wrapper = await mount(<App />)
expect(wrapper.state('cats').length).toBe(3)
})
Upvotes: 0
Reputation: 488
I had a similar problem and it was necessary to return a promise from the it
callback and check the expectation in the then
method of the promise.
In your case (assuming ajaxFn was a promise, or you could turn it into one) I think this would be approximately:
it('renders correct number of cats', () => {
let wrapper = mount(<App />)
return ajaxFn.then(() => {
expect(wrapper.state('cats').length).toBe(3);
}
})
Upvotes: 2
Reputation: 2695
If you end up setting state in your component in some context that enzyme doesn't know about, you will have to manually call .update()
on the wrapper in order for it to get the updated version of the render tree.
it('renders correct number of cats', () => {
let wrapper = mount(<App />)
expect(wrapper.update().state('cats').length).toBe(3)
})
Upvotes: 10