Reputation: 1620
Enzyme newbie here. I am trying to test if the state of a React component is being updated after calling a method on that component.
This is a snippet of the component that I am testing:
class App extends React.Component {
constructor(props) {
super(props);
}
state = {
recipes: {},
user: null
};
handleUnauth = () => {
this.setState({
user: null
});
};
render() {
//render children, pass down methods as props etc...
}
}
Below is the test:
import createRouterContext from 'react-router-test-context';
import { shallow, mount } from 'enzyme';
import expect from 'expect';
import React from 'react';
import App from 'App'; //import with webpack alias
describe('App', () => {
let wrapper, context;
beforeEach(() => {
context = createRouterContext();
wrapper = mount(<App/>, { context });
});
it('should remove logged in user details on logout', () => {
const user = {
uid: 'abc123',
name: 'John Doe'
};
wrapper.setState({ user }, () => {
wrapper.instance().handleUnauth();
const userState = wrapper.state('user');
expect(userState).toEqual(null);
});
});
});
My test fails with the following error:
I understand that updating of state is not synchronous but I am not sure if that has something to do with this or if there are better ways to test this using Enzyme. Would be super grateful if someone can please point me in the right direction. Oh and I tried this by calling wrapper.update()
right after calling wrapper.instance().handleUnauth()
in the test but this too didn't work.
Upvotes: 7
Views: 12499
Reputation: 15292
From the React#setState
,
setState(updater, [callback])
setState()
enqueues changes to the component state. ThesetState
doesn't immediately update the state.setState()
does not always immediately update the component. It may batch or defer the update until later. This makes readingthis.state
right after callingsetState()
a potential pitfall.Instead, usecomponentDidUpdate
or asetState
callback(setState(updater, callback))
Solution 1:
Remove callback from setState
;
wrapper.setState({ user });
wrapper.instance().handleUnauth();
const userState = wrapper.state('user');
expect(userState).toEqual(null);
Solution 2:
Read the updated state in the callback parameter of setState callback
wrapper.setState({ user }, (userState) => {
wrapper.instance().handleUnauth();
//const userState = wrapper.state('user'); // comment it.
expect(userState).toEqual(null);
});
Upvotes: 6