@@ -811,6 +811,202 @@ describe('FakeTimers', () => {
811
811
} )
812
812
} )
813
813
814
+ describe ( 'advanceTimersToNextFrame' , ( ) => {
815
+ it ( 'runs scheduled animation frame callbacks in order' , ( ) => {
816
+ const global = {
817
+ Date,
818
+ clearTimeout,
819
+ process,
820
+ requestAnimationFrame : ( ) => - 1 ,
821
+ setTimeout,
822
+ } as unknown as typeof globalThis
823
+
824
+ const timers = new FakeTimers ( { global } )
825
+ timers . useFakeTimers ( )
826
+
827
+ const runOrder : Array < string > = [ ]
828
+ const mock1 = vi . fn ( ( ) => runOrder . push ( 'mock1' ) )
829
+ const mock2 = vi . fn ( ( ) => runOrder . push ( 'mock2' ) )
830
+ const mock3 = vi . fn ( ( ) => runOrder . push ( 'mock3' ) )
831
+
832
+ global . requestAnimationFrame ( mock1 )
833
+ global . requestAnimationFrame ( mock2 )
834
+ global . requestAnimationFrame ( mock3 )
835
+
836
+ timers . advanceTimersToNextFrame ( )
837
+
838
+ expect ( runOrder ) . toEqual ( [ 'mock1' , 'mock2' , 'mock3' ] )
839
+ } )
840
+
841
+ it ( 'should only run currently scheduled animation frame callbacks' , ( ) => {
842
+ const global = {
843
+ Date,
844
+ clearTimeout,
845
+ process,
846
+ requestAnimationFrame : ( ) => - 1 ,
847
+ setTimeout,
848
+ } as unknown as typeof globalThis
849
+
850
+ const timers = new FakeTimers ( { global } )
851
+ timers . useFakeTimers ( )
852
+
853
+ const runOrder : Array < string > = [ ]
854
+ function run ( ) {
855
+ runOrder . push ( 'first-frame' )
856
+
857
+ // scheduling another animation frame in the first frame
858
+ global . requestAnimationFrame ( ( ) => runOrder . push ( 'second-frame' ) )
859
+ }
860
+
861
+ global . requestAnimationFrame ( run )
862
+
863
+ // only the first frame should be executed
864
+ timers . advanceTimersToNextFrame ( )
865
+
866
+ expect ( runOrder ) . toEqual ( [ 'first-frame' ] )
867
+
868
+ timers . advanceTimersToNextFrame ( )
869
+
870
+ expect ( runOrder ) . toEqual ( [ 'first-frame' , 'second-frame' ] )
871
+ } )
872
+
873
+ it ( 'should allow cancelling of scheduled animation frame callbacks' , ( ) => {
874
+ const global = {
875
+ Date,
876
+ cancelAnimationFrame : ( ) => { } ,
877
+ clearTimeout,
878
+ process,
879
+ requestAnimationFrame : ( ) => - 1 ,
880
+ setTimeout,
881
+ } as unknown as typeof globalThis
882
+
883
+ const timers = new FakeTimers ( { global } )
884
+ const callback = vi . fn ( )
885
+ timers . useFakeTimers ( )
886
+
887
+ const timerId = global . requestAnimationFrame ( callback )
888
+ global . cancelAnimationFrame ( timerId )
889
+
890
+ timers . advanceTimersToNextFrame ( )
891
+
892
+ expect ( callback ) . not . toHaveBeenCalled ( )
893
+ } )
894
+
895
+ it ( 'should only advance as much time is needed to get to the next frame' , ( ) => {
896
+ const global = {
897
+ Date,
898
+ cancelAnimationFrame : ( ) => { } ,
899
+ clearTimeout,
900
+ process,
901
+ requestAnimationFrame : ( ) => - 1 ,
902
+ setTimeout,
903
+ } as unknown as typeof globalThis
904
+
905
+ const timers = new FakeTimers ( { global } )
906
+ timers . useFakeTimers ( )
907
+
908
+ const runOrder : Array < string > = [ ]
909
+ const start = global . Date . now ( )
910
+
911
+ const callback = ( ) => runOrder . push ( 'frame' )
912
+ global . requestAnimationFrame ( callback )
913
+
914
+ // Advancing timers less than a frame (which is 16ms)
915
+ timers . advanceTimersByTime ( 6 )
916
+ expect ( global . Date . now ( ) ) . toEqual ( start + 6 )
917
+
918
+ // frame not yet executed
919
+ expect ( runOrder ) . toEqual ( [ ] )
920
+
921
+ // move timers forward to execute frame
922
+ timers . advanceTimersToNextFrame ( )
923
+
924
+ // frame has executed as time has moved forward 10ms to get to the 16ms frame time
925
+ expect ( runOrder ) . toEqual ( [ 'frame' ] )
926
+ expect ( global . Date . now ( ) ) . toEqual ( start + 16 )
927
+ } )
928
+
929
+ it ( 'should execute any timers on the way to the animation frame' , ( ) => {
930
+ const global = {
931
+ Date,
932
+ cancelAnimationFrame : ( ) => { } ,
933
+ clearTimeout,
934
+ process,
935
+ requestAnimationFrame : ( ) => - 1 ,
936
+ setTimeout,
937
+ } as unknown as typeof globalThis
938
+
939
+ const timers = new FakeTimers ( { global } )
940
+ timers . useFakeTimers ( )
941
+
942
+ const runOrder : Array < string > = [ ]
943
+
944
+ global . requestAnimationFrame ( ( ) => runOrder . push ( 'frame' ) )
945
+
946
+ // scheduling a timeout that will be executed on the way to the frame
947
+ global . setTimeout ( ( ) => runOrder . push ( 'timeout' ) , 10 )
948
+
949
+ // move timers forward to execute frame
950
+ timers . advanceTimersToNextFrame ( )
951
+
952
+ expect ( runOrder ) . toEqual ( [ 'timeout' , 'frame' ] )
953
+ } )
954
+
955
+ it ( 'should not execute any timers scheduled inside of an animation frame callback' , ( ) => {
956
+ const global = {
957
+ Date,
958
+ cancelAnimationFrame : ( ) => { } ,
959
+ clearTimeout,
960
+ process,
961
+ requestAnimationFrame : ( ) => - 1 ,
962
+ setTimeout,
963
+ } as unknown as typeof globalThis
964
+
965
+ const timers = new FakeTimers ( { global } )
966
+ timers . useFakeTimers ( )
967
+
968
+ const runOrder : Array < string > = [ ]
969
+
970
+ global . requestAnimationFrame ( ( ) => {
971
+ runOrder . push ( 'frame' )
972
+ // scheduling a timer inside of a frame
973
+ global . setTimeout ( ( ) => runOrder . push ( 'timeout' ) , 1 )
974
+ } )
975
+
976
+ timers . advanceTimersToNextFrame ( )
977
+
978
+ // timeout not yet executed
979
+ expect ( runOrder ) . toEqual ( [ 'frame' ] )
980
+
981
+ // validating that the timer will still be executed
982
+ timers . advanceTimersByTime ( 1 )
983
+ expect ( runOrder ) . toEqual ( [ 'frame' , 'timeout' ] )
984
+ } )
985
+
986
+ it ( 'should call animation frame callbacks with the latest system time' , ( ) => {
987
+ const global = {
988
+ Date,
989
+ clearTimeout,
990
+ performance,
991
+ process,
992
+ requestAnimationFrame : ( ) => - 1 ,
993
+ setTimeout,
994
+ } as unknown as typeof globalThis
995
+
996
+ const timers = new FakeTimers ( { global } )
997
+ timers . useFakeTimers ( )
998
+
999
+ const callback = vi . fn ( )
1000
+
1001
+ global . requestAnimationFrame ( callback )
1002
+
1003
+ timers . advanceTimersToNextFrame ( )
1004
+
1005
+ // `requestAnimationFrame` callbacks are called with a `DOMHighResTimeStamp`
1006
+ expect ( callback ) . toHaveBeenCalledWith ( global . performance . now ( ) )
1007
+ } )
1008
+ } )
1009
+
814
1010
describe ( 'reset' , ( ) => {
815
1011
it ( 'resets all pending setTimeouts' , ( ) => {
816
1012
const global = { Date : FakeDate , clearTimeout, process, setTimeout }
0 commit comments