React+jest - Testing Async Components And Waiting For Mount
Solution 1:
I was facing the exact same problem. The problem is that the test won't wait for the promises to be fulfilled. My solution was to use the the done callback, provided by Jest, to signal that the test ended.
Like this:
it('wait async code before assert something', (doneCallback) => {
const wrapper = shallow(<Component />);
setImmediate(() => {
expect(wrapper.find('.async').length).toBe(1);
doneCallback();
});
});
Solution 2:
The weird behavior is probably because you used async
for the componentDidMount
implementation.
Currently, all React rendering process is synchronous, thus everything related to its rendering flow needs to be treated as synchronous. And it happens that currently too, the React team is developing a breaking change feature to allow async rendering.
But! Even after this feature is available, keep in mind that componentDidMount
lifecycle hook will still be synchronous, and all the others hooks too, so it's important to be aware that React won't wait any Promise to resolve inside the hooks.
You can start a Promise inside the componentDidMount
if it fits your use case, and let the resolved result change the state. But the lifecycle hook will finish before it resolves, this will affect your test case because the test will need to wait for that result of the resolved Promise to be processed before asserting it, you can use jest.runAllTicks() to guarantee this behavior.
Solution 3:
enzyme-async-helpers helped me a lot with this sort of problem.
You could easily get it working by adding a loading
state and then doing something like:
import * asReactfrom'react';
import { shallow, mount } from'enzyme';
importLargeSelectorfrom'./LargeSelector';
import { waitForState } from'enzyme-async-helpers';
describe('<LargeSelector />', async () => {
describe('search', async () => {
it('should save initial response in cache', async () => {
const wrapper = awaitshallow(<LargeSelectorquery={async (search) => ['search:' + search]} />);
awaitwaitForState(wrapper, state => state.loading === false);
expect(LargeSelector.prototype.componentDidMount).toHaveBeenCalledTimes(1);
expect(wrapper.state()).toHaveProperty('options', ['search:']);
expect(wrapper.state()).toHaveProperty('initialOptions', ['search:']);
});
});
});
And:
this.setState({ initialOptions: results })
Would have to be updated to:
this.setState({ initialOptions: results, loading: false })
Post a Comment for "React+jest - Testing Async Components And Waiting For Mount"