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.
state , we use this. setState() . This is a function available to all React components that use state, and allows us to let React know that the component state has changed. This way the component knows it should re-render, because its state has changed and its UI will most likely also change.
The state does not depend on the rendering of a component and remains unaffected by re-rendering. The state gets updated only by a lifecycle method or by a call to setState.
Migrating from react-testing-library to EnzymeTo migrate tests from react-testing-library to Enzyme, you'll need to install an additional library called enzyme-adapter-react-[react-version] . This adapter library is necessary and there are different setup steps depending on your version.
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);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With