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