When use jest.advanceTimersToNextTimer(steps), you don't need to provide the milliseconds manually anymore to run the macro-tasks have been queued via setTimeout() or setInterval(). Like the doc said:
Advances all timers by the needed milliseconds so that only the next timeouts/intervals will run.
Besides, you can provide a steps to jest.advanceTimersToNextTimer() method so that it will run steps amount of next timeouts/intervals. See "should pass with steps" test case. The default steps is 1, see here
When use jest.advanceTimersByTime(), if there are a lot of macro-tasks queued via setTimeout() or setInterval(), if we want to advance all timers, we have to calculate the msToRun milliseconds by ourself. This is maybe very cumbersome. See "should pass advance all timers" test case.
Besides, sometimes you may want to check the status before the timer execution. In this case, you have to use jest.advanceTimersByTime(), see this real world example, the timer is 200 millisecond,but they check the state of the fast forward in 199 milliseconds.
jest.advanceTimersToNextTimer() use click.next() method of the @sinonjs/faker-timers package underly.
Advances the clock to the the moment of the first scheduled timer, firing it.
jest.advanceTimersByTime() just use clock.tick(time) underly.
See the below example, three test cases do the same thing in different ways.
describe('71667406', () => {
beforeAll(() => {
jest.useFakeTimers();
});
afterAll(() => {
jest.useRealTimers();
});
describe('advanceTimersToNextTimer', () => {
test('should pass', () => {
const runOrder: Array<string> = [];
const mock1 = jest.fn(() => runOrder.push('mock1'));
const mock2 = jest.fn(() => runOrder.push('mock2'));
const mock3 = jest.fn(() => runOrder.push('mock3'));
const mock4 = jest.fn(() => runOrder.push('mock4'));
setTimeout(mock1, 100);
setTimeout(mock2, 0);
setTimeout(mock3, 0);
setInterval(() => {
mock4();
}, 200);
jest.advanceTimersToNextTimer();
// Move forward to t=0
expect(runOrder).toEqual(['mock2', 'mock3']);
jest.advanceTimersToNextTimer();
// Move forward to t=100
expect(runOrder).toEqual(['mock2', 'mock3', 'mock1']);
jest.advanceTimersToNextTimer();
// Move forward to t=200
expect(runOrder).toEqual(['mock2', 'mock3', 'mock1', 'mock4']);
jest.advanceTimersToNextTimer();
// Move forward to t=400
expect(runOrder).toEqual(['mock2', 'mock3', 'mock1', 'mock4', 'mock4']);
});
test('should pass with steps', () => {
const runOrder: Array<string> = [];
const mock1 = jest.fn(() => runOrder.push('mock1'));
const mock2 = jest.fn(() => runOrder.push('mock2'));
const mock3 = jest.fn(() => runOrder.push('mock3'));
const mock4 = jest.fn(() => runOrder.push('mock4'));
setTimeout(mock1, 100);
setTimeout(mock2, 0);
setTimeout(mock3, 0);
setInterval(() => {
mock4();
}, 200);
jest.advanceTimersToNextTimer(4);
expect(runOrder).toEqual(['mock2', 'mock3', 'mock1', 'mock4', 'mock4']);
});
});
describe('advanceTimersByTime', () => {
test('should pass', () => {
const runOrder: Array<string> = [];
const mock1 = jest.fn(() => runOrder.push('mock1'));
const mock2 = jest.fn(() => runOrder.push('mock2'));
const mock3 = jest.fn(() => runOrder.push('mock3'));
const mock4 = jest.fn(() => runOrder.push('mock4'));
setTimeout(mock1, 100);
setTimeout(mock2, 0);
setTimeout(mock3, 0);
setInterval(() => {
mock4();
}, 200);
jest.advanceTimersByTime(0);
// Move forward to t=0
expect(runOrder).toEqual(['mock2', 'mock3']);
jest.advanceTimersByTime(100);
// Move forward to t=100
expect(runOrder).toEqual(['mock2', 'mock3', 'mock1']);
jest.advanceTimersByTime(200);
// Move forward to t=200
expect(runOrder).toEqual(['mock2', 'mock3', 'mock1', 'mock4']);
jest.advanceTimersByTime(200);
// Move forward to t=400
expect(runOrder).toEqual(['mock2', 'mock3', 'mock1', 'mock4', 'mock4']);
});
test('should pass advance all timers', () => {
const runOrder: Array<string> = [];
const mock1 = jest.fn(() => runOrder.push('mock1'));
const mock2 = jest.fn(() => runOrder.push('mock2'));
const mock3 = jest.fn(() => runOrder.push('mock3'));
const mock4 = jest.fn(() => runOrder.push('mock4'));
setTimeout(mock1, 100);
setTimeout(mock2, 0);
setTimeout(mock3, 0);
setInterval(() => {
mock4();
}, 200);
// We need to calculate it, this is very cumbersome
jest.advanceTimersByTime(0 + 100 + 200 + 200);
expect(runOrder).toEqual(['mock2', 'mock3', 'mock1', 'mock4', 'mock4']);
});
});
});
Test result:
PASS stackoverflow/71667406/index.test.ts
71667406
advanceTimersToNextTimer
✓ should pass (4 ms)
✓ should pass with steps
advanceTimersByTime
✓ should pass (1 ms)
Test Suites: 1 passed, 1 total
Tests: 3 passed, 3 total
Snapshots: 0 total
Time: 1.242 s
I also hope that Jest official can give more examples to explain the use scenario of the API.