I'm trying to test a React component which has an async componentDidMount
.
The promise itself doesn't need to be mocked, it's not necessarily for accessing outer content, mostly just a wrapper for props.
However, in order to test it I need to use wrapper.update()
4 times which seems really weird to me.
The solutions in:
- How do test async components with Jest?
- https://github.com/airbnb/enzyme/issues/1027
- https://github.com/airbnb/enzyme/issues/1581
- https://github.com/airbnb/enzyme/issues/346
all didn't work for me.
Here's what my test looks like (which currently works, but this solution isn't elegant at all, and not too scalable):
import * as React from 'react'
import { shallow, mount } from 'enzyme'
import LargeSelector from './LargeSelector'
describe('<LargeSelector />', async () => {
const componentDidMountSpy = jest.spyOn(LargeSelector.prototype, 'componentDidMount')
describe('search', async () => {
it('should save initial response in cache', async () => {
const wrapper = await shallow(<LargeSelector query={async (search) => ['search:' + search]} />)
// WHY DO I NEED 4 UPDATES???
await wrapper.update()
await wrapper.update()
await wrapper.update()
await wrapper.update()
expect(LargeSelector.prototype.componentDidMount).toHaveBeenCalledTimes(1) // works fine
// these 2 only pass the expectation if I call wrapper.update() no less than 4 times
expect(wrapper.state()).toHaveProperty('options', ['search:'])
expect(wrapper.state()).toHaveProperty('initialOptions', ['search:'])
})
})
})
Here are the implementations of componentDidMount
and filterResults
(call in the former):
public async componentDidMount() {
if (this.props.searchOnInit) {
const results = await this.filterResults('', [])
if (this.props.cacheInitialResponse) {
this.setState({ initialOptions: results })
}
}
}
private async filterResults(search: string, filters: IFilter[]) {
const results = await this.props.query(search, filters)
this.setState({ options: results })
return results
}