-
Notifications
You must be signed in to change notification settings - Fork 80
/
throttle-test.ts
274 lines (208 loc) · 7.13 KB
/
throttle-test.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
import Backburner from 'backburner';
QUnit.module('tests/throttle');
QUnit.test('throttle', function(assert) {
assert.expect(18);
let bb = new Backburner(['zomg']);
let step = 0;
let done = assert.async();
let wasCalled = false;
function throttler() {
assert.ok(!wasCalled);
wasCalled = true;
}
// let's throttle the function `throttler` for 40ms
// it will be executed in 40ms
bb.throttle(null, throttler, 40, false);
assert.equal(step++, 0);
// let's schedule `throttler` to run in 10ms
setTimeout(() => {
assert.equal(step++, 1);
assert.ok(!wasCalled);
bb.throttle(null, throttler, false);
}, 10);
// let's schedule `throttler` to run again in 20ms
setTimeout(() => {
assert.equal(step++, 2);
assert.ok(!wasCalled);
bb.throttle(null, throttler, false);
}, 20);
// let's schedule `throttler` to run yet again in 30ms
setTimeout(() => {
assert.equal(step++, 3);
assert.ok(!wasCalled);
bb.throttle(null, throttler, false);
}, 30);
// at 40ms, `throttler` will get called once
// now, let's schedule an assertion to occur at 50ms,
// 10ms after `throttler` has been called
setTimeout(() => {
assert.equal(step++, 4);
assert.ok(wasCalled);
}, 50);
// great, we've made it this far, there's one more thing
// we need to test. we want to make sure we can call `throttle`
// again with the same target/method after it has executed
// at the 60ms mark, let's schedule another call to `throttle`
setTimeout(() => {
wasCalled = false; // reset the flag
// assert call order
assert.equal(step++, 5);
// call throttle for the second time
bb.throttle(null, throttler, 100, false);
// assert that it is called in the future and not blackholed
setTimeout(() => {
assert.equal(step++, 6);
assert.ok(wasCalled, 'Another throttle call with the same function can be executed later');
}, 110);
}, 60);
setTimeout(() => {
wasCalled = false; // reset the flag
// assert call order
assert.equal(step++, 7);
// call throttle again that time using a string number like time interval
bb.throttle(null, throttler, '100', false);
// assert that it is called in the future and not blackholed
setTimeout(() => {
assert.equal(step++, 8);
assert.ok(wasCalled, 'Throttle accept a string number like time interval');
done();
}, 110);
}, 180);
});
QUnit.test('throttle with cancelTimers', function(assert) {
assert.expect(1);
let count = 0;
let bb = new Backburner(['zomg']);
// Throttle a no-op 10ms
bb.throttle(null, () => { /* no-op */ }, 10, false);
try {
bb.cancelTimers();
} catch (e) {
count++;
}
assert.equal(count, 0, 'calling cancelTimers while something is being throttled does not throw an error');
});
QUnit.test('throttled function is called with final argument', function(assert) {
assert.expect(1);
let done = assert.async();
let count = 0;
let bb = new Backburner(['zomg']);
function throttled(arg) {
assert.equal(arg, 'bus');
done();
}
bb.throttle(null, throttled, 'car' , 10, false);
bb.throttle(null, throttled, 'bicycle' , 10, false);
bb.throttle(null, throttled, 'bus' , 10, false);
});
QUnit.test('throttle leading edge', function(assert) {
assert.expect(10);
let bb = new Backburner(['zerg']);
let throttle;
let throttle2;
let wasCalled = false;
let done = assert.async();
function throttler() {
assert.ok(!wasCalled, 'throttler hasn\'t been called yet');
wasCalled = true;
}
// let's throttle the function `throttler` for 40ms
// it will be executed immediately, but throttled for the future hits
throttle = bb.throttle(null, throttler, 40);
assert.ok(wasCalled, 'function was executed immediately');
wasCalled = false;
// let's schedule `throttler` to run again, it shouldn't be allowed to queue for another 40 msec
throttle2 = bb.throttle(null, throttler, 40);
assert.equal(throttle, throttle2, 'No new throttle was inserted, returns old throttle');
setTimeout(() => {
assert.ok(!wasCalled, 'attempt to call throttle again didn\'t happen');
throttle = bb.throttle(null, throttler, 40);
assert.ok(wasCalled, 'newly inserted throttle after timeout functioned');
assert.ok(bb.cancel(throttle), 'wait time of throttle was cancelled');
wasCalled = false;
throttle2 = bb.throttle(null, throttler, 40);
assert.notEqual(throttle, throttle2, 'the throttle is different');
assert.ok(wasCalled, 'throttle was inserted and run immediately after cancel');
done();
}, 60);
});
QUnit.test('throttle returns timer information usable for cancelling', function(assert) {
assert.expect(3);
let done = assert.async();
let bb = new Backburner(['batman']);
let wasCalled = false;
function throttler() {
assert.ok(false, 'this method shouldn\'t be called');
wasCalled = true;
}
let timer = bb.throttle(null, throttler, 1, false);
assert.ok(bb.cancel(timer), 'the timer is cancelled');
// should return false second time around
assert.ok(!bb.cancel(timer), 'the timer no longer exists in the list');
setTimeout(() => {
assert.ok(!wasCalled, 'the timer wasn\'t called after waiting');
done();
}, 60);
});
QUnit.test('throttler cancel after it\'s executed returns false', function(assert) {
assert.expect(3);
let bb = new Backburner(['darkknight']);
let done = assert.async();
let wasCalled = false;
function throttler() {
assert.ok(true, 'the throttled method was called');
wasCalled = true;
}
let timer = bb.throttle(null, throttler, 1);
setTimeout(() => {
assert.ok(!bb.cancel(timer), 'no timer existed to cancel');
assert.ok(wasCalled, 'the timer was actually called');
done();
}, 10);
});
QUnit.test('throttler returns the appropriate timer to cancel if the old item still exists', function(assert) {
assert.expect(5);
let bb = new Backburner(['robin']);
let wasCalled = false;
let done = assert.async();
function throttler() {
assert.ok(true, 'the throttled method was called');
wasCalled = true;
}
let timer = bb.throttle(null, throttler, 1);
let timer2 = bb.throttle(null, throttler, 1);
assert.deepEqual(timer, timer2, 'the same timer was returned');
setTimeout(() => {
bb.throttle(null, throttler, 1);
assert.ok(!bb.cancel(timer), 'the second timer isn\'t removed, despite appearing to be the same item');
assert.ok(wasCalled, 'the timer was actually called');
done();
}, 10);
});
QUnit.test('onError', function(assert) {
assert.expect(1);
function onError(error) {
assert.equal('test error', error.message);
}
let bb = new Backburner(['errors'], {
onError: onError
});
bb.throttle(null, () => {
throw new Error('test error');
}, 20);
});
QUnit.test('throttle + immediate joins existing run loop instances', function(assert) {
assert.expect(1);
function onError(error) {
assert.equal('test error', error.message);
}
let bb = new Backburner(['errors'], {
onError: onError
});
bb.run(() => {
let parentInstance = bb.currentInstance;
bb.throttle(null, () => {
assert.equal(bb.currentInstance, parentInstance);
}, 20, true);
});
});