1 import { renderHook } from '@testing-library/react-hooks';
3 import useInterval from './useInterval';
5 describe('useInterval', () => {
6 let callback: jest.Mock<any, any>;
7 let setInterval: jest.SpyInstance<any, any>;
8 let clearInterval: jest.SpyInstance<any, any>;
12 setInterval = jest.spyOn(window, 'setInterval');
13 clearInterval = jest.spyOn(window, 'clearInterval');
21 callback.mockRestore();
22 jest.clearAllTimers();
29 it('should init hook with no delay', () => {
30 const { result } = renderHook(() => useInterval(callback, null));
32 const value = result.current;
34 expect(value).toBeUndefined();
35 // if null delay provided, it's assumed as no delay
36 expect(setInterval).not.toHaveBeenCalled();
39 it('should set pass delay to setInterval', () => {
41 const { result } = renderHook(() => useInterval(callback, delay));
43 const value = result.current;
45 expect(value).toBeUndefined();
46 expect(setInterval).toHaveBeenCalledTimes(1);
47 expect(setInterval).toHaveBeenCalledWith(expect.any(Function), delay);
50 it('should repeatedly calls provided callback with a fixed time delay between each call', () => {
51 renderHook(() => useInterval(callback, 200));
52 expect(callback).not.toHaveBeenCalled();
54 // fast-forward time until 1 millisecond before it should be executed
55 jest.advanceTimersByTime(199);
56 expect(callback).not.toHaveBeenCalled();
58 // fast-forward until 1st call should be executed
59 jest.advanceTimersByTime(1);
60 expect(callback).toHaveBeenCalledTimes(1);
62 // fast-forward until next timer should be executed
63 jest.advanceTimersToNextTimer();
64 expect(callback).toHaveBeenCalledTimes(2);
66 // fast-forward until 3 more timers should be executed
67 jest.advanceTimersToNextTimer(3);
68 expect(callback).toHaveBeenCalledTimes(5);
71 it('should clear interval on unmount', () => {
72 const { unmount } = renderHook(() => useInterval(callback, 200));
73 const initialTimerCount = jest.getTimerCount();
74 expect(clearInterval).not.toHaveBeenCalled();
78 expect(clearInterval).toHaveBeenCalledTimes(1);
79 expect(jest.getTimerCount()).toBe(initialTimerCount - 1);
82 it('should handle new interval when delay is updated', () => {
84 const { rerender } = renderHook(() => useInterval(callback, delay));
85 expect(callback).not.toHaveBeenCalled();
87 // fast-forward initial delay
88 jest.advanceTimersByTime(200);
89 expect(callback).toHaveBeenCalledTimes(1);
91 // update delay by increasing previous one
95 // fast-forward initial delay again but this time it should not execute the cb
96 jest.advanceTimersByTime(200);
97 expect(callback).toHaveBeenCalledTimes(1);
99 // fast-forward remaining time for new delay
100 jest.advanceTimersByTime(300);
101 expect(callback).toHaveBeenCalledTimes(2);
104 it('should clear pending interval when delay is updated', () => {
106 const { rerender } = renderHook(() => useInterval(callback, delay));
107 expect(clearInterval).not.toHaveBeenCalled();
108 const initialTimerCount = jest.getTimerCount();
110 // update delay while there is a pending interval
114 expect(clearInterval).toHaveBeenCalledTimes(1);
115 expect(jest.getTimerCount()).toBe(initialTimerCount);