17
17
import HTTPPollingDatafileManager from '../src/httpPollingDatafileManager'
18
18
import { Headers , AbortableRequest , Response } from '../src/http'
19
19
import { DatafileManagerConfig } from '../src/datafileManager' ;
20
- import TestTimeoutFactory from './testTimeoutFactory '
20
+ import { advanceTimersByTime , getTimerCount } from './testUtils '
21
21
22
22
jest . mock ( '../src/backoffController' , ( ) => {
23
23
return jest . fn ( ) . mockImplementation ( ( ) => {
@@ -59,29 +59,23 @@ class TestDatafileManager extends HTTPPollingDatafileManager {
59
59
}
60
60
61
61
describe ( 'httpPollingDatafileManager' , ( ) => {
62
- const testTimeoutFactory : TestTimeoutFactory = new TestTimeoutFactory ( )
63
-
64
- function createTestManager ( config : DatafileManagerConfig ) : TestDatafileManager {
65
- return new TestDatafileManager ( {
66
- ...config ,
67
- timeoutFactory : testTimeoutFactory
68
- } )
69
- }
62
+ beforeEach ( ( ) => {
63
+ jest . useFakeTimers ( )
64
+ } )
70
65
71
66
let manager : TestDatafileManager
72
67
afterEach ( async ( ) => {
73
- testTimeoutFactory . cleanup ( )
74
-
75
68
if ( manager ) {
76
69
manager . stop ( )
77
70
}
78
71
jest . clearAllMocks ( )
79
72
jest . restoreAllMocks ( )
73
+ jest . clearAllTimers ( )
80
74
} )
81
75
82
76
describe ( 'when constructed with sdkKey and datafile and autoUpdate: true,' , ( ) => {
83
77
beforeEach ( ( ) => {
84
- manager = createTestManager ( { datafile : { foo : 'abcd' } , sdkKey : '123' , autoUpdate : true } )
78
+ manager = new TestDatafileManager ( { datafile : { foo : 'abcd' } , sdkKey : '123' , autoUpdate : true } )
85
79
} )
86
80
87
81
it ( 'returns the passed datafile from get' , ( ) => {
@@ -118,7 +112,9 @@ describe('httpPollingDatafileManager', () => {
118
112
} )
119
113
expect ( manager . get ( ) ) . toEqual ( { foo : 'bar' } )
120
114
updateFn . mockReset ( )
121
- testTimeoutFactory . timeoutFns [ 0 ] ( )
115
+
116
+ await advanceTimersByTime ( 300000 )
117
+
122
118
expect ( manager . responsePromises . length ) . toBe ( 2 )
123
119
await manager . responsePromises [ 1 ]
124
120
expect ( updateFn ) . toBeCalledTimes ( 1 )
@@ -131,7 +127,7 @@ describe('httpPollingDatafileManager', () => {
131
127
132
128
describe ( 'when constructed with sdkKey and datafile and autoUpdate: false,' , ( ) => {
133
129
beforeEach ( ( ) => {
134
- manager = createTestManager ( { datafile : { foo : 'abcd' } , sdkKey : '123' , autoUpdate : false } )
130
+ manager = new TestDatafileManager ( { datafile : { foo : 'abcd' } , sdkKey : '123' , autoUpdate : false } )
135
131
} )
136
132
137
133
it ( 'returns the passed datafile from get' , ( ) => {
@@ -160,13 +156,13 @@ describe('httpPollingDatafileManager', () => {
160
156
datafile : { foo : 'bar' }
161
157
} )
162
158
expect ( manager . get ( ) ) . toEqual ( { foo : 'bar' } )
163
- expect ( testTimeoutFactory . timeoutFns . length ) . toBe ( 0 )
159
+ expect ( getTimerCount ( ) ) . toBe ( 0 )
164
160
} )
165
161
} )
166
162
167
163
describe ( 'when constructed with sdkKey and autoUpdate: true' , ( ) => {
168
164
beforeEach ( ( ) => {
169
- manager = createTestManager ( { sdkKey : '123' , updateInterval : 1000 , autoUpdate : true } )
165
+ manager = new TestDatafileManager ( { sdkKey : '123' , updateInterval : 1000 , autoUpdate : true } )
170
166
} )
171
167
172
168
describe ( 'initial state' , ( ) => {
@@ -215,22 +211,32 @@ describe('httpPollingDatafileManager', () => {
215
211
)
216
212
manager . start ( )
217
213
await manager . onReady ( )
218
- testTimeoutFactory . timeoutFns [ 0 ] ( )
214
+ await advanceTimersByTime ( 1000 )
215
+ expect ( manager . responsePromises . length ) . toBe ( 2 )
219
216
await manager . responsePromises [ 1 ]
220
217
expect ( manager . get ( ) ) . toEqual ( { foo : 'bar' } )
221
218
} )
222
219
223
220
describe ( 'live updates' , ( ) => {
224
- it ( 'passes the update interval to its timeoutFactory setTimeout method' , ( ) => {
225
- manager . queuedResponses . push ( {
226
- statusCode : 200 ,
227
- body : '{"foo3": "bar3"}' ,
228
- headers : { } ,
229
- } )
230
- const setTimeoutSpy : jest . SpyInstance < ( ) => void , [ ( ) => void , number ] > = jest . spyOn ( testTimeoutFactory , 'setTimeout' )
221
+ it ( 'sets a timeout to update again after the update interval' , async ( ) => {
222
+ manager . queuedResponses . push (
223
+ {
224
+ statusCode : 200 ,
225
+ body : '{"foo3": "bar3"}' ,
226
+ headers : { } ,
227
+ } ,
228
+ {
229
+ statusCode : 200 ,
230
+ body : '{"foo4": "bar4"}' ,
231
+ headers : { } ,
232
+ } ,
233
+ )
234
+ const makeGetRequestSpy = jest . spyOn ( manager , 'makeGetRequest' )
231
235
manager . start ( )
232
- expect ( setTimeoutSpy ) . toBeCalledTimes ( 1 )
233
- expect ( setTimeoutSpy . mock . calls [ 0 ] [ 1 ] ) . toBe ( 1000 )
236
+ expect ( makeGetRequestSpy ) . toBeCalledTimes ( 1 )
237
+ await manager . responsePromises [ 0 ]
238
+ await advanceTimersByTime ( 1000 )
239
+ expect ( makeGetRequestSpy ) . toBeCalledTimes ( 2 )
234
240
} )
235
241
236
242
it ( 'emits update events after live updates' , async ( ) => {
@@ -260,15 +266,15 @@ describe('httpPollingDatafileManager', () => {
260
266
expect ( manager . get ( ) ) . toEqual ( { foo : 'bar' } )
261
267
expect ( updateFn ) . toBeCalledTimes ( 0 )
262
268
263
- testTimeoutFactory . timeoutFns [ 0 ] ( )
269
+ await advanceTimersByTime ( 1000 )
264
270
await manager . responsePromises [ 1 ]
265
271
expect ( updateFn ) . toBeCalledTimes ( 1 )
266
272
expect ( updateFn . mock . calls [ 0 ] [ 0 ] ) . toEqual ( { datafile : { foo2 : 'bar2' } } )
267
273
expect ( manager . get ( ) ) . toEqual ( { foo2 : 'bar2' } )
268
274
269
275
updateFn . mockReset ( )
270
276
271
- testTimeoutFactory . timeoutFns [ 1 ] ( )
277
+ await advanceTimersByTime ( 1000 )
272
278
await manager . responsePromises [ 2 ]
273
279
expect ( updateFn ) . toBeCalledTimes ( 1 )
274
280
expect ( updateFn . mock . calls [ 0 ] [ 0 ] ) . toEqual ( { datafile : { foo3 : 'bar3' } } )
@@ -285,13 +291,11 @@ describe('httpPollingDatafileManager', () => {
285
291
abort ( ) { } ,
286
292
responsePromise,
287
293
} )
288
- const setTimeoutSpy = jest . spyOn ( testTimeoutFactory , 'setTimeout' )
289
294
290
295
manager . start ( )
291
- expect ( setTimeoutSpy ) . toBeCalledTimes ( 1 )
292
296
expect ( makeGetRequestSpy ) . toBeCalledTimes ( 1 )
293
297
294
- testTimeoutFactory . timeoutFns [ 0 ] ( )
298
+ await advanceTimersByTime ( 1000 )
295
299
expect ( makeGetRequestSpy ) . toBeCalledTimes ( 1 )
296
300
297
301
resolveResponsePromise ! ( {
@@ -301,7 +305,6 @@ describe('httpPollingDatafileManager', () => {
301
305
} )
302
306
await responsePromise
303
307
expect ( makeGetRequestSpy ) . toBeCalledTimes ( 2 )
304
- expect ( setTimeoutSpy ) . toBeCalledTimes ( 2 )
305
308
} )
306
309
} )
307
310
@@ -317,10 +320,9 @@ describe('httpPollingDatafileManager', () => {
317
320
manager . start ( )
318
321
await manager . onReady ( )
319
322
320
- expect ( testTimeoutFactory . timeoutFns . length ) . toBe ( 1 )
321
- expect ( testTimeoutFactory . cancelFns . length ) . toBe ( 1 )
323
+ expect ( getTimerCount ( ) ) . toBe ( 1 )
322
324
manager . stop ( )
323
- expect ( testTimeoutFactory . cancelFns [ 0 ] ) . toBeCalledTimes ( 1 )
325
+ expect ( getTimerCount ( ) ) . toBe ( 0 )
324
326
} )
325
327
326
328
it ( 'cancels reactions to a pending fetch when stop is called' , async ( ) => {
@@ -340,7 +342,9 @@ describe('httpPollingDatafileManager', () => {
340
342
manager . start ( )
341
343
await manager . onReady ( )
342
344
expect ( manager . get ( ) ) . toEqual ( { foo : 'bar' } )
343
- testTimeoutFactory . timeoutFns [ 0 ] ( )
345
+
346
+ advanceTimersByTime ( 1000 )
347
+
344
348
expect ( manager . responsePromises . length ) . toBe ( 2 )
345
349
manager . stop ( )
346
350
await manager . responsePromises [ 1 ]
@@ -383,9 +387,9 @@ describe('httpPollingDatafileManager', () => {
383
387
expect ( manager . responsePromises . length ) . toBe ( 1 )
384
388
await manager . responsePromises [ 0 ]
385
389
// Not ready yet due to first request failed, but should have queued a live update
386
- expect ( testTimeoutFactory . timeoutFns . length ) . toBe ( 1 )
390
+ expect ( getTimerCount ( ) ) . toBe ( 1 )
387
391
// Trigger the update, should fetch the next response which should succeed, then we get ready
388
- testTimeoutFactory . timeoutFns [ 0 ] ( )
392
+ advanceTimersByTime ( 1000 )
389
393
await manager . onReady ( )
390
394
expect ( manager . get ( ) ) . toEqual ( { foo : 'bar' } )
391
395
} )
@@ -416,7 +420,7 @@ describe('httpPollingDatafileManager', () => {
416
420
// First response promise was for the initial 200 response
417
421
expect ( manager . responsePromises . length ) . toBe ( 1 )
418
422
// Trigger the queued update
419
- testTimeoutFactory . timeoutFns [ 0 ] ( )
423
+ advanceTimersByTime ( 1000 )
420
424
// Second response promise is for the 304 response
421
425
expect ( manager . responsePromises . length ) . toBe ( 2 )
422
426
await manager . responsePromises [ 1 ]
@@ -443,7 +447,7 @@ describe('httpPollingDatafileManager', () => {
443
447
manager . start ( )
444
448
await manager . onReady ( )
445
449
const makeGetRequestSpy = jest . spyOn ( manager , 'makeGetRequest' )
446
- testTimeoutFactory . timeoutFns [ 0 ] ( )
450
+ advanceTimersByTime ( 1000 )
447
451
expect ( makeGetRequestSpy ) . toBeCalledTimes ( 1 )
448
452
const firstCall = makeGetRequestSpy . mock . calls [ 0 ]
449
453
const headers = firstCall [ 1 ]
@@ -458,7 +462,9 @@ describe('httpPollingDatafileManager', () => {
458
462
const BackoffControllerMock = ( BackoffController as unknown ) as jest . Mock < BackoffController , [ ] >
459
463
const getDelayMock = BackoffControllerMock . mock . results [ 0 ] . value . getDelay
460
464
getDelayMock . mockImplementationOnce ( ( ) => 5432 )
461
- const setTimeoutSpy = jest . spyOn ( testTimeoutFactory , 'setTimeout' )
465
+
466
+ const makeGetRequestSpy = jest . spyOn ( manager , 'makeGetRequest' )
467
+
462
468
manager . queuedResponses . push (
463
469
{
464
470
statusCode : 404 ,
@@ -468,8 +474,15 @@ describe('httpPollingDatafileManager', () => {
468
474
)
469
475
manager . start ( )
470
476
await manager . responsePromises [ 0 ]
471
- expect ( setTimeoutSpy ) . toBeCalledTimes ( 1 )
472
- expect ( setTimeoutSpy . mock . calls [ 0 ] [ 1 ] ) . toBe ( 5432 )
477
+ expect ( makeGetRequestSpy ) . toBeCalledTimes ( 1 )
478
+
479
+ // Should not make another request after 1 second because the error should have triggered backoff
480
+ advanceTimersByTime ( 1000 )
481
+ expect ( makeGetRequestSpy ) . toBeCalledTimes ( 1 )
482
+
483
+ // But after another 5 seconds, another request should be made
484
+ advanceTimersByTime ( 5000 )
485
+ expect ( makeGetRequestSpy ) . toBeCalledTimes ( 2 )
473
486
} )
474
487
475
488
it ( 'calls countError on the backoff controller when a non-success status code response is received' , async ( ) => {
@@ -531,7 +544,7 @@ describe('httpPollingDatafileManager', () => {
531
544
532
545
describe ( 'when constructed with sdkKey and autoUpdate: false' , ( ) => {
533
546
beforeEach ( ( ) => {
534
- manager = createTestManager ( { sdkKey : '123' , autoUpdate : false } )
547
+ manager = new TestDatafileManager ( { sdkKey : '123' , autoUpdate : false } )
535
548
} )
536
549
537
550
it ( 'after being started, fetches the datafile and resolves onReady' , async ( ) => {
@@ -555,7 +568,7 @@ describe('httpPollingDatafileManager', () => {
555
568
manager . on ( 'update' , updateFn )
556
569
manager . start ( )
557
570
await manager . onReady ( )
558
- expect ( testTimeoutFactory . timeoutFns . length ) . toBe ( 0 )
571
+ expect ( getTimerCount ( ) ) . toBe ( 0 )
559
572
} )
560
573
561
574
// TODO: figure out what's wrong with this test
@@ -579,7 +592,7 @@ describe('httpPollingDatafileManager', () => {
579
592
580
593
describe ( 'when constructed with sdkKey and a valid urlTemplate' , ( ) => {
581
594
beforeEach ( ( ) => {
582
- manager = createTestManager ( {
595
+ manager = new TestDatafileManager ( {
583
596
sdkKey : '456' ,
584
597
updateInterval : 1000 ,
585
598
urlTemplate : 'https://localhost:5556/datafiles/%s' ,
@@ -602,22 +615,23 @@ describe('httpPollingDatafileManager', () => {
602
615
603
616
describe ( 'when constructed with an update interval below the minimum' , ( ) => {
604
617
beforeEach ( ( ) => {
605
- manager = createTestManager ( { sdkKey : '123' , updateInterval : 500 , autoUpdate : true } )
618
+ manager = new TestDatafileManager ( { sdkKey : '123' , updateInterval : 500 , autoUpdate : true } )
606
619
} )
607
620
608
621
it ( 'uses the default update interval' , async ( ) => {
622
+ const makeGetRequestSpy = jest . spyOn ( manager , 'makeGetRequest' )
623
+
609
624
manager . queuedResponses . push ( {
610
625
statusCode : 200 ,
611
626
body : '{"foo3": "bar3"}' ,
612
627
headers : { } ,
613
628
} )
614
629
615
- const setTimeoutSpy : jest . SpyInstance < ( ) => void , [ ( ) => void , number ] > = jest . spyOn ( testTimeoutFactory , 'setTimeout' )
616
-
617
630
manager . start ( )
618
631
await manager . onReady ( )
619
- expect ( setTimeoutSpy ) . toBeCalledTimes ( 1 )
620
- expect ( setTimeoutSpy . mock . calls [ 0 ] [ 1 ] ) . toBe ( 300000 )
632
+ expect ( makeGetRequestSpy ) . toBeCalledTimes ( 1 )
633
+ await advanceTimersByTime ( 300000 )
634
+ expect ( makeGetRequestSpy ) . toBeCalledTimes ( 2 )
621
635
} )
622
636
} )
623
637
} )
0 commit comments