@@ -20,14 +20,15 @@ import '../test/setup';
20
20
import {
21
21
countBytes ,
22
22
HeartbeatServiceImpl ,
23
- extractHeartbeatsForHeader
23
+ extractHeartbeatsForHeader ,
24
+ getEarliestHeartbeatIdx
24
25
} from './heartbeatService' ;
25
26
import {
26
27
Component ,
27
28
ComponentType ,
28
29
ComponentContainer
29
30
} from '@firebase/component' ;
30
- import { PlatformLoggerService } from './types' ;
31
+ import { PlatformLoggerService , SingleDateHeartbeat } from './types' ;
31
32
import { FirebaseApp } from './public-types' ;
32
33
import * as firebaseUtil from '@firebase/util' ;
33
34
import { SinonStub , stub , useFakeTimers } from 'sinon' ;
@@ -173,7 +174,6 @@ describe('HeartbeatServiceImpl', () => {
173
174
let writeStub : SinonStub ;
174
175
let userAgentString = USER_AGENT_STRING_1 ;
175
176
const mockIndexedDBHeartbeats = [
176
- // Chosen so one will exceed 30 day limit and one will not.
177
177
{
178
178
agent : 'old-user-agent' ,
179
179
date : '1969-12-01'
@@ -236,15 +236,14 @@ describe('HeartbeatServiceImpl', () => {
236
236
} ) ;
237
237
}
238
238
} ) ;
239
- it ( `triggerHeartbeat() writes new heartbeats and retains old ones newer than 30 days ` , async ( ) => {
239
+ it ( `triggerHeartbeat() writes new heartbeats and retains old ones` , async ( ) => {
240
240
userAgentString = USER_AGENT_STRING_2 ;
241
241
clock . tick ( 3 * 24 * 60 * 60 * 1000 ) ;
242
242
await heartbeatService . triggerHeartbeat ( ) ;
243
243
if ( firebaseUtil . isIndexedDBAvailable ( ) ) {
244
244
expect ( writeStub ) . to . be . calledWith ( {
245
245
heartbeats : [
246
- // The first entry exceeds the 30 day retention limit.
247
- mockIndexedDBHeartbeats [ 1 ] ,
246
+ ...mockIndexedDBHeartbeats ,
248
247
{ agent : USER_AGENT_STRING_2 , date : '1970-01-04' }
249
248
]
250
249
} ) ;
@@ -260,6 +259,7 @@ describe('HeartbeatServiceImpl', () => {
260
259
) ;
261
260
if ( firebaseUtil . isIndexedDBAvailable ( ) ) {
262
261
expect ( heartbeatHeaders ) . to . include ( 'old-user-agent' ) ;
262
+ expect ( heartbeatHeaders ) . to . include ( '1969-12-01' ) ;
263
263
expect ( heartbeatHeaders ) . to . include ( '1969-12-31' ) ;
264
264
}
265
265
expect ( heartbeatHeaders ) . to . include ( USER_AGENT_STRING_2 ) ;
@@ -273,6 +273,36 @@ describe('HeartbeatServiceImpl', () => {
273
273
const emptyHeaders = await heartbeatService . getHeartbeatsHeader ( ) ;
274
274
expect ( emptyHeaders ) . to . equal ( '' ) ;
275
275
} ) ;
276
+ it ( 'triggerHeartbeat() removes the earliest heartbeat once it exceeds the max number of heartbeats' , async ( ) => {
277
+ // Trigger heartbeats until we reach the limit
278
+ const numHeartbeats =
279
+ heartbeatService . _heartbeatsCache ?. heartbeats . length ! ;
280
+ for ( let i = numHeartbeats ; i <= 30 ; i ++ ) {
281
+ await heartbeatService . triggerHeartbeat ( ) ;
282
+ clock . tick ( 24 * 60 * 60 * 1000 ) ;
283
+ }
284
+
285
+ expect ( heartbeatService . _heartbeatsCache ?. heartbeats . length ) . to . equal ( 30 ) ;
286
+ const earliestHeartbeatDate = getEarliestHeartbeatIdx (
287
+ heartbeatService . _heartbeatsCache ?. heartbeats !
288
+ ) ;
289
+ const earliestHeartbeat =
290
+ heartbeatService . _heartbeatsCache ?. heartbeats [ earliestHeartbeatDate ] ! ;
291
+ await heartbeatService . triggerHeartbeat ( ) ;
292
+ expect ( heartbeatService . _heartbeatsCache ?. heartbeats . length ) . to . equal ( 30 ) ;
293
+ expect (
294
+ heartbeatService . _heartbeatsCache ?. heartbeats . indexOf ( earliestHeartbeat )
295
+ ) . to . equal ( - 1 ) ;
296
+ } ) ;
297
+ it ( 'triggerHeartbeat() never exceeds 30 heartbeats' , async ( ) => {
298
+ for ( let i = 0 ; i <= 50 ; i ++ ) {
299
+ await heartbeatService . triggerHeartbeat ( ) ;
300
+ clock . tick ( 24 * 60 * 60 * 1000 ) ;
301
+ expect (
302
+ heartbeatService . _heartbeatsCache ?. heartbeats . length
303
+ ) . to . be . lessThanOrEqual ( 30 ) ;
304
+ }
305
+ } ) ;
276
306
} ) ;
277
307
278
308
describe ( 'If IndexedDB records that a header was sent today' , ( ) => {
@@ -426,4 +456,22 @@ describe('HeartbeatServiceImpl', () => {
426
456
) ;
427
457
} ) ;
428
458
} ) ;
459
+
460
+ describe ( 'getEarliestHeartbeatIdx()' , ( ) => {
461
+ it ( 'returns -1 if the heartbeats array is empty' , ( ) => {
462
+ const heartbeats : SingleDateHeartbeat [ ] = [ ] ;
463
+ const idx = getEarliestHeartbeatIdx ( heartbeats ) ;
464
+ expect ( idx ) . to . equal ( - 1 ) ;
465
+ } ) ;
466
+
467
+ it ( 'returns the index of the earliest date' , ( ) => {
468
+ const heartbeats = [
469
+ { agent : generateUserAgentString ( 2 ) , date : '2022-01-02' } ,
470
+ { agent : generateUserAgentString ( 1 ) , date : '2022-01-01' } ,
471
+ { agent : generateUserAgentString ( 3 ) , date : '2022-01-03' }
472
+ ] ;
473
+ const idx = getEarliestHeartbeatIdx ( heartbeats ) ;
474
+ expect ( idx ) . to . equal ( 1 ) ;
475
+ } ) ;
476
+ } ) ;
429
477
} ) ;
0 commit comments