Skip to content

Commit 384259e

Browse files
test_runner: sync ESM exports when mocking timers
This change ensures that ESM imports of node:timers/promises are correctly mocked when using mock.timers.enable(). This is achieved by calling syncBuiltinESMExports() whenever the mocked timers are toggled or reset. Fixes: #62081
1 parent 8edeff9 commit 384259e

File tree

2 files changed

+49
-3
lines changed

2 files changed

+49
-3
lines changed

lib/internal/test_runner/mock/mock_timers.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const {
2424
validateNumber,
2525
validateStringArray,
2626
} = require('internal/validators');
27+
const { syncBuiltinESMExports } = require('internal/modules/cjs/loader');
2728

2829
const {
2930
AbortError,
@@ -440,9 +441,9 @@ class MockTimers {
440441

441442
const eventIt = EventEmitter.on(emitter, 'data');
442443
const timer = this.#createTimer(true,
443-
() => emitter.emit('data'),
444-
interval,
445-
options);
444+
() => emitter.emit('data'),
445+
interval,
446+
options);
446447

447448
try {
448449
// eslint-disable-next-line no-unused-vars
@@ -628,6 +629,7 @@ class MockTimers {
628629
const target = activate ? options.toFake : options.toReal;
629630
ArrayPrototypeForEach(this.#timersInContext, (timer) => target[timer]());
630631
this.#isEnabled = activate;
632+
syncBuiltinESMExports();
631633
}
632634

633635
/**
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { describe, it } from 'node:test';
2+
import { setTimeout } from 'node:timers/promises';
3+
import assert from 'node:assert';
4+
5+
describe('Mock Timers ESM Regression', () => {
6+
it('should work with node:timers/promises and runAll() in ESM', async (t) => {
7+
t.mock.timers.enable({ apis: ['Date', 'setTimeout'] });
8+
const startTime = Date.now();
9+
let t1 = 0;
10+
11+
await Promise.all([
12+
(async () => {
13+
await setTimeout(1000);
14+
t1 = Date.now();
15+
})(),
16+
(async () => {
17+
// Wait for the next tick to ensure setTimeout has been called
18+
await new Promise(resolve => process.nextTick(resolve));
19+
t.mock.timers.runAll();
20+
})()
21+
]);
22+
23+
assert.strictEqual(t1 - startTime, 1000);
24+
});
25+
26+
it('should work with node:timers/promises and tick() in ESM', async (t) => {
27+
t.mock.timers.enable({ apis: ['Date', 'setTimeout'] });
28+
const startTime = Date.now();
29+
let t1 = 0;
30+
31+
await Promise.all([
32+
(async () => {
33+
await setTimeout(500);
34+
t1 = Date.now();
35+
})(),
36+
(async () => {
37+
await new Promise(resolve => process.nextTick(resolve));
38+
t.mock.timers.tick(500);
39+
})()
40+
]);
41+
42+
assert.strictEqual(t1 - startTime, 500);
43+
});
44+
});

0 commit comments

Comments
 (0)