Skip to content

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

Merge request reports

Loading