@@ -594,6 +594,185 @@ describe('Mock Timers Test Suite', () => {
594
594
} ) ;
595
595
} ) ;
596
596
597
+ describe ( 'scheduler.wait Suite' , ( ) => {
598
+ it ( 'should advance in time and trigger timers when calling the .tick function multiple times' , async ( t ) => {
599
+ t . mock . timers . enable ( { apis : [ 'scheduler.wait' ] } ) ;
600
+ const p = nodeTimersPromises . scheduler . wait ( 2000 ) ;
601
+
602
+ t . mock . timers . tick ( 1000 ) ;
603
+ t . mock . timers . tick ( 500 ) ;
604
+ t . mock . timers . tick ( 500 ) ;
605
+ t . mock . timers . tick ( 500 ) ;
606
+
607
+ p . then ( common . mustCall ( ( result ) => {
608
+ assert . strictEqual ( result , undefined ) ;
609
+ } ) ) ;
610
+ } ) ;
611
+
612
+ it ( 'should work with the same params as the original timers/promises/scheduler/wait' , async ( t ) => {
613
+ t . mock . timers . enable ( { apis : [ 'scheduler.wait' ] } ) ;
614
+ const expectedResult = 'result' ;
615
+ const controller = new AbortController ( ) ;
616
+ const p = nodeTimersPromises . scheduler . wait ( 2000 , expectedResult , {
617
+ ref : true ,
618
+ signal : controller . signal ,
619
+ } ) ;
620
+
621
+ t . mock . timers . tick ( 1000 ) ;
622
+ t . mock . timers . tick ( 500 ) ;
623
+ t . mock . timers . tick ( 500 ) ;
624
+ t . mock . timers . tick ( 500 ) ;
625
+
626
+ const result = await p ;
627
+ assert . strictEqual ( result , expectedResult ) ;
628
+ } ) ;
629
+
630
+ it ( 'should abort operation if timers/promises/scheduler.wait received an aborted signal' , async ( t ) => {
631
+ t . mock . timers . enable ( { apis : [ 'scheduler.wait' ] } ) ;
632
+ const expectedResult = 'result' ;
633
+ const controller = new AbortController ( ) ;
634
+ const p = nodeTimersPromises . scheduler . wait ( 2000 , {
635
+ ref : true ,
636
+ signal : controller . signal ,
637
+ } ) ;
638
+
639
+ t . mock . timers . tick ( 1000 ) ;
640
+ controller . abort ( ) ;
641
+ t . mock . timers . tick ( 500 ) ;
642
+ t . mock . timers . tick ( 500 ) ;
643
+ t . mock . timers . tick ( 500 ) ;
644
+ await assert . rejects ( ( ) => p , {
645
+ name : 'AbortError' ,
646
+ } ) ;
647
+ } ) ;
648
+
649
+
650
+ it ( 'should abort operation even if the .tick was not called' , async ( t ) => {
651
+ t . mock . timers . enable ( { apis : [ 'scheduler.wait' ] } ) ;
652
+ const controller = new AbortController ( ) ;
653
+ const p = nodeTimersPromises . scheduler . wait ( 2000 , {
654
+ ref : true ,
655
+ signal : controller . signal ,
656
+ } ) ;
657
+
658
+ controller . abort ( ) ;
659
+
660
+ await assert . rejects ( ( ) => p , {
661
+ name : 'AbortError' ,
662
+ } ) ;
663
+ } ) ;
664
+
665
+ it ( 'should abort operation when .abort is called before calling setInterval' , async ( t ) => {
666
+ t . mock . timers . enable ( { apis : [ 'setTimeout' ] } ) ;
667
+ const expectedResult = 'result' ;
668
+ const controller = new AbortController ( ) ;
669
+ controller . abort ( ) ;
670
+ const p = nodeTimersPromises . setTimeout ( 2000 , expectedResult , {
671
+ ref : true ,
672
+ signal : controller . signal ,
673
+ } ) ;
674
+
675
+ await assert . rejects ( ( ) => p , {
676
+ name : 'AbortError' ,
677
+ } ) ;
678
+ } ) ;
679
+
680
+ it ( 'should reject given an an invalid signal instance' , async ( t ) => {
681
+ t . mock . timers . enable ( { apis : [ 'scheduler.wait' ] } ) ;
682
+ const p = nodeTimersPromises . scheduler . wait ( 2000 , {
683
+ ref : true ,
684
+ signal : { } ,
685
+ } ) ;
686
+
687
+ await assert . rejects ( ( ) => p , {
688
+ name : 'TypeError' ,
689
+ code : 'ERR_INVALID_ARG_TYPE' ,
690
+ } ) ;
691
+ } ) ;
692
+
693
+ // Test for https://github.com/nodejs/node/issues/50365
694
+ it ( 'should not affect other timers when aborting' , async ( t ) => {
695
+ const f1 = t . mock . fn ( ) ;
696
+ const f2 = t . mock . fn ( ) ;
697
+ t . mock . timers . enable ( { apis : [ 'scheduler.wait' ] } ) ;
698
+ const ac = new AbortController ( ) ;
699
+
700
+ // id 1 & pos 1 in priority queue
701
+ nodeTimersPromises . scheduler . wait ( 100 , { signal : ac . signal } ) . then ( f1 , f1 ) ;
702
+ // id 2 & pos 1 in priority queue (id 1 is moved to pos 2)
703
+ nodeTimersPromises . scheduler . wait ( 50 ) . then ( f2 , f2 ) ;
704
+
705
+ ac . abort ( ) ; // BUG: will remove timer at pos 1 not timer with id 1!
706
+
707
+ t . mock . timers . runAll ( ) ;
708
+ await nodeTimersPromises . setImmediate ( ) ; // let promises settle
709
+
710
+ // First scheduler.wait is aborted
711
+ assert . strictEqual ( f1 . mock . callCount ( ) , 1 ) ;
712
+ assert . strictEqual ( f1 . mock . calls [ 0 ] . arguments [ 0 ] . code , 'ABORT_ERR' ) ;
713
+
714
+ // Second scheduler.wait should resolve, but never settles, because it was eronously removed by ac.abort()
715
+ assert . strictEqual ( f2 . mock . callCount ( ) , 1 ) ;
716
+ } ) ;
717
+
718
+ // Test for https://github.com/nodejs/node/issues/50365
719
+ // it('should not affect other timers when aborted after triggering', async (t) => {
720
+ // const f1 = t.mock.fn();
721
+ // const f2 = t.mock.fn();
722
+ // t.mock.timers.enable({ apis: ['setTimeout'] });
723
+ // const ac = new AbortController();
724
+
725
+ // // id 1 & pos 1 in priority queue
726
+ // nodeTimersPromises.setTimeout(50, true, { signal: ac.signal }).then(f1, f1);
727
+ // // id 2 & pos 2 in priority queue
728
+ // nodeTimersPromises.setTimeout(100).then(f2, f2);
729
+
730
+ // // First setTimeout resolves
731
+ // t.mock.timers.tick(50);
732
+ // await nodeTimersPromises.setImmediate(); // let promises settle
733
+ // assert.strictEqual(f1.mock.callCount(), 1);
734
+ // assert.strictEqual(f1.mock.calls[0].arguments.length, 1);
735
+ // assert.strictEqual(f1.mock.calls[0].arguments[0], true);
736
+
737
+ // // Now timer with id 2 will be at pos 1 in priority queue
738
+ // ac.abort(); // BUG: will remove timer at pos 1 not timer with id 1!
739
+
740
+ // // Second setTimeout should resolve, but never settles, because it was eronously removed by ac.abort()
741
+ // t.mock.timers.runAll();
742
+ // await nodeTimersPromises.setImmediate(); // let promises settle
743
+ // assert.strictEqual(f2.mock.callCount(), 1);
744
+ // });
745
+
746
+ // it('should not affect other timers when clearing timeout inside own callback', (t) => {
747
+ // t.mock.timers.enable({ apis: ['setTimeout'] });
748
+ // const f = t.mock.fn();
749
+
750
+ // const timer = nodeTimers.setTimeout(() => {
751
+ // f();
752
+ // // Clearing the already-expired timeout should do nothing
753
+ // nodeTimers.clearTimeout(timer);
754
+ // }, 50);
755
+ // nodeTimers.setTimeout(f, 50);
756
+ // nodeTimers.setTimeout(f, 50);
757
+
758
+ // t.mock.timers.runAll();
759
+ // assert.strictEqual(f.mock.callCount(), 3);
760
+ // });
761
+
762
+ // it('should allow clearing timeout inside own callback', (t) => {
763
+ // t.mock.timers.enable({ apis: ['setTimeout'] });
764
+ // const f = t.mock.fn();
765
+
766
+ // const timer = nodeTimers.setTimeout(() => {
767
+ // f();
768
+ // nodeTimers.clearTimeout(timer);
769
+ // }, 50);
770
+
771
+ // t.mock.timers.runAll();
772
+ // assert.strictEqual(f.mock.callCount(), 1);
773
+ // });
774
+ } ) ;
775
+
597
776
describe ( 'setInterval Suite' , ( ) => {
598
777
it ( 'should tick three times using fake setInterval' , async ( t ) => {
599
778
t . mock . timers . enable ( { apis : [ 'setInterval' ] } ) ;
0 commit comments