promiseDelay
returns a Promise
that resolves after ms
so call a spy
in then
and test to see if the spy
has been called after different intervals:
describe('promiseDelay', () => {
beforeEach(() => { jest.useFakeTimers(); });
afterEach(() => { jest.useRealTimers(); });
test('should not resolve until timeout has elapsed', async () => {
const spy = jest.fn();
promiseDelay(100).then(spy); // <= resolve after 100ms
jest.advanceTimersByTime(20); // <= advance less than 100ms
await Promise.resolve(); // let any pending callbacks in PromiseJobs run
expect(spy).not.toHaveBeenCalled(); // SUCCESS
jest.advanceTimersByTime(80); // <= advance the rest of the time
await Promise.resolve(); // let any pending callbacks in PromiseJobs run
expect(spy).toHaveBeenCalled(); // SUCCESS
});
});
Note that test code is synchronous and Timer Mocks make setTimeout
synchronous but then
queues a callback in PromiseJobs
so any queued callbacks need to be allowed to run before testing if the spy
has been called.
This can be done by using an async
test function and calling await
on a resolved Promise
which effectively queues the rest of the test at the end of PromiseJobs
allowing any pending callbacks to run before the test continues.
Additional information about how promises and fake timers interact is available in my answer here.