@@ -20,14 +20,15 @@ import '../test/setup';
2020import {
2121 countBytes ,
2222 HeartbeatServiceImpl ,
23- extractHeartbeatsForHeader
23+ extractHeartbeatsForHeader ,
24+ getEarliestHeartbeatIdx
2425} from './heartbeatService' ;
2526import {
2627 Component ,
2728 ComponentType ,
2829 ComponentContainer
2930} from '@firebase/component' ;
30- import { PlatformLoggerService } from './types' ;
31+ import { PlatformLoggerService , SingleDateHeartbeat } from './types' ;
3132import { FirebaseApp } from './public-types' ;
3233import * as firebaseUtil from '@firebase/util' ;
3334import { SinonStub , stub , useFakeTimers } from 'sinon' ;
@@ -173,7 +174,6 @@ describe('HeartbeatServiceImpl', () => {
173174 let writeStub : SinonStub ;
174175 let userAgentString = USER_AGENT_STRING_1 ;
175176 const mockIndexedDBHeartbeats = [
176- // Chosen so one will exceed 30 day limit and one will not.
177177 {
178178 agent : 'old-user-agent' ,
179179 date : '1969-12-01'
@@ -236,15 +236,14 @@ describe('HeartbeatServiceImpl', () => {
236236 } ) ;
237237 }
238238 } ) ;
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 ( ) => {
240240 userAgentString = USER_AGENT_STRING_2 ;
241241 clock . tick ( 3 * 24 * 60 * 60 * 1000 ) ;
242242 await heartbeatService . triggerHeartbeat ( ) ;
243243 if ( firebaseUtil . isIndexedDBAvailable ( ) ) {
244244 expect ( writeStub ) . to . be . calledWith ( {
245245 heartbeats : [
246- // The first entry exceeds the 30 day retention limit.
247- mockIndexedDBHeartbeats [ 1 ] ,
246+ ...mockIndexedDBHeartbeats ,
248247 { agent : USER_AGENT_STRING_2 , date : '1970-01-04' }
249248 ]
250249 } ) ;
@@ -260,6 +259,7 @@ describe('HeartbeatServiceImpl', () => {
260259 ) ;
261260 if ( firebaseUtil . isIndexedDBAvailable ( ) ) {
262261 expect ( heartbeatHeaders ) . to . include ( 'old-user-agent' ) ;
262+ expect ( heartbeatHeaders ) . to . include ( '1969-12-01' ) ;
263263 expect ( heartbeatHeaders ) . to . include ( '1969-12-31' ) ;
264264 }
265265 expect ( heartbeatHeaders ) . to . include ( USER_AGENT_STRING_2 ) ;
@@ -273,6 +273,36 @@ describe('HeartbeatServiceImpl', () => {
273273 const emptyHeaders = await heartbeatService . getHeartbeatsHeader ( ) ;
274274 expect ( emptyHeaders ) . to . equal ( '' ) ;
275275 } ) ;
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+ } ) ;
276306 } ) ;
277307
278308 describe ( 'If IndexedDB records that a header was sent today' , ( ) => {
@@ -426,4 +456,22 @@ describe('HeartbeatServiceImpl', () => {
426456 ) ;
427457 } ) ;
428458 } ) ;
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+ } ) ;
429477} ) ;
0 commit comments