Stealing an idea from ember's settled
test helper.
Assuming these conditions are true in your unit tests -
- you're using Jest
- and Jest's fake timers
- and all your data requests are happening via
fetch
You can call await settled()
before making any assertions to make sure that -
- all of React's updates are applied
- all requests made have been resolved
- all timers have run their course
(This has not been tested at all, buyer beware)
import { act } from "react-dom/test-utils";
let _fetchImpl = global.fetch;
let fetches = new Set();
global.fetch = async (...args) => {
const promise = _fetchImpl(...args);
fetches.add(promise);
return promise.then(x => {
fetches.delete(promise);
return x;
});
};
async function settled() {
while (fetches.size > 0 && jest.getTimerCount() > 0) {
await act(async () => {
jest.runAllTimers();
await Promise.all(fetches);
});
}
}
it('renders the page', async () => {
render(<App/>);
await settled();
expect(queryByRole('button')).toExist(); // or your favourite assertions
});