I have a solution I use for this particular problem, but I'd be interested to know if there is a simpler or better way of implementing it.
When testing React components in Jest, I often will have to wait for Promises to resolve before I can accurately test the updated render. For example, when a component on mount does a network request in a side effect:
const TestComponent: React.FunctionComponent = () => {
const [state, setState] = useState<NetworkPayload>()
useEffect(() => {
SomeNetworkRequest().then(setState)
}, [])
if (!state) {
return <Spin/>
}
return <div>{state.foo}</div>
}
In the Jest test, I would mock the network response and return a promise so my test can wait for the promise and assert against the latest render:
function MockNetworkResponse<T extends Object> (response: T) {
global.Request = jest.fn()
const promise = Promise.resolve(response)
global.fetch = () => Promise.resolve({
ok: true,
json: () => promise
} as unknown as Response) // we only need to mock that which we are actually using
return promise
}
test("Should render foo", async () => {
let testComponent: ReactWrapper
const networkPromise = MockNetworkRequest({foo: "test"})
await act(async () => {
testComponent = mount(<TestComponent/>)
await networkPromise
})
testComponent = testComponent
testComponent.update()
expect(testComponent.text()).toEqual("test")
})
While this does work in terms of waiting for the promise chain to resolve before testing the component's rendered state, I'm not sure if there is possibly a simpler way of waiting until the component reaches the state I want.
I like to try and avoid relying on timeout loops as it could create additional test execution time, and there isn't any way of directly referencing the promise chain inside the effect itself.
The above solution can get increasingly complicated if say there are multiple network requests, or subsequent ones caused by mount of other child components that have their own network behavior.
Any advice / pointers would be appreciated. It may be simply that there is a good library for handling cases like this more gracefully.