GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — test_runner: introduces a new MockTimers API by ErickWendel · Pull Request #47775 · nodejs/node

Conversation

@ErickWendel

@ErickWendel ErickWendel commented Apr 28, 2023 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

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

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

velrino, lysandroc, ananeridev, mateus4k, carvalhoviniciusluiz, Albuquerquess, gustavopch, and gabrielcaiana reacted with hooray emoji thi2pra1, marco-ippolito, adrianmouzinho, thiagobrito, hulkish, emersonjds, velrino, felipebc11, carvalhoviniciusluiz, CarmoDaGama, and 7 more reacted with heart emoji rivailruiz, bricss, MoLow, benjamingr, fatso83, omariosouto, AZagatti, natanpires, marco-ippolito, hulkish, and 17 more reacted with rocket emoji
All reactions
  • 🎉 8 reactions
  • ❤️ 17 reactions
  • 🚀 27 reactions
@ErickWendel
test_runner: add initial draft for fakeTimers
568ad96
Signed-off-by: Erick Wendel <[email protected]>
@nodejs-github-bot

nodejs-github-bot commented Apr 28, 2023 •
edited by ErickWendel
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/test_runner
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ErickWendel ErickWendel self-assigned this Apr 28, 2023
@nodejs-github-bot nodejs-github-bot added lib / src Issues and PRs involving general changes in the lib/ or src/ directories. needs-ci PRs that need a full CI run. labels Apr 28, 2023
@benjamingr

benjamingr commented Apr 30, 2023 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Hey message me (wherever) I am a maintainer of sinon/jest's fake timers and would be happy to give feedback. I'll also leave some on this PR

christopherfulldev reacted with laugh emoji MoLow, ErickWendel, ljharb, fatso83, acidiney, rubenbelem, hulkish, emersonjds, and aelnonym reacted with heart emoji
All reactions
  • 😄 1 reaction
  • ❤️ 9 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

benjamingr
benjamingr reviewed Apr 30, 2023
View reviewed changes
Comment thread lib/internal/test_runner/fake_timers.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

benjamingr
benjamingr reviewed Apr 30, 2023
View reviewed changes
Comment thread lib/internal/test_runner/fake_timers.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

benjamingr
benjamingr reviewed Apr 30, 2023
View reviewed changes
Comment thread lib/internal/test_runner/fake_timers.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

benjamingr
benjamingr reviewed Apr 30, 2023
View reviewed changes
Comment thread lib/internal/test_runner/fake_timers.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

@benjamingr

benjamingr commented Apr 30, 2023

Copy link
Copy Markdown
Member

