@@ -21,7 +21,8 @@ import sinonChai from 'sinon-chai';
2121import  { 
2222  transportHandler , 
2323  setupTransportService , 
24-   resetTransportService 
24+   resetTransportService , 
25+   flushQueuedEvents 
2526}  from  './transport_service' ; 
2627import  {  SettingsService  }  from  './settings_service' ; 
2728
@@ -88,14 +89,15 @@ describe('Firebase Performance > transport_service', () => {
8889    expect ( fetchStub ) . to . not . have . been . called ; 
8990  } ) ; 
9091
91-   it ( 'sends up to the maximum event limit in one request' ,  async  ( )  =>  { 
92+   it ( 'sends up to the maximum event limit in one request if payload is under 64 KB ' ,  async  ( )  =>  { 
9293    // Arrange 
9394    const  setting  =  SettingsService . getInstance ( ) ; 
9495    const  flTransportFullUrl  = 
9596      setting . flTransportEndpointUrl  +  '?key='  +  setting . transportKey ; 
9697
9798    // Act 
98-     // Generate 1020 events, which should be dispatched in two batches (1000 events and 20 events). 
99+     // Generate 1020 events with small payloads, which should be dispatched in two batches 
100+     // (1000 events and 20 events). 
99101    for  ( let  i  =  0 ;  i  <  1020 ;  i ++ )  { 
100102      testTransportHandler ( 'event'  +  i ) ; 
101103    } 
@@ -134,6 +136,58 @@ describe('Firebase Performance > transport_service', () => {
134136    expect ( fetchStub ) . to . not . have . been . called ; 
135137  } ) ; 
136138
139+   it ( 'sends fetch if payload is above 64 KB' ,  async  ( )  =>  { 
140+     // Arrange 
141+     const  setting  =  SettingsService . getInstance ( ) ; 
142+     const  flTransportFullUrl  = 
143+       setting . flTransportEndpointUrl  +  '?key='  +  setting . transportKey ; 
144+     fetchStub . resolves ( 
145+       new  Response ( '{}' ,  { 
146+         status : 200 , 
147+         headers : {  'Content-type' : 'application/json'  } 
148+       } ) 
149+     ) ; 
150+ 
151+     // Act 
152+     // Generate 1020 events with a large payload. The total size of the payload will be > 65 KB 
153+     const  payload  =  'a' . repeat ( 300 ) ; 
154+     for  ( let  i  =  0 ;  i  <  1020 ;  i ++ )  { 
155+       testTransportHandler ( payload  +  i ) ; 
156+     } 
157+     // Wait for first and second event dispatch to happen. 
158+     clock . tick ( INITIAL_SEND_TIME_DELAY_MS ) ; 
159+     // This is to resolve the floating promise chain in transport service. 
160+     await  Promise . resolve ( ) . then ( ) . then ( ) . then ( ) ; 
161+     clock . tick ( DEFAULT_SEND_INTERVAL_MS ) ; 
162+ 
163+     // Assert 
164+     // Expects the first logRequest which contains first 1000 events. 
165+     const  firstLogRequest  =  generateLogRequest ( '5501' ) ; 
166+     for  ( let  i  =  0 ;  i  <  MAX_EVENT_COUNT_PER_REQUEST ;  i ++ )  { 
167+       firstLogRequest [ 'log_event' ] . push ( { 
168+         'source_extension_json_proto3' : payload  +  i , 
169+         'event_time_ms' : '1' 
170+       } ) ; 
171+     } 
172+     expect ( fetchStub ) . calledWith ( flTransportFullUrl ,  { 
173+       method : 'POST' , 
174+       body : JSON . stringify ( firstLogRequest ) 
175+     } ) ; 
176+     // Expects the second logRequest which contains remaining 20 events; 
177+     const  secondLogRequest  =  generateLogRequest ( '15501' ) ; 
178+     for  ( let  i  =  0 ;  i  <  20 ;  i ++ )  { 
179+       secondLogRequest [ 'log_event' ] . push ( { 
180+         'source_extension_json_proto3' :
181+           payload  +  ( MAX_EVENT_COUNT_PER_REQUEST  +  i ) , 
182+         'event_time_ms' : '1' 
183+       } ) ; 
184+     } 
185+     expect ( sendBeaconStub ) . calledWith ( 
186+       flTransportFullUrl , 
187+       JSON . stringify ( secondLogRequest ) 
188+     ) ; 
189+   } ) ; 
190+ 
137191  it ( 'falls back to fetch if sendBeacon fails.' ,  async  ( )  =>  { 
138192    sendBeaconStub . returns ( false ) ; 
139193    fetchStub . resolves ( 
@@ -147,6 +201,98 @@ describe('Firebase Performance > transport_service', () => {
147201    expect ( fetchStub ) . to . have . been . calledOnce ; 
148202  } ) ; 
149203
204+   it ( 'flushes the queue with multiple sendBeacons in batches of 40' ,  async  ( )  =>  { 
205+     // Arrange 
206+     const  setting  =  SettingsService . getInstance ( ) ; 
207+     const  flTransportFullUrl  = 
208+       setting . flTransportEndpointUrl  +  '?key='  +  setting . transportKey ; 
209+     fetchStub . resolves ( 
210+       new  Response ( '{}' ,  { 
211+         status : 200 , 
212+         headers : {  'Content-type' : 'application/json'  } 
213+       } ) 
214+     ) ; 
215+ 
216+     const  payload  =  'a' . repeat ( 300 ) ; 
217+     // Act 
218+     // Generate 80 events 
219+     for  ( let  i  =  0 ;  i  <  80 ;  i ++ )  { 
220+       testTransportHandler ( payload  +  i ) ; 
221+     } 
222+ 
223+     flushQueuedEvents ( ) ; 
224+ 
225+     // Assert 
226+     const  firstLogRequest  =  generateLogRequest ( '1' ) ; 
227+     const  secondLogRequest  =  generateLogRequest ( '1' ) ; 
228+     for  ( let  i  =  0 ;  i  <  40 ;  i ++ )  { 
229+       firstLogRequest [ 'log_event' ] . push ( { 
230+         'source_extension_json_proto3' : payload  +  ( i  +  40 ) , 
231+         'event_time_ms' : '1' 
232+       } ) ; 
233+       secondLogRequest [ 'log_event' ] . push ( { 
234+         'source_extension_json_proto3' : payload  +  i , 
235+         'event_time_ms' : '1' 
236+       } ) ; 
237+     } 
238+     expect ( sendBeaconStub ) . calledWith ( 
239+       flTransportFullUrl , 
240+       JSON . stringify ( firstLogRequest ) 
241+     ) ; 
242+     expect ( sendBeaconStub ) . calledWith ( 
243+       flTransportFullUrl , 
244+       JSON . stringify ( secondLogRequest ) 
245+     ) ; 
246+     expect ( fetchStub ) . to . not . have . been . called ; 
247+   } ) ; 
248+ 
249+   it ( 'flushes the queue with fetch for sendBeacons that failed' ,  async  ( )  =>  { 
250+     // Arrange 
251+     const  setting  =  SettingsService . getInstance ( ) ; 
252+     const  flTransportFullUrl  = 
253+       setting . flTransportEndpointUrl  +  '?key='  +  setting . transportKey ; 
254+     fetchStub . resolves ( 
255+       new  Response ( '{}' ,  { 
256+         status : 200 , 
257+         headers : {  'Content-type' : 'application/json'  } 
258+       } ) 
259+     ) ; 
260+ 
261+     const  payload  =  'a' . repeat ( 300 ) ; 
262+     // Act 
263+     // Generate 80 events 
264+     for  ( let  i  =  0 ;  i  <  80 ;  i ++ )  { 
265+       testTransportHandler ( payload  +  i ) ; 
266+     } 
267+     sendBeaconStub . onCall ( 0 ) . returns ( true ) ; 
268+     sendBeaconStub . onCall ( 1 ) . returns ( false ) ; 
269+     flushQueuedEvents ( ) ; 
270+ 
271+     // Assert 
272+     const  firstLogRequest  =  generateLogRequest ( '1' ) ; 
273+     const  secondLogRequest  =  generateLogRequest ( '1' ) ; 
274+     for  ( let  i  =  40 ;  i  <  80 ;  i ++ )  { 
275+       firstLogRequest [ 'log_event' ] . push ( { 
276+         'source_extension_json_proto3' : payload  +  i , 
277+         'event_time_ms' : '1' 
278+       } ) ; 
279+     } 
280+     for  ( let  i  =  0 ;  i  <  40 ;  i ++ )  { 
281+       secondLogRequest [ 'log_event' ] . push ( { 
282+         'source_extension_json_proto3' : payload  +  i , 
283+         'event_time_ms' : '1' 
284+       } ) ; 
285+     } 
286+     expect ( sendBeaconStub ) . calledWith ( 
287+       flTransportFullUrl , 
288+       JSON . stringify ( firstLogRequest ) 
289+     ) ; 
290+     expect ( fetchStub ) . calledWith ( flTransportFullUrl ,  { 
291+       method : 'POST' , 
292+       body : JSON . stringify ( secondLogRequest ) 
293+     } ) ; 
294+   } ) ; 
295+ 
150296  function  generateLogRequest ( requestTimeMs : string ) : any  { 
151297    return  { 
152298      'request_time_ms' : requestTimeMs , 
0 commit comments