Skip to content

Commit a5b3d76

Browse files
authored
test_runner: align mock timeout api
Expose Timeout.close() and Timeout[Symbol.dispose]() from MockTimers. This keeps fake setTimeout() handles aligned with the public Timeout API so disposal-based patterns do not throw. Add targeted coverage for Timeout.close() and Timeout[Symbol.dispose](). Signed-off-by: sangwook <rewq5991@gmail.com> PR-URL: #62820 Fixes: #62815 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Chemi Atlow <chemi@atlow.co.il> Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Jacob Smith <jacob@frende.me>
1 parent 3dc06ae commit a5b3d76

2 files changed

Lines changed: 39 additions & 0 deletions

File tree

lib/internal/test_runner/mock/mock_timers.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,15 @@ const TIMERS_DEFAULT_INTERVAL = {
7979
};
8080

8181
class Timeout {
82+
#clear;
83+
8284
constructor(opts) {
8385
this.id = opts.id;
8486
this.callback = opts.callback;
8587
this.runAt = opts.runAt;
8688
this.interval = opts.interval;
8789
this.args = opts.args;
90+
this.#clear = opts.clear;
8891
}
8992

9093
hasRef() {
@@ -102,6 +105,15 @@ class Timeout {
102105
refresh() {
103106
return this;
104107
}
108+
109+
close() {
110+
this.#clear(this);
111+
return this;
112+
}
113+
114+
[SymbolDispose]() {
115+
this.#clear(this);
116+
}
105117
}
106118

107119
class MockTimers {
@@ -329,6 +341,7 @@ class MockTimers {
329341
runAt: this.#now + delay,
330342
interval: isInterval ? delay : undefined,
331343
args,
344+
clear: this.#clearTimeout,
332345
};
333346

334347
const timer = new Timeout(opts);

test/parallel/test-runner-mock-timers.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,32 @@ describe('Mock Timers Test Suite', () => {
266266
assert.deepStrictEqual(fn.mock.calls[0].arguments, args);
267267
});
268268

269+
it('should expose Timeout.prototype[Symbol.dispose]', (t) => {
270+
t.mock.timers.enable({ apis: ['setTimeout'] });
271+
const fn = t.mock.fn();
272+
const timeout = globalThis.setTimeout(fn, 2000);
273+
274+
assert.strictEqual(typeof timeout[Symbol.dispose], 'function');
275+
276+
timeout[Symbol.dispose]();
277+
t.mock.timers.tick(2000);
278+
279+
assert.strictEqual(fn.mock.callCount(), 0);
280+
});
281+
282+
it('should expose Timeout.prototype.close()', (t) => {
283+
t.mock.timers.enable({ apis: ['setTimeout'] });
284+
const fn = t.mock.fn();
285+
const timeout = globalThis.setTimeout(fn, 2000);
286+
287+
assert.strictEqual(typeof timeout.close, 'function');
288+
assert.strictEqual(timeout.close(), timeout);
289+
290+
t.mock.timers.tick(2000);
291+
292+
assert.strictEqual(fn.mock.callCount(), 0);
293+
});
294+
269295
it('should keep setTimeout working if timers are disabled', (t, done) => {
270296
const now = Date.now();
271297
const timeout = 2;

0 commit comments

Comments
 (0)