15
15
* limitations under the License.
16
16
*/
17
17
18
- import { spy , useFakeTimers , SinonFakeTimers } from 'sinon' ;
18
+ import { stub , useFakeTimers , SinonFakeTimers } from 'sinon' ;
19
19
import { use , expect } from 'chai' ;
20
20
import sinonChai from 'sinon-chai' ;
21
21
import {
@@ -27,8 +27,10 @@ import { SettingsService } from './settings_service';
27
27
28
28
use ( sinonChai ) ;
29
29
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' ) ;
32
34
const INITIAL_SEND_TIME_DELAY_MS = 5.5 * 1000 ;
33
35
const DEFAULT_SEND_INTERVAL_MS = 10 * 1000 ;
34
36
const MAX_EVENT_COUNT_PER_REQUEST = 1000 ;
@@ -41,12 +43,14 @@ describe('Firebase Performance > transport_service', () => {
41
43
beforeEach ( ( ) => {
42
44
clock = useFakeTimers ( 1 ) ;
43
45
setupTransportService ( ) ;
46
+ sendBeaconStub . returns ( true ) ;
44
47
} ) ;
45
48
46
49
afterEach ( ( ) => {
47
50
clock . restore ( ) ;
48
51
resetTransportService ( ) ;
49
- sendBeaconSpy . resetHistory ( ) ;
52
+ sendBeaconStub . restore ( ) ;
53
+ fetchStub . restore ( ) ;
50
54
} ) ;
51
55
52
56
it ( 'throws an error when logging an empty message' , ( ) => {
@@ -57,20 +61,23 @@ describe('Firebase Performance > transport_service', () => {
57
61
58
62
it ( 'does not attempt to log an event after INITIAL_SEND_TIME_DELAY_MS if queue is empty' , ( ) => {
59
63
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 ;
61
66
} ) ;
62
67
63
68
it ( 'attempts to log an event after DEFAULT_SEND_INTERVAL_MS if queue not empty' , async ( ) => {
64
69
clock . tick ( INITIAL_SEND_TIME_DELAY_MS ) ;
65
70
testTransportHandler ( 'someEvent' ) ;
66
71
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 ;
68
74
} ) ;
69
75
70
76
it ( 'successful send a message to transport' , ( ) => {
71
77
testTransportHandler ( 'event1' ) ;
72
78
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 ;
74
81
} ) ;
75
82
76
83
it ( 'sends up to the maximum event limit in one request' , async ( ) => {
@@ -99,7 +106,7 @@ describe('Firebase Performance > transport_service', () => {
99
106
'event_time_ms' : '1'
100
107
} ) ;
101
108
}
102
- expect ( sendBeaconSpy ) . which . to . have . been . calledWith (
109
+ expect ( sendBeaconStub ) . which . to . have . been . calledWith (
103
110
flTransportFullUrl ,
104
111
JSON . stringify ( firstLogRequest )
105
112
) ;
@@ -112,7 +119,55 @@ describe('Firebase Performance > transport_service', () => {
112
119
'event_time_ms' : '1'
113
120
} ) ;
114
121
}
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 (
116
171
flTransportFullUrl ,
117
172
JSON . stringify ( secondLogRequest )
118
173
) ;
0 commit comments