Skip to content

fix(testing): FakeTime fakes node:timers and node:timers/promises timer methods#7181

Open
truffle-dev wants to merge 2 commits into
denoland:mainfrom
truffle-dev:fix-faketime-node-timers
Open

fix(testing): FakeTime fakes node:timers and node:timers/promises timer methods#7181
truffle-dev wants to merge 2 commits into
denoland:mainfrom
truffle-dev:fix-faketime-node-timers

Conversation

@truffle-dev

@truffle-dev truffle-dev commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Fixes #7177.

FakeTime only swaps the globalThis timer functions (plus Date and AbortSignal.timeout), but the node:timers polyfill never reads those globals — timers.promises.setTimeout constructs a Timeout that schedules through the internal createTimer_ primitive, so the fake clock is invisible to anything entering through node:timers. The repro in the issue hangs because the real one-second timer never fires inside the test's fake-time window.

This patch makes overrideGlobals()/restoreGlobals() also swap the timer methods on the node:timers and node:timers/promises module objects: setTimeout/clearTimeout/setInterval/clearInterval delegate to the same fakes already used for the globals, and node:timers/promises setTimeout gets a promise fake built on the fake scheduler that honors signal (both pre-aborted and aborted mid-flight). In Deno the object attached at timers.promises and the node:timers/promises module object are distinct, so both are patched.

Two implementation notes:

  • The module objects are obtained through process.getBuiltinModule() rather than static node: imports. A static import adds a node: edge to the published module graph, which _tools/check_docs.ts (via @deno/doc) fails to load; getBuiltinModule returns the same module object (the new tests compare against statically imported references), is synchronous, and lets runtimes without the Node compatibility layer skip the patching instead of failing to load @std/testing/time. Deno 1.x predates getBuiltinModule, so the faking and the corresponding tests are skipped there (verified locally against 1.46.3); the test file also views the module objects through local types, since the Node typings bundled with Deno 1.x lack promises on node:timers and declare an incompatible AbortSignal on node:timers/promises.
  • Named imports such as import { setTimeout } from "node:timers/promises" capture the real implementation at module load and cannot be faked afterwards. This is documented in the FakeTime jsdoc along with a runnable example.

setImmediate and the promise-based setInterval are left unfaked, consistent with FakeTime not faking immediates on globalThis today; the jsdoc lists exactly which methods are faked.

The issue's repro shape is covered in time_test.ts, plus faked/restored identity checks mirroring the existing global-timer tests and abort rejection coverage for the promise fake. deno task lint, deno fmt --check, and deno test -A --doc testing/ all pass locally.

@codecov

codecov Bot commented Jun 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.03922% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 94.57%. Comparing base (cdf74a8) to head (4d39965).

Files with missing lines Patch % Lines
testing/time.ts 97.56% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7181      +/-   ##
==========================================
- Coverage   94.57%   94.57%   -0.01%     
==========================================
  Files         636      637       +1     
  Lines       52142    52200      +58     
  Branches     9401     9406       +5     
==========================================
+ Hits        49315    49367      +52     
- Misses       2249     2254       +5     
- Partials      578      579       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FakeTime does not mock node:timers methods

1 participant