I'm wondering what the right layer for this is:

  • We can do it with the approach you picked (and userland libraries like sinon use) which is overriding setTimeout/setInterval etc.
  • We can override it one level deeper at the Timeout class and instead of calling binding.scheduleTimer keep the linked list / priority queue machinery and only mock out interoperating with libuv.
  • We can override one level deeper at timers.cc (e.g. override RunTimers / ScheduleTimer on node's v8 env)

It is worth mentioning that places that need fake time/timers like HTTP server date headers does new Date() so presumably that'd either have to work or be adjusted to something that does.

fatso83 reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@benjamingr

benjamingr commented Apr 30, 2023

Copy link
Copy Markdown
Member

Also cc some sinon folks @SimenB @fatso83 @mroderick

Also note you can use our tests (super simple) https://github.com/sinonjs/fake-timers/blob/main/test/fake-timers-test.js

fatso83 reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ErickWendel

ErickWendel commented Apr 30, 2023

Copy link
Copy Markdown
Member Author

That's great @benjamingr gonna check it out soon! I loved the concerns and suggestions surely it's helpful and will help making this feature a complete solution!

benjamingr reacted with heart emoji
All reactions
  • ❤️ 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@tniessen

tniessen commented May 1, 2023

Copy link
Copy Markdown
Member

We can do it with the approach you picked (and userland libraries like sinon use) which is overriding setTimeout/setInterval etc.

In that case, I am wondering if there is any advantage of having it in core, besides convenience.

If we commit to something like this at the lower levels that you mention, and not just through some monkey-patching in the test runner, we should evaluate spec-compliance and various side-effects. Timers are notoriously tricky in Node.js.

ErickWendel reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

cjihrig
cjihrig reviewed May 1, 2023
View reviewed changes

@cjihrig cjihrig left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments:

  • I don't think this should be a separate API inside of the test runner, but rather a component of the existing mock functionality.
  • I don't think this should change the code of any parts of core other than the test runner.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread lib/internal/test_runner/test.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

@benjamingr

benjamingr commented May 1, 2023

Copy link
Copy Markdown
Member

@tniessen

In that case, I am wondering if there is any advantage of having it in core, besides convenience.

Other than convenience, the motivation in several cases is that Node dates/timers use primordials which makes it impossible to mock things like http date headers impossible in userland without hacks.

fatso83 reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ErickWendel
ErickWendel force-pushed the test_runner/introduce-fake-timers branch from 7a71461 to 278893a Compare May 1, 2023 17:02
@ErickWendel
test_runner: move fakerTimers to mock module
ac0fab3
Signed-off-by: Erick Wendel <[email protected]>
@ErickWendel
ErickWendel force-pushed the test_runner/introduce-fake-timers branch from 278893a to ac0fab3 Compare May 1, 2023 17:08
@ljharb

ljharb commented May 1, 2023

Copy link
Copy Markdown
Member

@benjamingr wouldn't that defeat the purpose of primordials tho? there shouldn't be a way for later-run code to compromise first-run code.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ErickWendel
test_runner: change fakeTimers prop name
e54a162
Signed-off-by: Erick Wendel <[email protected]>
@ErickWendel
ErickWendel force-pushed the test_runner/introduce-fake-timers branch from ed3a873 to 3670374 Compare May 1, 2023 18:33
@ErickWendel
test_runner: implement PriorityQueue for timers
71ffd10
Signed-off-by: Erick Wendel <[email protected]>
@ErickWendel
ErickWendel force-pushed the test_runner/introduce-fake-timers branch from 3670374 to 71ffd10 Compare May 1, 2023 18:33
ljharb
ljharb reviewed May 1, 2023
View reviewed changes
Comment thread lib/internal/test_runner/mock/fake_timers.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

benjamingr
benjamingr reviewed May 1, 2023
View reviewed changes
Comment thread lib/internal/test_runner/mock/fake_timers.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

@ErickWendel
test_runner: add @ljharb suggestion
a0f8afd
Signed-off-by: Erick Wendel <[email protected]>
@ErickWendel
ErickWendel force-pushed the test_runner/introduce-fake-timers branch from 407644b to a0f8afd Compare May 1, 2023 18:43
benjamingr
benjamingr reviewed May 1, 2023
View reviewed changes
Comment thread lib/internal/test_runner/mock/fake_timers.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

@ErickWendel
test_runner: add @benjamingr suggestion
0f55f65
Signed-off-by: Erick Wendel <[email protected]>
@github-actions github-actions Bot mentioned this pull request Jun 24, 2023
CI Reliability 2023-06-24 nodejs/reliability#597
Open
25 tasks
@khaosdoctor khaosdoctor mentioned this pull request Jul 2, 2023
test_runner: Add Date to the supported mock APIs #48638
Merged
4 tasks done
RafaelGSS pushed a commit that referenced this pull request Jul 3, 2023
@ErickWendel @RafaelGSS
test_runner: add initial draft for fakeTimers
7d01c88
Signed-off-by: Erick Wendel <[email protected]>
PR-URL: #47775
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Moshe Atlow <[email protected]>
@RafaelGSS RafaelGSS mentioned this pull request Jul 3, 2023
v20.4.0 proposal #48643
Merged
RafaelGSS added a commit that referenced this pull request Jul 3, 2023
@RafaelGSS
2023-07-04, Version 20.4.0 (Current)
51174cd
Notable changes:

crypto:
  * update root certificates to NSS 3.90 (Node.js GitHub Bot) #48416
doc:
  * add vmoroz to collaborators (Vladimir Morozov) #48527
  * add kvakil to collaborators (Keyhan Vakil) #48449
fs, stream:
  * initial `Symbol.dispose` and `Symbol.asyncDispose` support (Moshe Atlow) #48518
test_runner:
  * (SEMVER-MINOR) add initial draft for fakeTimers (Erick Wendel) #47775
tls:
  * (SEMVER-MINOR) add ALPNCallback server option for dynamic ALPN negotiation (Tim Perry) #45190

PR-URL: #48643
RafaelGSS added a commit to RafaelGSS/node that referenced this pull request Jul 4, 2023
@RafaelGSS
2023-07-05, Version 20.4.0 (Current)
73c632e
Notable changes:

crypto:
  * update root certificates to NSS 3.90 (Node.js GitHub Bot) nodejs#48416
doc:
  * add vmoroz to collaborators (Vladimir Morozov) nodejs#48527
  * add kvakil to collaborators (Keyhan Vakil) nodejs#48449
fs, stream:
  * initial `Symbol.dispose` and `Symbol.asyncDispose` support (Moshe Atlow) nodejs#48518
test_runner:
  * (SEMVER-MINOR) add initial draft for fakeTimers (Erick Wendel) nodejs#47775
tls:
  * (SEMVER-MINOR) add ALPNCallback server option for dynamic ALPN negotiation (Tim Perry) nodejs#45190

PR-URL: nodejs#48643
RafaelGSS added a commit that referenced this pull request Jul 5, 2023
@RafaelGSS
2023-07-05, Version 20.4.0 (Current)
8fc3851
Notable changes:

crypto:
  * update root certificates to NSS 3.90 (Node.js GitHub Bot) #48416
doc:
  * add vmoroz to collaborators (Vladimir Morozov) #48527
  * add kvakil to collaborators (Keyhan Vakil) #48449
fs, stream:
  * initial `Symbol.dispose` and `Symbol.asyncDispose` support (Moshe Atlow) #48518
test_runner:
  * (SEMVER-MINOR) add initial draft for fakeTimers (Erick Wendel) #47775
tls:
  * (SEMVER-MINOR) add ALPNCallback server option for dynamic ALPN negotiation (Tim Perry) #45190

PR-URL: #48643
Ceres6 pushed a commit to Ceres6/node that referenced this pull request Aug 14, 2023
@ErickWendel @Ceres6
test_runner: add initial draft for fakeTimers
c4c3aed
Signed-off-by: Erick Wendel <[email protected]>
PR-URL: nodejs#47775
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Moshe Atlow <[email protected]>
Ceres6 pushed a commit to Ceres6/node that referenced this pull request Aug 14, 2023
@RafaelGSS @Ceres6
2023-07-05, Version 20.4.0 (Current)
7fa148c
Notable changes:

crypto:
  * update root certificates to NSS 3.90 (Node.js GitHub Bot) nodejs#48416
doc:
  * add vmoroz to collaborators (Vladimir Morozov) nodejs#48527
  * add kvakil to collaborators (Keyhan Vakil) nodejs#48449
fs, stream:
  * initial `Symbol.dispose` and `Symbol.asyncDispose` support (Moshe Atlow) nodejs#48518
test_runner:
  * (SEMVER-MINOR) add initial draft for fakeTimers (Erick Wendel) nodejs#47775
tls:
  * (SEMVER-MINOR) add ALPNCallback server option for dynamic ALPN negotiation (Tim Perry) nodejs#45190

PR-URL: nodejs#48643
Ceres6 pushed a commit to Ceres6/node that referenced this pull request Aug 14, 2023
@ErickWendel @Ceres6
test_runner: add initial draft for fakeTimers
572525a
Signed-off-by: Erick Wendel <[email protected]>
PR-URL: nodejs#47775
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Moshe Atlow <[email protected]>
Ceres6 pushed a commit to Ceres6/node that referenced this pull request Aug 14, 2023
@RafaelGSS @Ceres6
2023-07-05, Version 20.4.0 (Current)
574f438
Notable changes:

crypto:
  * update root certificates to NSS 3.90 (Node.js GitHub Bot) nodejs#48416
doc:
  * add vmoroz to collaborators (Vladimir Morozov) nodejs#48527
  * add kvakil to collaborators (Keyhan Vakil) nodejs#48449
fs, stream:
  * initial `Symbol.dispose` and `Symbol.asyncDispose` support (Moshe Atlow) nodejs#48518
test_runner:
  * (SEMVER-MINOR) add initial draft for fakeTimers (Erick Wendel) nodejs#47775
tls:
  * (SEMVER-MINOR) add ALPNCallback server option for dynamic ALPN negotiation (Tim Perry) nodejs#45190

PR-URL: nodejs#48643
@ruyadorno

ruyadorno commented Sep 10, 2023

Copy link
Copy Markdown
Member

This commit has a broken test when cherry-picked into v18.x-staging. It's going to need manual backporting in case we want it in v18.

ErickWendel reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ruyadorno ruyadorno added the backport-requested-v18.x label Sep 10, 2023
@atlowChemi atlowChemi mentioned this pull request Sep 10, 2023
fs, test_runner, timers: Use kResistStopPropagation where applicable #48521
Merged
@ruyadorno ruyadorno mentioned this pull request Sep 11, 2023
test: add Symbol.dispose support to mocktimers #48549
Merged
atlowChemi pushed a commit to atlowChemi/node that referenced this pull request Sep 12, 2023
@ErickWendel @atlowChemi
test_runner: add initial draft for fakeTimers
5529c87
Signed-off-by: Erick Wendel <[email protected]>
PR-URL: nodejs#47775
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Moshe Atlow <[email protected]>
@atlowChemi atlowChemi mentioned this pull request Sep 12, 2023
[v18.x backport] Backport a couple of PRs #49618
Closed
@ErickWendel ErickWendel mentioned this pull request Sep 16, 2023
[v18.x backport] test_runner: introduces a new MockTimers API #49672
Closed
atlowChemi pushed a commit to atlowChemi/node that referenced this pull request Sep 18, 2023
@ErickWendel @atlowChemi
test_runner: add initial draft for fakeTimers
5e66fec
Signed-off-by: Erick Wendel <[email protected]>
PR-URL: nodejs#47775
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Moshe Atlow <[email protected]>
@ruyadorno ruyadorno added backport-open-v18.x and removed backport-requested-v18.x labels Sep 18, 2023
@targos targos removed the backport-open-v18.x label Oct 28, 2023
@targos targos mentioned this pull request Nov 28, 2023
v18.19.0 release proposal #50953
Merged
@ErickWendel ErickWendel mentioned this pull request Oct 15, 2024
test_runner: mark mockTimers as stable #55398
Closed
@coderabbitai coderabbitai Bot mentioned this pull request Aug 9, 2026
Add popup-first Hosted Auth React SDK namoidhq/namoid-js#12
Merged
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@ljharb ljharb ljharb approved these changes
@tniessen tniessen tniessen left review comments
@benjamingr benjamingr benjamingr approved these changes
@MoLow MoLow MoLow approved these changes
@aduh95 aduh95 Awaiting requested review from aduh95
@cjihrig cjihrig Awaiting requested review from cjihrig
+1 more reviewer
@fatso83 fatso83 fatso83 left review comments
Reviewers whose approvals may not affect merge requirements

Uh oh!

There was an error while loading. Please reload this page.

Assignees

@ErickWendel ErickWendel

Labels

commit-queue-squash PRs the Commit Queue should land as one squashed commit. experimental Issues and PRs related to experimental features. lib / src Issues and PRs involving general changes in the lib/ or src/ directories. needs-ci PRs that need a full CI run. notable-change PRs with changes that should be highlighted in changelogs. semver-minor PRs that contain new features and should be released in the next minor version. test_runner Issues and PRs related to the test runner subsystem.

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

11 participants

@ErickWendel @nodejs-github-bot @benjamingr @tniessen @ljharb @MoLow @cjihrig @ruyadorno @fatso83 @aduh95 @targos
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.