@@ -21,7 +21,8 @@ import sinonChai from 'sinon-chai';
21
21
import {
22
22
transportHandler ,
23
23
setupTransportService ,
24
- resetTransportService
24
+ resetTransportService ,
25
+ flushQueuedEvents
25
26
} from './transport_service' ;
26
27
import { SettingsService } from './settings_service' ;
27
28
@@ -88,14 +89,15 @@ describe('Firebase Performance > transport_service', () => {
88
89
expect ( fetchStub ) . to . not . have . been . called ;
89
90
} ) ;
90
91
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 ( ) => {
92
93
// Arrange
93
94
const setting = SettingsService . getInstance ( ) ;
94
95
const flTransportFullUrl =
95
96
setting . flTransportEndpointUrl + '?key=' + setting . transportKey ;
96
97
97
98
// 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).
99
101
for ( let i = 0 ; i < 1020 ; i ++ ) {
100
102
testTransportHandler ( 'event' + i ) ;
101
103
}
@@ -134,6 +136,58 @@ describe('Firebase Performance > transport_service', () => {
134
136
expect ( fetchStub ) . to . not . have . been . called ;
135
137
} ) ;
136
138
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
+
137
191
it ( 'falls back to fetch if sendBeacon fails.' , async ( ) => {
138
192
sendBeaconStub . returns ( false ) ;
139
193
fetchStub . resolves (
@@ -147,6 +201,98 @@ describe('Firebase Performance > transport_service', () => {
147
201
expect ( fetchStub ) . to . have . been . calledOnce ;
148
202
} ) ;
149
203
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
+
150
296
function generateLogRequest ( requestTimeMs : string ) : any {
151
297
return {
152
298
'request_time_ms' : requestTimeMs ,
0 commit comments