Skip to content

Commit 11fbd92

Browse files
ErickWendeltargos
authored andcommitted
test_runner: add support for setImmediate
PR-URL: #49397 Reviewed-By: Chemi Atlow <chemi@atlow.co.il> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
1 parent 48a1b93 commit 11fbd92

File tree

3 files changed

+312
-10
lines changed

3 files changed

+312
-10
lines changed

doc/api/test.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -1531,9 +1531,10 @@ added:
15311531
Enables timer mocking for the specified timers.
15321532

15331533
* `timers` {Array} An optional array containing the timers to mock.
1534-
The currently supported timer values are `'setInterval'` and `'setTimeout'`.
1535-
If no array is provided, all timers (`'setInterval'`, `'clearInterval'`, `'setTimeout'`,
1536-
and `'clearTimeout'`) will be mocked by default.
1534+
The currently supported timer values are `'setInterval'`, `'setTimeout'`,
1535+
and `'setImmediate'`. If no value is provided, all timers (`'setInterval'`,
1536+
`'clearInterval'`, `'setTimeout'`, `'clearTimeout'`, `'setImmediate'`,
1537+
and `'clearImmediate'`) will be mocked by default.
15371538

15381539
**Note:** When you enable mocking for a specific timer, its associated
15391540
clear function will also be implicitly mocked.

lib/internal/test_runner/mock/mock_timers.js

+72-5
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,19 @@ function abortIt(signal) {
4747
return new AbortError(undefined, { __proto__: null, cause: signal.reason });
4848
}
4949

50-
const SUPPORTED_TIMERS = ['setTimeout', 'setInterval'];
50+
const SUPPORTED_TIMERS = ['setTimeout', 'setInterval', 'setImmediate'];
51+
const TIMERS_DEFAULT_INTERVAL = {
52+
__proto__: null,
53+
setImmediate: -1,
54+
};
5155

5256
class MockTimers {
5357
#realSetTimeout;
5458
#realClearTimeout;
5559
#realSetInterval;
5660
#realClearInterval;
61+
#realSetImmediate;
62+
#realClearImmediate;
5763

5864
#realPromisifiedSetTimeout;
5965
#realPromisifiedSetInterval;
@@ -62,6 +68,9 @@ class MockTimers {
6268
#realTimersClearTimeout;
6369
#realTimersSetInterval;
6470
#realTimersClearInterval;
71+
#realTimersSetImmediate;
72+
#realTimersClearImmediate;
73+
#realPromisifiedSetImmediate;
6574

6675
#timersInContext = [];
6776
#isEnabled = false;
@@ -75,6 +84,16 @@ class MockTimers {
7584
#setInterval = FunctionPrototypeBind(this.#createTimer, this, true);
7685
#clearInterval = FunctionPrototypeBind(this.#clearTimer, this);
7786

87+
#setImmediate = (callback, ...args) => {
88+
return this.#createTimer(
89+
false,
90+
callback,
91+
TIMERS_DEFAULT_INTERVAL.setImmediate,
92+
...args,
93+
);
94+
};
95+
96+
#clearImmediate = FunctionPrototypeBind(this.#clearTimer, this);
7897
constructor() {
7998
emitExperimentalWarning('The MockTimers API');
8099
}
@@ -157,7 +176,7 @@ class MockTimers {
157176
yield* iterator;
158177
}
159178

160-
#setTimeoutPromisified(ms, result, options) {
179+
#promisifyTimer({ timerFn, clearFn, ms, result, options }) {
161180
return new Promise((resolve, reject) => {
162181
if (options?.signal) {
163182
try {
@@ -172,12 +191,12 @@ class MockTimers {
172191
}
173192

174193
const onabort = () => {
175-
this.#clearTimeout(id);
194+
clearFn(id);
176195
return reject(abortIt(options.signal));
177196
};
178197

179-
const id = this.#setTimeout(() => {
180-
return resolve(result || id);
198+
const id = timerFn(() => {
199+
return resolve(result);
181200
}, ms);
182201

183202
if (options?.signal) {
@@ -191,6 +210,28 @@ class MockTimers {
191210
});
192211
}
193212

213+
#setImmediatePromisified(result, options) {
214+
return this.#promisifyTimer({
215+
__proto__: null,
216+
timerFn: FunctionPrototypeBind(this.#setImmediate, this),
217+
clearFn: FunctionPrototypeBind(this.#clearImmediate, this),
218+
ms: TIMERS_DEFAULT_INTERVAL.setImmediate,
219+
result,
220+
options,
221+
});
222+
}
223+
224+
#setTimeoutPromisified(ms, result, options) {
225+
return this.#promisifyTimer({
226+
__proto__: null,
227+
timerFn: FunctionPrototypeBind(this.#setTimeout, this),
228+
clearFn: FunctionPrototypeBind(this.#clearTimeout, this),
229+
ms,
230+
result,
231+
options,
232+
});
233+
}
234+
194235
#toggleEnableTimers(activate) {
195236
const options = {
196237
__proto__: null,
@@ -232,6 +273,23 @@ class MockTimers {
232273
this,
233274
);
234275
},
276+
setImmediate: () => {
277+
this.#realSetImmediate = globalThis.setImmediate;
278+
this.#realClearImmediate = globalThis.clearImmediate;
279+
this.#realTimersSetImmediate = nodeTimers.setImmediate;
280+
this.#realTimersClearImmediate = nodeTimers.clearImmediate;
281+
282+
globalThis.setImmediate = this.#setImmediate;
283+
globalThis.clearImmediate = this.#clearImmediate;
284+
285+
nodeTimers.setImmediate = this.#setImmediate;
286+
nodeTimers.clearImmediate = this.#clearImmediate;
287+
288+
nodeTimersPromises.setImmediate = FunctionPrototypeBind(
289+
this.#setImmediatePromisified,
290+
this,
291+
);
292+
},
235293
},
236294
toReal: {
237295
__proto__: null,
@@ -253,6 +311,15 @@ class MockTimers {
253311

254312
nodeTimersPromises.setInterval = this.#realPromisifiedSetInterval;
255313
},
314+
setImmediate: () => {
315+
globalThis.setImmediate = this.#realSetImmediate;
316+
globalThis.clearImmediate = this.#realClearImmediate;
317+
318+
nodeTimers.setImmediate = this.#realTimersSetImmediate;
319+
nodeTimers.clearImmediate = this.#realTimersClearImmediate;
320+
321+
nodeTimersPromises.setImmediate = this.#realPromisifiedSetImmediate;
322+
},
256323
},
257324
};
258325

0 commit comments

Comments
 (0)