Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 44ac0e1

Browse filesBrowse files
mcollinaaduh95
authored andcommitted
test_runner: make it compatible with fake timers
Signed-off-by: Matteo Collina <hello@matteocollina.com> PR-URL: #59272 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Chemi Atlow <chemi@atlow.co.il> Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Aviv Keller <me@aviv.sh> Reviewed-By: Paolo Insogna <paolo@cowtech.it>
1 parent 198b6e0 commit 44ac0e1
Copy full SHA for 44ac0e1

3 files changed

+58-1Lines changed: 58 additions & 1 deletion

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎lib/internal/test_runner/test.js‎

Copy file name to clipboardExpand all lines: lib/internal/test_runner/test.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ function stopTest(timeout, signal) {
149149

150150
disposeFunction = () => {
151151
abortListener[SymbolDispose]();
152-
timer[SymbolDispose]();
152+
clearTimeout(timer);
153153
};
154154
}
155155

Collapse file
+43Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
'use strict';
2+
3+
// Simulate @sinonjs/fake-timers: patch the timers module BEFORE
4+
// the test runner is loaded, so the test runner captures the patched
5+
// versions at import time.
6+
const nodeTimers = require('node:timers');
7+
const originalSetTimeout = nodeTimers.setTimeout;
8+
const originalClearTimeout = nodeTimers.clearTimeout;
9+
10+
const fakeTimers = new Map();
11+
let nextId = 1;
12+
13+
nodeTimers.setTimeout = (fn, delay, ...args) => {
14+
const id = nextId++;
15+
const timer = originalSetTimeout(fn, delay, ...args);
16+
fakeTimers.set(id, timer);
17+
// Sinon fake timers return an object with unref/ref but without
18+
// Symbol.dispose, which would cause the test runner to throw.
19+
return { id, unref() {}, ref() {} };
20+
};
21+
22+
nodeTimers.clearTimeout = (id) => {
23+
if (id != null && typeof id === 'object') id = id.id;
24+
const timer = fakeTimers.get(id);
25+
if (timer) {
26+
originalClearTimeout(timer);
27+
fakeTimers.delete(id);
28+
}
29+
};
30+
31+
// Now load the test runner - it will capture our patched setTimeout/clearTimeout
32+
const { test } = require('node:test');
33+
34+
test('test with fake timers and timeout', { timeout: 10_000 }, () => {
35+
// This test verifies that the test runner works when setTimeout returns
36+
// an object without Symbol.dispose (like sinon fake timers).
37+
// Previously, the test runner called timer[Symbol.dispose]() which would
38+
// throw TypeError on objects returned by fake timer implementations.
39+
});
40+
41+
// Restore
42+
nodeTimers.setTimeout = originalSetTimeout;
43+
nodeTimers.clearTimeout = originalClearTimeout;
Collapse file
+14Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
'use strict';
2+
require('../common');
3+
const fixtures = require('../common/fixtures');
4+
const assert = require('node:assert');
5+
const { spawnSync } = require('node:child_process');
6+
const { test } = require('node:test');
7+
8+
test('mock timers do not break test timeout cleanup', async () => {
9+
const fixture = fixtures.path('test-runner', 'mock-timers-with-timeout.js');
10+
const cp = spawnSync(process.execPath, ['--test', fixture], {
11+
timeout: 30_000,
12+
});
13+
assert.strictEqual(cp.status, 0, `Test failed:\nstdout: ${cp.stdout}\nstderr: ${cp.stderr}`);
14+
});

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.