14
14
* See the License for the specific language governing permissions and
15
15
* limitations under the License.
16
16
*/
17
- import { stub , SinonStub , useFakeTimers , SinonFakeTimers } from 'sinon' ;
17
+ import { stub , useFakeTimers , SinonFakeTimers , SinonStub } from 'sinon' ;
18
18
import { expect } from 'chai' ;
19
19
import { SettingsService } from './settings_service' ;
20
20
import { CONFIG_EXPIRY_LOCAL_STORAGE_KEY } from '../constants' ;
21
- import { setupApi } from './api_service' ;
21
+ import { setupApi , Api } from './api_service' ;
22
22
import * as iidService from './iid_service' ;
23
23
import { getConfig } from './remote_config_service' ;
24
24
import { FirebaseApp } from '@firebase/app-types' ;
@@ -41,11 +41,10 @@ describe('Performance Monitoring > remote_config_service', () => {
41
41
const APP_ID = '1:23r:web:fewq' ;
42
42
const API_KEY = 'asdfghjk' ;
43
43
44
- let fetchStub : SinonStub < [ RequestInfo , RequestInit ?] , Promise < Response > > ;
45
- let storageGetItemStub : SinonStub < [ string ] , string | null > ;
46
44
let clock : SinonFakeTimers ;
47
45
48
46
setupApi ( self ) ;
47
+ const ApiInstance = Api . getInstance ( ) ;
49
48
50
49
function storageGetItemFakeFactory (
51
50
expiry : string ,
@@ -67,17 +66,47 @@ describe('Performance Monitoring > remote_config_service', () => {
67
66
settingsService . tracesSamplingRate = 1 ;
68
67
}
69
68
70
- beforeEach ( ( ) => {
71
- fetchStub = stub ( self , 'fetch' ) ;
72
- storageGetItemStub = stub ( self . localStorage , 'getItem' ) ;
69
+ // parameterized beforeEach. Should be called at beginning of each test.
70
+ function setup (
71
+ storageConfig : { expiry : string ; config : string } ,
72
+ fetchConfig ?: { reject : boolean ; value ?: Response }
73
+ ) : {
74
+ storageGetItemStub : SinonStub < [ string ] , string | null > ;
75
+ fetchStub : SinonStub < [ RequestInfo , RequestInit ?] , Promise < Response > > ;
76
+ } {
77
+ const fetchStub = stub ( self , 'fetch' ) ;
78
+
79
+ if ( fetchConfig ) {
80
+ fetchConfig . reject
81
+ ? fetchStub . rejects ( )
82
+ : fetchStub . resolves ( fetchConfig . value ) ;
83
+ }
84
+
73
85
stub ( iidService , 'getAuthTokenPromise' ) . returns (
74
86
Promise . resolve ( AUTH_TOKEN )
75
87
) ;
88
+
76
89
clock = useFakeTimers ( GLOBAL_CLOCK_NOW ) ;
77
90
SettingsService . prototype . firebaseAppInstance = ( {
78
91
options : { projectId : PROJECT_ID , appId : APP_ID , apiKey : API_KEY }
79
92
} as unknown ) as FirebaseApp ;
80
- } ) ;
93
+
94
+ // we need to stub the entire localStorage, because storage can't be stubbed in Firefox and IE.
95
+ // stubbing on self(window) seems to only work the first time (at least in Firefox), the subsequent
96
+ // tests will have the same stub. stub.reset() in afterEach doesn't help either. As a result, we stub on ApiInstance.
97
+ // https://github.com/sinonjs/sinon/issues/662
98
+ const storageStub = stub ( ApiInstance , 'localStorage' ) ;
99
+ const getItemStub : SinonStub < [ string ] , string | null > = stub ( ) ;
100
+
101
+ storageStub . value ( {
102
+ getItem : getItemStub . callsFake (
103
+ storageGetItemFakeFactory ( storageConfig . expiry , storageConfig . config )
104
+ ) ,
105
+ setItem : ( ) => { }
106
+ } ) ;
107
+
108
+ return { storageGetItemStub : getItemStub , fetchStub } ;
109
+ }
81
110
82
111
afterEach ( ( ) => {
83
112
resetSettingsService ( ) ;
@@ -88,15 +117,14 @@ describe('Performance Monitoring > remote_config_service', () => {
88
117
it ( 'gets the config from the local storage if available and valid' , async ( ) => {
89
118
// After global clock. Config not expired.
90
119
const EXPIRY_LOCAL_STORAGE_VALUE = '1556524895330' ;
91
- storageGetItemStub . callsFake (
92
- storageGetItemFakeFactory (
93
- EXPIRY_LOCAL_STORAGE_VALUE ,
94
- STRINGIFIED_CONFIG
95
- )
96
- ) ;
120
+ const { storageGetItemStub : getItemStub } = setup ( {
121
+ expiry : EXPIRY_LOCAL_STORAGE_VALUE ,
122
+ config : STRINGIFIED_CONFIG
123
+ } ) ;
124
+
97
125
await getConfig ( IID ) ;
98
126
99
- expect ( storageGetItemStub ) . to . be . called ;
127
+ expect ( getItemStub ) . to . be . called ;
100
128
expect ( SettingsService . getInstance ( ) . loggingEnabled ) . to . be . true ;
101
129
expect ( SettingsService . getInstance ( ) . logEndPointUrl ) . to . equal ( LOG_URL ) ;
102
130
expect ( SettingsService . getInstance ( ) . logSource ) . to . equal ( LOG_SOURCE ) ;
@@ -111,12 +139,12 @@ describe('Performance Monitoring > remote_config_service', () => {
111
139
it ( 'does not call remote config if a valid config is in local storage' , async ( ) => {
112
140
// After global clock. Config not expired.
113
141
const EXPIRY_LOCAL_STORAGE_VALUE = '1556524895330' ;
114
- storageGetItemStub . callsFake (
115
- storageGetItemFakeFactory (
116
- EXPIRY_LOCAL_STORAGE_VALUE ,
117
- STRINGIFIED_CONFIG
118
- )
119
- ) ;
142
+
143
+ const { fetchStub } = setup ( {
144
+ expiry : EXPIRY_LOCAL_STORAGE_VALUE ,
145
+ config : STRINGIFIED_CONFIG
146
+ } ) ;
147
+
120
148
await getConfig ( IID ) ;
121
149
122
150
expect ( fetchStub ) . not . to . be . called ;
@@ -125,16 +153,15 @@ describe('Performance Monitoring > remote_config_service', () => {
125
153
it ( 'gets the config from RC if local version is not valid' , async ( ) => {
126
154
// Expired local config.
127
155
const EXPIRY_LOCAL_STORAGE_VALUE = '1556524895320' ;
128
- storageGetItemStub . callsFake (
129
- storageGetItemFakeFactory (
130
- EXPIRY_LOCAL_STORAGE_VALUE ,
131
- 'not a valid config and should not be used'
132
- )
156
+
157
+ const { storageGetItemStub : getItemStub } = setup (
158
+ { expiry : EXPIRY_LOCAL_STORAGE_VALUE , config : STRINGIFIED_CONFIG } ,
159
+ { reject : false , value : new Response ( STRINGIFIED_CONFIG ) }
133
160
) ;
134
- fetchStub . resolves ( new Response ( STRINGIFIED_CONFIG ) ) ;
161
+
135
162
await getConfig ( IID ) ;
136
163
137
- expect ( storageGetItemStub ) . to . be . calledOnce ;
164
+ expect ( getItemStub ) . to . be . calledOnce ;
138
165
expect ( SettingsService . getInstance ( ) . loggingEnabled ) . to . be . true ;
139
166
expect ( SettingsService . getInstance ( ) . logEndPointUrl ) . to . equal ( LOG_URL ) ;
140
167
expect ( SettingsService . getInstance ( ) . logSource ) . to . equal ( LOG_SOURCE ) ;
@@ -149,13 +176,15 @@ describe('Performance Monitoring > remote_config_service', () => {
149
176
it ( 'does not change the default config if call to RC fails' , async ( ) => {
150
177
// Expired local config.
151
178
const EXPIRY_LOCAL_STORAGE_VALUE = '1556524895320' ;
152
- storageGetItemStub . callsFake (
153
- storageGetItemFakeFactory (
154
- EXPIRY_LOCAL_STORAGE_VALUE ,
155
- 'not a valid config and should not be used'
156
- )
179
+
180
+ setup (
181
+ {
182
+ expiry : EXPIRY_LOCAL_STORAGE_VALUE ,
183
+ config : 'not a valid config and should not be used'
184
+ } ,
185
+ { reject : true }
157
186
) ;
158
- fetchStub . rejects ( ) ;
187
+
159
188
await getConfig ( IID ) ;
160
189
161
190
expect ( SettingsService . getInstance ( ) . loggingEnabled ) . to . equal ( false ) ;
@@ -164,17 +193,19 @@ describe('Performance Monitoring > remote_config_service', () => {
164
193
it ( 'uses secondary configs if the response does not have all the fields' , async ( ) => {
165
194
// Expired local config.
166
195
const EXPIRY_LOCAL_STORAGE_VALUE = '1556524895320' ;
167
- storageGetItemStub . callsFake (
168
- storageGetItemFakeFactory (
169
- EXPIRY_LOCAL_STORAGE_VALUE ,
170
- 'not a valid config and should not be used'
171
- )
172
- ) ;
173
196
const STRINGIFIED_PARTIAL_CONFIG = `{"entries":{\
174
197
"fpr_vc_network_request_sampling_rate":"0.250000",\
175
198
"fpr_vc_session_sampling_rate":"0.250000","fpr_vc_trace_sampling_rate":"0.500000"},\
176
199
"state":"UPDATE"}` ;
177
- fetchStub . resolves ( new Response ( STRINGIFIED_PARTIAL_CONFIG ) ) ;
200
+
201
+ setup (
202
+ {
203
+ expiry : EXPIRY_LOCAL_STORAGE_VALUE ,
204
+ config : 'not a valid config and should not be used'
205
+ } ,
206
+ { reject : false , value : new Response ( STRINGIFIED_PARTIAL_CONFIG ) }
207
+ ) ;
208
+
178
209
await getConfig ( IID ) ;
179
210
180
211
expect ( SettingsService . getInstance ( ) . loggingEnabled ) . to . be . true ;
@@ -183,14 +214,15 @@ describe('Performance Monitoring > remote_config_service', () => {
183
214
it ( 'uses secondary configs if the response does not have any fields' , async ( ) => {
184
215
// Expired local config.
185
216
const EXPIRY_LOCAL_STORAGE_VALUE = '1556524895320' ;
186
- storageGetItemStub . callsFake (
187
- storageGetItemFakeFactory (
188
- EXPIRY_LOCAL_STORAGE_VALUE ,
189
- 'not a valid config and should not be used'
190
- )
191
- ) ;
192
217
const STRINGIFIED_PARTIAL_CONFIG = '{"state":"NO TEMPLATE"}' ;
193
- fetchStub . resolves ( new Response ( STRINGIFIED_PARTIAL_CONFIG ) ) ;
218
+
219
+ setup (
220
+ {
221
+ expiry : EXPIRY_LOCAL_STORAGE_VALUE ,
222
+ config : 'not a valid config and should not be used'
223
+ } ,
224
+ { reject : false , value : new Response ( STRINGIFIED_PARTIAL_CONFIG ) }
225
+ ) ;
194
226
await getConfig ( IID ) ;
195
227
196
228
expect ( SettingsService . getInstance ( ) . loggingEnabled ) . to . be . true ;
0 commit comments