4.3 KB145 lines
Blame
1/**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8import {debounce} from '../debounce';
9
10describe('debounce', () => {
11 let func1: jest.Mock<[number, string]>;
12 const BUFFER = 10;
13
14 beforeEach(() => {
15 jest.resetModules();
16 func1 = jest.fn();
17 jest.useFakeTimers();
18 });
19
20 function argsEquivalent(args1: Array<unknown>, args2: Array<unknown>) {
21 for (let i = 0; i < Math.max(args1.length, args2.length); i++) {
22 if (args1[i] != args2[i]) {
23 return false;
24 }
25 }
26 return true;
27 }
28
29 function assertCalledWith(...origargs: Array<unknown>) {
30 const args = [].slice.call(origargs);
31 expect(func1.mock.calls.some(call => argsEquivalent(args, call))).toBeTruthy();
32 }
33
34 it('should not call until the wait is over', () => {
35 const wait = 200;
36 const debounced = debounce(func1, wait);
37 debounced(1, 'a');
38 expect(func1).not.toBeCalled();
39
40 jest.advanceTimersByTime(wait + BUFFER);
41 assertCalledWith(1, 'a');
42
43 // make sure that subsequent function isn't called right away
44 debounced(2, 'a');
45 expect(func1.mock.calls.length).toBe(1);
46 jest.clearAllTimers();
47 });
48
49 it('should only call the last function per batch', () => {
50 const wait = 200;
51 const debounced = debounce(func1, wait);
52 debounced(1, 'a');
53 expect(func1).not.toBeCalled();
54 jest.advanceTimersByTime(100);
55 debounced(2, 'a');
56 jest.advanceTimersByTime(100);
57 debounced(3, 'a');
58 jest.advanceTimersByTime(100);
59 debounced(4, 'a');
60 jest.advanceTimersByTime(100);
61 debounced(5, 'a');
62 expect(jest.getTimerCount()).toBe(1);
63 jest.advanceTimersByTime(wait + BUFFER);
64 assertCalledWith(5, 'a');
65 debounced(6, 'a');
66 debounced(7, 'a');
67 jest.advanceTimersByTime(wait + BUFFER);
68 assertCalledWith(7, 'a');
69 expect(func1.mock.calls.length).toBe(2);
70 });
71
72 it('should be reset-able', () => {
73 const wait = 300;
74 const debounced = debounce(func1, wait);
75 debounced(1, 'a');
76 debounced.reset();
77 expect(jest.getTimerCount()).toBe(0);
78 jest.runAllTimers();
79 expect(func1).not.toBeCalled();
80 });
81
82 it('should correctly show if the timeout is pending', () => {
83 const wait = 300;
84 const debounced = debounce(func1, wait);
85 expect(debounced.isPending()).toBe(false);
86 debounced(1, 'a');
87 debounced(1, 'a');
88 expect(debounced.isPending()).toBe(true);
89 jest.runAllTimers();
90 expect(func1.mock.calls.length).toBe(1);
91 expect(debounced.isPending()).toBe(false);
92 });
93
94 describe('leading', () => {
95 it('should call the function immediately if able', () => {
96 const wait = 300;
97 const debounced = debounce(func1, wait, undefined, true);
98 debounced(1, 'a');
99 expect(func1).toBeCalled();
100 });
101 it('should gate consecutive calls within the wait time', () => {
102 const wait = 300;
103 const debounced = debounce(func1, wait, undefined, true);
104 debounced(1, 'a');
105 debounced(1, 'a');
106 debounced(1, 'a');
107 debounced(1, 'a');
108 debounced(1, 'a');
109 expect(func1).toBeCalledTimes(1);
110 });
111 it('should call the function immediately after the wait time', () => {
112 const wait = 300;
113 const debounced = debounce(func1, wait, undefined, true);
114 debounced(1, 'a');
115 debounced(1, 'a');
116 debounced(1, 'a');
117 debounced(1, 'a');
118 debounced(1, 'a');
119 expect(func1).toBeCalledTimes(1);
120 jest.advanceTimersByTime(wait + BUFFER);
121 debounced(1, 'a');
122 debounced(1, 'a');
123 debounced(1, 'a');
124 debounced(1, 'a');
125 debounced(1, 'a');
126 expect(func1).toBeCalledTimes(2);
127 });
128 it('should extend the wait time whenever it is called within the wait time', () => {
129 const wait = 300;
130 const debounced = debounce(func1, wait, undefined, true);
131 debounced(1, 'a');
132 expect(func1).toBeCalledTimes(1);
133 jest.advanceTimersByTime(wait - BUFFER);
134 debounced(1, 'a');
135 expect(func1).toBeCalledTimes(1);
136 jest.advanceTimersByTime(wait - BUFFER);
137 debounced(1, 'a');
138 expect(func1).toBeCalledTimes(1);
139 jest.advanceTimersByTime(wait + BUFFER);
140 debounced(1, 'a');
141 expect(func1).toBeCalledTimes(2);
142 });
143 });
144});
145