1515 * limitations under the License.
1616 */
1717
18- import { spy , useFakeTimers , SinonFakeTimers } from 'sinon' ;
18+ import { stub , useFakeTimers , SinonFakeTimers } from 'sinon' ;
1919import { use , expect } from 'chai' ;
2020import sinonChai from 'sinon-chai' ;
2121import {
@@ -27,8 +27,10 @@ import { SettingsService } from './settings_service';
2727
2828use ( sinonChai ) ;
2929
30- describe ( 'Firebase Performance > transport_service' , ( ) => {
31- const sendBeaconSpy = spy ( navigator , 'sendBeacon' ) ;
30+ /* eslint-disable no-restricted-properties */
31+ describe . only ( 'Firebase Performance > transport_service' , ( ) => {
32+ const sendBeaconStub = stub ( navigator , 'sendBeacon' ) ;
33+ const fetchStub = stub ( window , 'fetch' ) ;
3234 const INITIAL_SEND_TIME_DELAY_MS = 5.5 * 1000 ;
3335 const DEFAULT_SEND_INTERVAL_MS = 10 * 1000 ;
3436 const MAX_EVENT_COUNT_PER_REQUEST = 1000 ;
@@ -41,12 +43,14 @@ describe('Firebase Performance > transport_service', () => {
4143 beforeEach ( ( ) => {
4244 clock = useFakeTimers ( 1 ) ;
4345 setupTransportService ( ) ;
46+ sendBeaconStub . returns ( true ) ;
4447 } ) ;
4548
4649 afterEach ( ( ) => {
4750 clock . restore ( ) ;
4851 resetTransportService ( ) ;
49- sendBeaconSpy . resetHistory ( ) ;
52+ sendBeaconStub . restore ( ) ;
53+ fetchStub . restore ( ) ;
5054 } ) ;
5155
5256 it ( 'throws an error when logging an empty message' , ( ) => {
@@ -57,20 +61,23 @@ describe('Firebase Performance > transport_service', () => {
5761
5862 it ( 'does not attempt to log an event after INITIAL_SEND_TIME_DELAY_MS if queue is empty' , ( ) => {
5963 clock . tick ( INITIAL_SEND_TIME_DELAY_MS ) ;
60- expect ( sendBeaconSpy ) . to . not . have . been . called ;
64+ expect ( sendBeaconStub ) . to . not . have . been . called ;
65+ expect ( fetchStub ) . to . not . have . been . called ;
6166 } ) ;
6267
6368 it ( 'attempts to log an event after DEFAULT_SEND_INTERVAL_MS if queue not empty' , async ( ) => {
6469 clock . tick ( INITIAL_SEND_TIME_DELAY_MS ) ;
6570 testTransportHandler ( 'someEvent' ) ;
6671 clock . tick ( DEFAULT_SEND_INTERVAL_MS ) ;
67- expect ( sendBeaconSpy ) . to . have . been . calledOnce ;
72+ expect ( sendBeaconStub ) . to . have . been . calledOnce ;
73+ expect ( fetchStub ) . to . not . have . been . called ;
6874 } ) ;
6975
7076 it ( 'successful send a message to transport' , ( ) => {
7177 testTransportHandler ( 'event1' ) ;
7278 clock . tick ( INITIAL_SEND_TIME_DELAY_MS ) ;
73- expect ( sendBeaconSpy ) . to . have . been . calledOnce ;
79+ expect ( sendBeaconStub ) . to . have . been . calledOnce ;
80+ expect ( fetchStub ) . to . not . have . been . called ;
7481 } ) ;
7582
7683 it ( 'sends up to the maximum event limit in one request' , async ( ) => {
@@ -99,7 +106,7 @@ describe('Firebase Performance > transport_service', () => {
99106 'event_time_ms' : '1'
100107 } ) ;
101108 }
102- expect ( sendBeaconSpy ) . which . to . have . been . calledWith (
109+ expect ( sendBeaconStub ) . which . to . have . been . calledWith (
103110 flTransportFullUrl ,
104111 JSON . stringify ( firstLogRequest )
105112 ) ;
@@ -112,7 +119,55 @@ describe('Firebase Performance > transport_service', () => {
112119 'event_time_ms' : '1'
113120 } ) ;
114121 }
115- expect ( sendBeaconSpy ) . calledWith (
122+ expect ( sendBeaconStub ) . calledWith (
123+ flTransportFullUrl ,
124+ JSON . stringify ( secondLogRequest )
125+ ) ;
126+ expect ( fetchStub ) . to . not . have . been . called ;
127+ } ) ;
128+
129+ it ( 'falls back to fetch if sendBeacon fails.' , async ( ) => {
130+ sendBeaconStub . returns ( false ) ;
131+ // Arrange
132+ const setting = SettingsService . getInstance ( ) ;
133+ const flTransportFullUrl =
134+ setting . flTransportEndpointUrl + '?key=' + setting . transportKey ;
135+
136+ // Act
137+ // Generate 1020 events, which should be dispatched in two batches (1000 events and 20 events).
138+ for ( let i = 0 ; i < 1020 ; i ++ ) {
139+ testTransportHandler ( 'event' + i ) ;
140+ }
141+ // Wait for first and second event dispatch to happen.
142+ clock . tick ( INITIAL_SEND_TIME_DELAY_MS ) ;
143+ // This is to resolve the floating promise chain in transport service.
144+ await Promise . resolve ( ) . then ( ) . then ( ) . then ( ) ;
145+ clock . tick ( DEFAULT_SEND_INTERVAL_MS ) ;
146+
147+ // Assert
148+ // Expects the first logRequest which contains first 1000 events.
149+ const firstLogRequest = generateLogRequest ( '5501' ) ;
150+ for ( let i = 0 ; i < MAX_EVENT_COUNT_PER_REQUEST ; i ++ ) {
151+ firstLogRequest [ 'log_event' ] . push ( {
152+ 'source_extension_json_proto3' : 'event' + i ,
153+ 'event_time_ms' : '1'
154+ } ) ;
155+ }
156+ expect ( fetchStub ) . to . not . have . been . called ;
157+ expect ( sendBeaconStub ) . which . to . have . been . calledWith (
158+ flTransportFullUrl ,
159+ JSON . stringify ( firstLogRequest )
160+ ) ;
161+ // Expects the second logRequest which contains remaining 20 events;
162+ const secondLogRequest = generateLogRequest ( '15501' ) ;
163+ for ( let i = 0 ; i < 20 ; i ++ ) {
164+ secondLogRequest [ 'log_event' ] . push ( {
165+ 'source_extension_json_proto3' :
166+ 'event' + ( MAX_EVENT_COUNT_PER_REQUEST + i ) ,
167+ 'event_time_ms' : '1'
168+ } ) ;
169+ }
170+ expect ( sendBeaconStub ) . calledWith (
116171 flTransportFullUrl ,
117172 JSON . stringify ( secondLogRequest )
118173 ) ;
0 commit comments