test_runner: introduces a new MockTimers API
This PR introduces a new FakeTimers API for the native Node.js test runner.
I'm opening it for review as I've implemented all features for this initial version (it's still missing docs but I think we can start moving forward while I write them)
Backlog
-
- accept a list of "Which timers/things do I mock?" -
- add an experimental warning -
- tests -
- 100% code coverage -
- docs -
- be part of the mock module -
- works with globals -
- works with require("timers/promises") -
- works with require("timers") -
- have a .reset
function to clear the state -
- have a .releaseAllTimers
function to trigger all functions -
- .reset
calls itself after an.it
test
API:
-
- globals -
- setTimeout -
- clearTimeout -
- setInterval -
- clearInterval
-
-
- timers -
- setTimeout -
- clearTimeout -
- setInterval -
- clearInterval
-
-
- timers/promises -
- setTimeout -
- setInterval
-
For the next version:
-
- Date.now -
- performance.now -
- scheduler.wait -
- queueMicrotask/process.nextTick -
- add tests for edge cases
MockTimers Design API
MockTimers.enable(['setInterval', 'setTimeout' ]) // enable fake timers
MockTimers.reset() // clean up to the original state
MockTimers.tick(100) // advance in time by 100ms
MockTimers.runAll() // release all timers
Usage example:
import assert from 'node:assert';
import { test } from 'node:test';
test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => {
const fn = context.mock.fn();
context.mock.timers.enable(['setTimeout']);
const nineSecs = 9000;
setTimeout(fn, nineSecs);
const threeSeconds = 3000;
context.mock.timers.tick(threeSeconds);
context.mock.timers.tick(threeSeconds);
context.mock.timers.tick(threeSeconds);
assert.strictEqual(fn.mock.callCount(), 1);
});