• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2process.env.NODE_TEST_KNOWN_GLOBALS = 0;
3const common = require('../common');
4
5const assert = require('node:assert');
6const { it, mock, describe } = require('node:test');
7const nodeTimers = require('node:timers');
8const nodeTimersPromises = require('node:timers/promises');
9
10describe('Mock Timers Test Suite', () => {
11  describe('MockTimers API', () => {
12    it('should throw an error if trying to enable a timer that is not supported', (t) => {
13      assert.throws(() => {
14        t.mock.timers.enable(['DOES_NOT_EXIST']);
15      }, {
16        code: 'ERR_INVALID_ARG_VALUE',
17      });
18    });
19
20    it('should throw an error if trying to enable a timer twice', (t) => {
21      t.mock.timers.enable();
22      assert.throws(() => {
23        t.mock.timers.enable();
24      }, {
25        code: 'ERR_INVALID_STATE',
26      });
27    });
28
29    it('should not throw if calling reset without enabling timers', (t) => {
30      t.mock.timers.reset();
31    });
32
33    it('should throw an error if calling tick without enabling timers', (t) => {
34      assert.throws(() => {
35        t.mock.timers.tick();
36      }, {
37        code: 'ERR_INVALID_STATE',
38      });
39    });
40
41    it('should throw an error if calling tick with a negative number', (t) => {
42      t.mock.timers.enable();
43      assert.throws(() => {
44        t.mock.timers.tick(-1);
45      }, {
46        code: 'ERR_INVALID_ARG_VALUE',
47      });
48    });
49    it('should check that propertyDescriptor gets back after resetting timers', (t) => {
50      const getDescriptor = (ctx, fn) => Object.getOwnPropertyDescriptor(ctx, fn);
51      const getCurrentTimersDescriptors = () => {
52        const timers = [
53          'setTimeout',
54          'clearTimeout',
55          'setInterval',
56          'clearInterval',
57          'setImmediate',
58          'clearImmediate',
59        ];
60
61        const globalTimersDescriptors = timers.map((fn) => getDescriptor(global, fn));
62        const nodeTimersDescriptors = timers.map((fn) => getDescriptor(nodeTimers, fn));
63        const nodeTimersPromisesDescriptors = timers
64          .filter((fn) => !fn.includes('clear'))
65          .map((fn) => getDescriptor(nodeTimersPromises, fn));
66
67        return {
68          global: globalTimersDescriptors,
69          nodeTimers: nodeTimersDescriptors,
70          nodeTimersPromises: nodeTimersPromisesDescriptors,
71        };
72      };
73
74      const originalDescriptors = getCurrentTimersDescriptors();
75
76      t.mock.timers.enable();
77      const during = getCurrentTimersDescriptors();
78      t.mock.timers.reset();
79      const after = getCurrentTimersDescriptors();
80
81      for (const env in originalDescriptors) {
82        for (const prop in originalDescriptors[env]) {
83          const originalDescriptor = originalDescriptors[env][prop];
84          const afterDescriptor = after[env][prop];
85
86          assert.deepStrictEqual(
87            originalDescriptor,
88            afterDescriptor,
89          );
90
91          assert.notDeepStrictEqual(
92            originalDescriptor,
93            during[env][prop],
94          );
95
96          assert.notDeepStrictEqual(
97            during[env][prop],
98            after[env][prop],
99          );
100
101        }
102      }
103    });
104
105    it('should reset all timers when calling .reset function', (t) => {
106      t.mock.timers.enable();
107      const fn = t.mock.fn();
108      global.setTimeout(fn, 1000);
109      t.mock.timers.reset();
110      assert.throws(() => {
111        t.mock.timers.tick(1000);
112      }, {
113        code: 'ERR_INVALID_STATE',
114      });
115
116      assert.strictEqual(fn.mock.callCount(), 0);
117    });
118
119    it('should reset all timers when calling Symbol.dispose', (t) => {
120      t.mock.timers.enable();
121      const fn = t.mock.fn();
122      global.setTimeout(fn, 1000);
123      // TODO(benjamingr) refactor to `using`
124      t.mock.timers[Symbol.dispose]();
125      assert.throws(() => {
126        t.mock.timers.tick(1000);
127      }, {
128        code: 'ERR_INVALID_STATE',
129      });
130
131      assert.strictEqual(fn.mock.callCount(), 0);
132    });
133
134    it('should execute in order if timeout is the same', (t) => {
135      t.mock.timers.enable();
136      const order = [];
137      const fn1 = t.mock.fn(() => order.push('f1'));
138      const fn2 = t.mock.fn(() => order.push('f2'));
139      global.setTimeout(fn1, 1000);
140      global.setTimeout(fn2, 1000);
141      t.mock.timers.tick(1000);
142      assert.strictEqual(fn1.mock.callCount(), 1);
143      assert.strictEqual(fn2.mock.callCount(), 1);
144      assert.deepStrictEqual(order, ['f1', 'f2']);
145    });
146
147    describe('runAll Suite', () => {
148      it('should throw an error if calling runAll without enabling timers', (t) => {
149        assert.throws(() => {
150          t.mock.timers.runAll();
151        }, {
152          code: 'ERR_INVALID_STATE',
153        });
154      });
155
156      it('should trigger all timers when calling .runAll function', async (t) => {
157        const timeoutFn = t.mock.fn();
158        const intervalFn = t.mock.fn();
159
160        t.mock.timers.enable();
161        global.setTimeout(timeoutFn, 1111);
162        const id = global.setInterval(intervalFn, 9999);
163        t.mock.timers.runAll();
164
165        global.clearInterval(id);
166        assert.strictEqual(timeoutFn.mock.callCount(), 1);
167        assert.strictEqual(intervalFn.mock.callCount(), 1);
168      });
169    });
170
171  });
172
173  describe('globals/timers', () => {
174    describe('setTimeout Suite', () => {
175      it('should advance in time and trigger timers when calling the .tick function', (t) => {
176        mock.timers.enable(['setTimeout']);
177
178        const fn = mock.fn();
179
180        global.setTimeout(fn, 4000);
181
182        mock.timers.tick(4000);
183        assert.strictEqual(fn.mock.callCount(), 1);
184        mock.timers.reset();
185      });
186
187      it('should advance in time and trigger timers when calling the .tick function multiple times', (t) => {
188        t.mock.timers.enable(['setTimeout']);
189        const fn = t.mock.fn();
190
191        global.setTimeout(fn, 2000);
192
193        t.mock.timers.tick(1000);
194        assert.strictEqual(fn.mock.callCount(), 0);
195        t.mock.timers.tick(500);
196        assert.strictEqual(fn.mock.callCount(), 0);
197        t.mock.timers.tick(500);
198        assert.strictEqual(fn.mock.callCount(), 1);
199      });
200
201      it('should work with the same params as the original setTimeout', (t) => {
202        t.mock.timers.enable(['setTimeout']);
203        const fn = t.mock.fn();
204        const args = ['a', 'b', 'c'];
205        global.setTimeout(fn, 2000, ...args);
206
207        t.mock.timers.tick(1000);
208        t.mock.timers.tick(500);
209        t.mock.timers.tick(500);
210
211        assert.strictEqual(fn.mock.callCount(), 1);
212        assert.deepStrictEqual(fn.mock.calls[0].arguments, args);
213      });
214
215      it('should keep setTimeout working if timers are disabled', (t, done) => {
216        const now = Date.now();
217        const timeout = 2;
218        const expected = () => now - timeout;
219        global.setTimeout(common.mustCall(() => {
220          assert.strictEqual(now - timeout, expected());
221          done();
222        }), timeout);
223      });
224
225    });
226
227    describe('clearTimeout Suite', () => {
228      it('should not advance in time if clearTimeout was invoked', (t) => {
229        t.mock.timers.enable(['setTimeout']);
230
231        const fn = mock.fn();
232
233        const id = global.setTimeout(fn, 4000);
234        global.clearTimeout(id);
235        t.mock.timers.tick(4000);
236
237        assert.strictEqual(fn.mock.callCount(), 0);
238      });
239    });
240
241    describe('setInterval Suite', () => {
242      it('should tick three times using fake setInterval', (t) => {
243        t.mock.timers.enable(['setInterval']);
244        const fn = t.mock.fn();
245
246        const id = global.setInterval(fn, 200);
247
248        t.mock.timers.tick(200);
249        t.mock.timers.tick(200);
250        t.mock.timers.tick(200);
251
252        global.clearInterval(id);
253
254        assert.strictEqual(fn.mock.callCount(), 3);
255      });
256
257      it('should work with the same params as the original setInterval', (t) => {
258        t.mock.timers.enable(['setInterval']);
259        const fn = t.mock.fn();
260        const args = ['a', 'b', 'c'];
261        const id = global.setInterval(fn, 200, ...args);
262
263        t.mock.timers.tick(200);
264        t.mock.timers.tick(200);
265        t.mock.timers.tick(200);
266
267        global.clearInterval(id);
268
269        assert.strictEqual(fn.mock.callCount(), 3);
270        assert.deepStrictEqual(fn.mock.calls[0].arguments, args);
271        assert.deepStrictEqual(fn.mock.calls[1].arguments, args);
272        assert.deepStrictEqual(fn.mock.calls[2].arguments, args);
273
274      });
275    });
276
277    describe('clearInterval Suite', () => {
278      it('should not advance in time if clearInterval was invoked', (t) => {
279        t.mock.timers.enable(['setInterval']);
280
281        const fn = mock.fn();
282        const id = global.setInterval(fn, 200);
283        global.clearInterval(id);
284        t.mock.timers.tick(200);
285
286        assert.strictEqual(fn.mock.callCount(), 0);
287      });
288    });
289
290    describe('setImmediate Suite', () => {
291      it('should keep setImmediate working if timers are disabled', (t, done) => {
292        const now = Date.now();
293        const timeout = 2;
294        const expected = () => now - timeout;
295        global.setImmediate(common.mustCall(() => {
296          assert.strictEqual(now - timeout, expected());
297          done();
298        }));
299      });
300
301      it('should work with the same params as the original setImmediate', (t) => {
302        t.mock.timers.enable(['setImmediate']);
303        const fn = t.mock.fn();
304        const args = ['a', 'b', 'c'];
305        global.setImmediate(fn, ...args);
306        t.mock.timers.tick(9999);
307
308        assert.strictEqual(fn.mock.callCount(), 1);
309        assert.deepStrictEqual(fn.mock.calls[0].arguments, args);
310      });
311
312      it('should not advance in time if clearImmediate was invoked', (t) => {
313        t.mock.timers.enable(['setImmediate']);
314
315        const id = global.setImmediate(common.mustNotCall());
316        global.clearImmediate(id);
317        t.mock.timers.tick(200);
318      });
319
320      it('should advance in time and trigger timers when calling the .tick function', (t) => {
321        t.mock.timers.enable(['setImmediate']);
322        global.setImmediate(common.mustCall(1));
323        t.mock.timers.tick(0);
324      });
325
326      it('should execute in order if setImmediate is called multiple times', (t) => {
327        t.mock.timers.enable(['setImmediate']);
328        const order = [];
329        const fn1 = t.mock.fn(common.mustCall(() => order.push('f1'), 1));
330        const fn2 = t.mock.fn(common.mustCall(() => order.push('f2'), 1));
331
332        global.setImmediate(fn1);
333        global.setImmediate(fn2);
334
335        t.mock.timers.tick(0);
336
337        assert.deepStrictEqual(order, ['f1', 'f2']);
338      });
339
340      it('should execute setImmediate first if setTimeout was also called', (t) => {
341        t.mock.timers.enable(['setImmediate', 'setTimeout']);
342        const order = [];
343        const fn1 = t.mock.fn(common.mustCall(() => order.push('f1'), 1));
344        const fn2 = t.mock.fn(common.mustCall(() => order.push('f2'), 1));
345
346        global.setTimeout(fn2, 0);
347        global.setImmediate(fn1);
348
349        t.mock.timers.tick(100);
350
351        assert.deepStrictEqual(order, ['f1', 'f2']);
352      });
353    });
354  });
355
356  describe('timers Suite', () => {
357    describe('setTimeout Suite', () => {
358      it('should advance in time and trigger timers when calling the .tick function multiple times', (t) => {
359        t.mock.timers.enable(['setTimeout']);
360        const fn = t.mock.fn();
361        const { setTimeout } = nodeTimers;
362        setTimeout(fn, 2000);
363
364        t.mock.timers.tick(1000);
365        t.mock.timers.tick(500);
366        t.mock.timers.tick(500);
367
368        assert.strictEqual(fn.mock.callCount(), 1);
369      });
370
371      it('should work with the same params as the original timers.setTimeout', (t) => {
372        t.mock.timers.enable(['setTimeout']);
373        const fn = t.mock.fn();
374        const { setTimeout } = nodeTimers;
375        const args = ['a', 'b', 'c'];
376        setTimeout(fn, 2000, ...args);
377
378        t.mock.timers.tick(1000);
379        t.mock.timers.tick(500);
380        t.mock.timers.tick(500);
381
382        assert.strictEqual(fn.mock.callCount(), 1);
383        assert.deepStrictEqual(fn.mock.calls[0].arguments, args);
384      });
385    });
386
387    describe('clearTimeout Suite', () => {
388      it('should not advance in time if clearTimeout was invoked', (t) => {
389        t.mock.timers.enable(['setTimeout']);
390
391        const fn = mock.fn();
392        const { setTimeout, clearTimeout } = nodeTimers;
393        const id = setTimeout(fn, 2000);
394        clearTimeout(id);
395        t.mock.timers.tick(2000);
396
397        assert.strictEqual(fn.mock.callCount(), 0);
398      });
399    });
400
401    describe('setInterval Suite', () => {
402      it('should tick three times using fake setInterval', (t) => {
403        t.mock.timers.enable(['setInterval']);
404        const fn = t.mock.fn();
405
406        const id = nodeTimers.setInterval(fn, 200);
407
408        t.mock.timers.tick(200);
409        t.mock.timers.tick(200);
410        t.mock.timers.tick(200);
411        t.mock.timers.tick(200);
412
413        nodeTimers.clearInterval(id);
414
415        assert.strictEqual(fn.mock.callCount(), 4);
416      });
417
418      it('should work with the same params as the original timers.setInterval', (t) => {
419        t.mock.timers.enable(['setInterval']);
420        const fn = t.mock.fn();
421        const args = ['a', 'b', 'c'];
422        const id = nodeTimers.setInterval(fn, 200, ...args);
423
424        t.mock.timers.tick(200);
425        t.mock.timers.tick(200);
426        t.mock.timers.tick(200);
427        t.mock.timers.tick(200);
428
429        nodeTimers.clearInterval(id);
430
431        assert.strictEqual(fn.mock.callCount(), 4);
432        assert.deepStrictEqual(fn.mock.calls[0].arguments, args);
433        assert.deepStrictEqual(fn.mock.calls[1].arguments, args);
434        assert.deepStrictEqual(fn.mock.calls[2].arguments, args);
435        assert.deepStrictEqual(fn.mock.calls[3].arguments, args);
436
437      });
438    });
439
440    describe('clearInterval Suite', () => {
441      it('should not advance in time if clearInterval was invoked', (t) => {
442        t.mock.timers.enable(['setInterval']);
443
444        const fn = mock.fn();
445        const { setInterval, clearInterval } = nodeTimers;
446        const id = setInterval(fn, 200);
447        clearInterval(id);
448        t.mock.timers.tick(200);
449
450        assert.strictEqual(fn.mock.callCount(), 0);
451      });
452    });
453
454    describe('setImmediate Suite', () => {
455      it('should keep setImmediate working if timers are disabled', (t, done) => {
456        const now = Date.now();
457        const timeout = 2;
458        const expected = () => now - timeout;
459        nodeTimers.setImmediate(common.mustCall(() => {
460          assert.strictEqual(now - timeout, expected());
461          done();
462        }, 1));
463      });
464
465      it('should work with the same params as the original setImmediate', (t) => {
466        t.mock.timers.enable(['setImmediate']);
467        const fn = t.mock.fn();
468        const args = ['a', 'b', 'c'];
469        nodeTimers.setImmediate(fn, ...args);
470        t.mock.timers.tick(9999);
471
472        assert.strictEqual(fn.mock.callCount(), 1);
473        assert.deepStrictEqual(fn.mock.calls[0].arguments, args);
474      });
475
476      it('should not advance in time if clearImmediate was invoked', (t) => {
477        t.mock.timers.enable(['setImmediate']);
478
479        const id = nodeTimers.setImmediate(common.mustNotCall());
480        nodeTimers.clearImmediate(id);
481        t.mock.timers.tick(200);
482      });
483
484      it('should advance in time and trigger timers when calling the .tick function', (t) => {
485        t.mock.timers.enable(['setImmediate']);
486        nodeTimers.setImmediate(common.mustCall(1));
487        t.mock.timers.tick(0);
488      });
489
490      it('should execute in order if setImmediate is called multiple times', (t) => {
491        t.mock.timers.enable(['setImmediate']);
492        const order = [];
493        const fn1 = t.mock.fn(common.mustCall(() => order.push('f1'), 1));
494        const fn2 = t.mock.fn(common.mustCall(() => order.push('f2'), 1));
495
496        nodeTimers.setImmediate(fn1);
497        nodeTimers.setImmediate(fn2);
498
499        t.mock.timers.tick(0);
500
501        assert.deepStrictEqual(order, ['f1', 'f2']);
502      });
503
504      it('should execute setImmediate first if setTimeout was also called', (t) => {
505        t.mock.timers.enable(['setImmediate', 'setTimeout']);
506        const order = [];
507        const fn1 = t.mock.fn(common.mustCall(() => order.push('f1'), 1));
508        const fn2 = t.mock.fn(common.mustCall(() => order.push('f2'), 1));
509
510        nodeTimers.setTimeout(fn2, 0);
511        nodeTimers.setImmediate(fn1);
512
513        t.mock.timers.tick(100);
514
515        assert.deepStrictEqual(order, ['f1', 'f2']);
516      });
517    });
518  });
519
520  describe('timers/promises', () => {
521    describe('setTimeout Suite', () => {
522      it('should advance in time and trigger timers when calling the .tick function multiple times', async (t) => {
523        t.mock.timers.enable(['setTimeout']);
524
525        const p = nodeTimersPromises.setTimeout(2000);
526
527        t.mock.timers.tick(1000);
528        t.mock.timers.tick(500);
529        t.mock.timers.tick(500);
530        t.mock.timers.tick(500);
531
532        p.then(common.mustCall((result) => {
533          assert.strictEqual(result, undefined);
534        }));
535      });
536
537      it('should work with the same params as the original timers/promises/setTimeout', async (t) => {
538        t.mock.timers.enable(['setTimeout']);
539        const expectedResult = 'result';
540        const controller = new AbortController();
541        const p = nodeTimersPromises.setTimeout(2000, expectedResult, {
542          ref: true,
543          signal: controller.signal
544        });
545
546        t.mock.timers.tick(1000);
547        t.mock.timers.tick(500);
548        t.mock.timers.tick(500);
549        t.mock.timers.tick(500);
550
551        const result = await p;
552        assert.strictEqual(result, expectedResult);
553      });
554
555      it('should abort operation if timers/promises/setTimeout received an aborted signal', async (t) => {
556        t.mock.timers.enable(['setTimeout']);
557        const expectedResult = 'result';
558        const controller = new AbortController();
559        const p = nodeTimersPromises.setTimeout(2000, expectedResult, {
560          ref: true,
561          signal: controller.signal
562        });
563
564        t.mock.timers.tick(1000);
565        controller.abort();
566        t.mock.timers.tick(500);
567        t.mock.timers.tick(500);
568        t.mock.timers.tick(500);
569        await assert.rejects(() => p, {
570          name: 'AbortError',
571        });
572
573      });
574      it('should abort operation even if the .tick wasn\'t called', async (t) => {
575        t.mock.timers.enable(['setTimeout']);
576        const expectedResult = 'result';
577        const controller = new AbortController();
578        const p = nodeTimersPromises.setTimeout(2000, expectedResult, {
579          ref: true,
580          signal: controller.signal
581        });
582
583        controller.abort();
584
585        await assert.rejects(() => p, {
586          name: 'AbortError',
587        });
588
589      });
590
591      it('should abort operation when .abort is called before calling setTimeout', async (t) => {
592        t.mock.timers.enable(['setTimeout']);
593        const expectedResult = 'result';
594        const controller = new AbortController();
595        controller.abort();
596        const p = nodeTimersPromises.setTimeout(2000, expectedResult, {
597          ref: true,
598          signal: controller.signal
599        });
600
601        await assert.rejects(() => p, {
602          name: 'AbortError',
603        });
604
605      });
606
607      it('should reject given an an invalid signal instance', async (t) => {
608        t.mock.timers.enable(['setTimeout']);
609        const expectedResult = 'result';
610        const p = nodeTimersPromises.setTimeout(2000, expectedResult, {
611          ref: true,
612          signal: {}
613        });
614
615        await assert.rejects(() => p, {
616          name: 'TypeError',
617          code: 'ERR_INVALID_ARG_TYPE'
618        });
619
620      });
621    });
622
623    describe('setInterval Suite', () => {
624      it('should tick three times using fake setInterval', async (t) => {
625        t.mock.timers.enable(['setInterval']);
626
627        const interval = 100;
628        const intervalIterator = nodeTimersPromises.setInterval(interval, Date.now());
629
630        const first = intervalIterator.next();
631        const second = intervalIterator.next();
632        const third = intervalIterator.next();
633
634        t.mock.timers.tick(interval);
635        t.mock.timers.tick(interval);
636        t.mock.timers.tick(interval);
637        t.mock.timers.tick(interval);
638
639        const results = await Promise.all([
640          first,
641          second,
642          third,
643        ]);
644
645        const finished = await intervalIterator.return();
646        assert.deepStrictEqual(finished, { done: true, value: undefined });
647
648        results.forEach((result) => {
649          assert.strictEqual(typeof result.value, 'number');
650          assert.strictEqual(result.done, false);
651        });
652
653      });
654      it('should tick five times testing a real use case', async (t) => {
655
656        t.mock.timers.enable(['setInterval']);
657
658        const expectedIterations = 5;
659        const interval = 1000;
660        const startedAt = Date.now();
661        async function run() {
662          const times = [];
663          for await (const time of nodeTimersPromises.setInterval(interval, startedAt)) {
664            times.push(time);
665            if (times.length === expectedIterations) break;
666
667          }
668          return times;
669        }
670
671        const r = run();
672        t.mock.timers.tick(interval);
673        t.mock.timers.tick(interval);
674        t.mock.timers.tick(interval);
675        t.mock.timers.tick(interval);
676        t.mock.timers.tick(interval);
677
678        const timeResults = await r;
679        assert.strictEqual(timeResults.length, expectedIterations);
680        for (let it = 1; it < expectedIterations; it++) {
681          assert.strictEqual(timeResults[it - 1], startedAt + (interval * it));
682        }
683      });
684
685      it('should abort operation given an abort controller signal', async (t) => {
686        t.mock.timers.enable(['setInterval']);
687
688        const interval = 100;
689        const abortController = new AbortController();
690        const intervalIterator = nodeTimersPromises.setInterval(interval, Date.now(), {
691          signal: abortController.signal
692        });
693
694        const first = intervalIterator.next();
695        const second = intervalIterator.next();
696
697        t.mock.timers.tick(interval);
698        abortController.abort();
699        t.mock.timers.tick(interval);
700
701        const firstResult = await first;
702        // Interval * 2 because value can be a little bit greater than interval
703        assert.ok(firstResult.value < Date.now() + interval * 2);
704        assert.strictEqual(firstResult.done, false);
705
706        await assert.rejects(() => second, {
707          name: 'AbortError',
708        });
709
710      });
711
712      it('should abort operation when .abort is called before calling setInterval', async (t) => {
713        t.mock.timers.enable(['setInterval']);
714
715        const interval = 100;
716        const abortController = new AbortController();
717        abortController.abort();
718        const intervalIterator = nodeTimersPromises.setInterval(interval, Date.now(), {
719          signal: abortController.signal
720        });
721
722        const first = intervalIterator.next();
723        t.mock.timers.tick(interval);
724
725        await assert.rejects(() => first, {
726          name: 'AbortError',
727        });
728      });
729
730      it('should abort operation given an abort controller signal on a real use case', async (t) => {
731        t.mock.timers.enable(['setInterval']);
732        const controller = new AbortController();
733        const signal = controller.signal;
734        const interval = 200;
735        const expectedIterations = 2;
736        const startedAt = Date.now();
737        const timeResults = [];
738        async function run() {
739          const it = nodeTimersPromises.setInterval(interval, startedAt, { signal });
740          for await (const time of it) {
741            timeResults.push(time);
742            if (timeResults.length === 5) break;
743          }
744        }
745
746        const r = run();
747        t.mock.timers.tick(interval);
748        t.mock.timers.tick(interval);
749        controller.abort();
750        t.mock.timers.tick(interval);
751        t.mock.timers.tick(interval);
752        t.mock.timers.tick(interval);
753        t.mock.timers.tick(interval);
754
755        await assert.rejects(() => r, {
756          name: 'AbortError',
757        });
758        assert.strictEqual(timeResults.length, expectedIterations);
759
760        for (let it = 1; it < expectedIterations; it++) {
761          assert.strictEqual(timeResults[it - 1], startedAt + (interval * it));
762        }
763
764      });
765
766    });
767
768    describe('setImmediate Suite', () => {
769      it('should advance in time and trigger timers when calling the .tick function multiple times', (t, done) => {
770        t.mock.timers.enable(['setImmediate']);
771        const p = nodeTimersPromises.setImmediate();
772
773        t.mock.timers.tick(5555);
774
775        p.then(common.mustCall((result) => {
776          assert.strictEqual(result, undefined);
777          done();
778        }, 1));
779      });
780
781      it('should work with the same params as the original timers/promises/setImmediate', async (t) => {
782        t.mock.timers.enable(['setImmediate']);
783        const expectedResult = 'result';
784        const controller = new AbortController();
785        const p = nodeTimersPromises.setImmediate(expectedResult, {
786          ref: true,
787          signal: controller.signal
788        });
789
790        t.mock.timers.tick(500);
791
792        const result = await p;
793        assert.strictEqual(result, expectedResult);
794      });
795
796      it('should abort operation if timers/promises/setImmediate received an aborted signal', async (t) => {
797        t.mock.timers.enable(['setImmediate']);
798        const expectedResult = 'result';
799        const controller = new AbortController();
800        const p = nodeTimersPromises.setImmediate(expectedResult, {
801          ref: true,
802          signal: controller.signal
803        });
804
805        controller.abort();
806        t.mock.timers.tick(0);
807
808        await assert.rejects(() => p, {
809          name: 'AbortError',
810        });
811
812      });
813      it('should abort operation even if the .tick wasn\'t called', async (t) => {
814        t.mock.timers.enable(['setImmediate']);
815        const expectedResult = 'result';
816        const controller = new AbortController();
817        const p = nodeTimersPromises.setImmediate(expectedResult, {
818          ref: true,
819          signal: controller.signal
820        });
821
822        controller.abort();
823
824        await assert.rejects(() => p, {
825          name: 'AbortError',
826        });
827      });
828
829      it('should abort operation when .abort is called before calling setImmediate', async (t) => {
830        t.mock.timers.enable(['setImmediate']);
831        const expectedResult = 'result';
832        const controller = new AbortController();
833        controller.abort();
834        const p = nodeTimersPromises.setImmediate(expectedResult, {
835          ref: true,
836          signal: controller.signal
837        });
838
839        await assert.rejects(() => p, {
840          name: 'AbortError',
841        });
842
843      });
844
845      it('should reject given an an invalid signal instance', async (t) => {
846        t.mock.timers.enable(['setImmediate']);
847        const expectedResult = 'result';
848        const p = nodeTimersPromises.setImmediate(expectedResult, {
849          ref: true,
850          signal: {}
851        });
852
853        await assert.rejects(() => p, {
854          name: 'TypeError',
855          code: 'ERR_INVALID_ARG_TYPE'
856        });
857
858      });
859
860      it('should execute in order if setImmediate is called multiple times', async (t) => {
861        t.mock.timers.enable(['setImmediate']);
862
863        const p1 = nodeTimersPromises.setImmediate('fn1');
864        const p2 = nodeTimersPromises.setImmediate('fn2');
865
866        t.mock.timers.tick(0);
867
868        const results = await Promise.race([p1, p2]);
869
870        assert.strictEqual(results, 'fn1');
871      });
872    });
873  });
874});
875