1

Why does this test work with legacy fake timers and not with the default modern fake timers from jest?

jest.useFakeTimers({ legacyFakeTimers: true }); // Works
// jest.useFakeTimers(); // Doesn't work

it('simpleTimer', async () => {
  async function simpleTimer(callback) {
    await callback();
    setTimeout(() => {
      simpleTimer(callback);
    }, 1000);
  }

  const callback = jest.fn();
  await simpleTimer(callback);
  for (let i = 0; i < 8; i++) {
    jest.advanceTimersByTime(1000);
    await Promise.resolve(); // allow any pending jobs in the PromiseJobs queue to run
  }
  expect(callback).toHaveBeenCalledTimes(9);  // SUCCESS
});

I got it from: https://stackoverflow.com/a/52196951, I've tried almost every answer in that post, and others like this one: Jest fake timers with promises.

Using the modern one just blocks the terminal until ^C is input/sent.

Other things that I've tried:

// 1
const flushPromises = () => new Promise(setImmediate);
// 2
const timeout = (ms) => // To wait like `await timeout(1000)`
  new Promise(resolve => {
    setTimeout(resolve, ms)
  });
// 3
await new Promise(process.nextTick);

I'm running out of ideas and places keywords to search.

I'm using:

  • Node.JS: v18.15.0;
  • Jest: v29.5.0;

With a setup file that contains only: jest.useFakeTimers().


So I realized that I had jest.useFakeTimers() both in setup file and test file. So I removed it from the setup file and left only one.

After that, I got another message:

thrown: "Exceeded timeout of 5000 ms for a test. Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

Changed again to jest.useFakeTimers({ legacyFakeTimers: true }) and worked as expected.

Rick Stanley
  • 732
  • 2
  • 9
  • 23
  • I'd like to add that interestingly enough, I have other tests that use async with fake timers for testing React Native code with Testing Library, like mocking global fetch in a helper function with a `setTimeout()` from 'timers/promises' module; I don't have this kind of problem with those tests. – Rick Stanley Mar 21 '23 at 01:42
  • I gave up for now, I'm using `{ legacyFakeTimers: true }` for this specific test, it gets the job done. – Rick Stanley Mar 21 '23 at 22:52

0 Answers0