Skip to content

Commit 57bc39d

Browse files
authored
stub storage differently so tests work in Firefox and IE (#1940)
* stub storage differently so tests work in Firefox and IE * [AUTOMATED]: Prettier Code Styling * rewrite test setup * [AUTOMATED]: Prettier Code Styling
1 parent c42239e commit 57bc39d

File tree

1 file changed

+80
-48
lines changed

1 file changed

+80
-48
lines changed

packages/performance/src/services/remote_config_service.test.ts

Lines changed: 80 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
import { stub, SinonStub, useFakeTimers, SinonFakeTimers } from 'sinon';
17+
import { stub, useFakeTimers, SinonFakeTimers, SinonStub } from 'sinon';
1818
import { expect } from 'chai';
1919
import { SettingsService } from './settings_service';
2020
import { CONFIG_EXPIRY_LOCAL_STORAGE_KEY } from '../constants';
21-
import { setupApi } from './api_service';
21+
import { setupApi, Api } from './api_service';
2222
import * as iidService from './iid_service';
2323
import { getConfig } from './remote_config_service';
2424
import { FirebaseApp } from '@firebase/app-types';
@@ -41,11 +41,10 @@ describe('Performance Monitoring > remote_config_service', () => {
4141
const APP_ID = '1:23r:web:fewq';
4242
const API_KEY = 'asdfghjk';
4343

44-
let fetchStub: SinonStub<[RequestInfo, RequestInit?], Promise<Response>>;
45-
let storageGetItemStub: SinonStub<[string], string | null>;
4644
let clock: SinonFakeTimers;
4745

4846
setupApi(self);
47+
const ApiInstance = Api.getInstance();
4948

5049
function storageGetItemFakeFactory(
5150
expiry: string,
@@ -67,17 +66,47 @@ describe('Performance Monitoring > remote_config_service', () => {
6766
settingsService.tracesSamplingRate = 1;
6867
}
6968

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+
7385
stub(iidService, 'getAuthTokenPromise').returns(
7486
Promise.resolve(AUTH_TOKEN)
7587
);
88+
7689
clock = useFakeTimers(GLOBAL_CLOCK_NOW);
7790
SettingsService.prototype.firebaseAppInstance = ({
7891
options: { projectId: PROJECT_ID, appId: APP_ID, apiKey: API_KEY }
7992
} 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+
}
81110

82111
afterEach(() => {
83112
resetSettingsService();
@@ -88,15 +117,14 @@ describe('Performance Monitoring > remote_config_service', () => {
88117
it('gets the config from the local storage if available and valid', async () => {
89118
// After global clock. Config not expired.
90119
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+
97125
await getConfig(IID);
98126

99-
expect(storageGetItemStub).to.be.called;
127+
expect(getItemStub).to.be.called;
100128
expect(SettingsService.getInstance().loggingEnabled).to.be.true;
101129
expect(SettingsService.getInstance().logEndPointUrl).to.equal(LOG_URL);
102130
expect(SettingsService.getInstance().logSource).to.equal(LOG_SOURCE);
@@ -111,12 +139,12 @@ describe('Performance Monitoring > remote_config_service', () => {
111139
it('does not call remote config if a valid config is in local storage', async () => {
112140
// After global clock. Config not expired.
113141
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+
120148
await getConfig(IID);
121149

122150
expect(fetchStub).not.to.be.called;
@@ -125,16 +153,15 @@ describe('Performance Monitoring > remote_config_service', () => {
125153
it('gets the config from RC if local version is not valid', async () => {
126154
// Expired local config.
127155
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) }
133160
);
134-
fetchStub.resolves(new Response(STRINGIFIED_CONFIG));
161+
135162
await getConfig(IID);
136163

137-
expect(storageGetItemStub).to.be.calledOnce;
164+
expect(getItemStub).to.be.calledOnce;
138165
expect(SettingsService.getInstance().loggingEnabled).to.be.true;
139166
expect(SettingsService.getInstance().logEndPointUrl).to.equal(LOG_URL);
140167
expect(SettingsService.getInstance().logSource).to.equal(LOG_SOURCE);
@@ -149,13 +176,15 @@ describe('Performance Monitoring > remote_config_service', () => {
149176
it('does not change the default config if call to RC fails', async () => {
150177
// Expired local config.
151178
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 }
157186
);
158-
fetchStub.rejects();
187+
159188
await getConfig(IID);
160189

161190
expect(SettingsService.getInstance().loggingEnabled).to.equal(false);
@@ -164,17 +193,19 @@ describe('Performance Monitoring > remote_config_service', () => {
164193
it('uses secondary configs if the response does not have all the fields', async () => {
165194
// Expired local config.
166195
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-
);
173196
const STRINGIFIED_PARTIAL_CONFIG = `{"entries":{\
174197
"fpr_vc_network_request_sampling_rate":"0.250000",\
175198
"fpr_vc_session_sampling_rate":"0.250000","fpr_vc_trace_sampling_rate":"0.500000"},\
176199
"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+
178209
await getConfig(IID);
179210

180211
expect(SettingsService.getInstance().loggingEnabled).to.be.true;
@@ -183,14 +214,15 @@ describe('Performance Monitoring > remote_config_service', () => {
183214
it('uses secondary configs if the response does not have any fields', async () => {
184215
// Expired local config.
185216
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-
);
192217
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+
);
194226
await getConfig(IID);
195227

196228
expect(SettingsService.getInstance().loggingEnabled).to.be.true;

0 commit comments

Comments
 (0)