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
});