Skip to content

Commit 310ee11

Browse files
Add integration tests for RC manage version operations (#914)
* Add integration tests for RC manage version operations * Fix rollback tests * PR fixes
1 parent fb4c988 commit 310ee11

File tree

5 files changed

+140
-13
lines changed

5 files changed

+140
-13
lines changed

src/remote-config/remote-config-api-client.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,10 @@ export class RemoteConfigApiClient {
477477
optionsCopy.endTime = new Date(optionsCopy.endTime).toISOString();
478478
}
479479
}
480+
// Remove undefined fields from optionsCopy
481+
Object.keys(optionsCopy).forEach(key =>
482+
(typeof (optionsCopy as any)[key] === 'undefined') && delete (optionsCopy as any)[key]
483+
);
480484
return optionsCopy;
481485
}
482486
}

src/remote-config/remote-config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ export class RemoteConfig implements FirebaseServiceInterface {
145145
return this.client.listVersions(options)
146146
.then((listVersionsResponse) => {
147147
return {
148-
versions: listVersionsResponse.versions.map(version => new VersionImpl(version)),
148+
versions: listVersionsResponse.versions?.map(version => new VersionImpl(version)) ?? [],
149149
nextPageToken: listVersionsResponse.nextPageToken,
150150
}
151151
});

test/integration/remote-config.spec.ts

Lines changed: 97 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const VALID_PARAMETERS = {
3232
},
3333
// eslint-disable-next-line @typescript-eslint/camelcase
3434
welcome_message: {
35-
defaultValue: { value: 'welcome text' + Date.now() },
35+
defaultValue: { value: `welcome text ${Date.now()}` },
3636
conditionalValues: {
3737
ios: { value: 'welcome ios text' },
3838
android: { value: 'welcome android text' },
@@ -57,16 +57,22 @@ const VALID_PARAMETER_GROUPS = {
5757
},
5858
};
5959

60-
const VALID_CONDITIONS: admin.remoteConfig.RemoteConfigCondition[] = [{
61-
name: 'ios',
62-
expression: 'device.os == \'ios\'',
63-
tagColor: 'INDIGO',
64-
},
65-
{
66-
name: 'android',
67-
expression: 'device.os == \'android\'',
68-
tagColor: 'GREEN',
69-
}];
60+
const VALID_CONDITIONS: admin.remoteConfig.RemoteConfigCondition[] = [
61+
{
62+
name: 'ios',
63+
expression: 'device.os == \'ios\'',
64+
tagColor: 'INDIGO',
65+
},
66+
{
67+
name: 'android',
68+
expression: 'device.os == \'android\'',
69+
tagColor: 'GREEN',
70+
},
71+
];
72+
73+
const VALID_VERSION = {
74+
description: `template description ${Date.now()}`,
75+
}
7076

7177
let currentTemplate: admin.remoteConfig.RemoteConfigTemplate;
7278

@@ -88,13 +94,16 @@ describe('admin.remoteConfig', () => {
8894
currentTemplate.conditions = VALID_CONDITIONS;
8995
currentTemplate.parameters = VALID_PARAMETERS;
9096
currentTemplate.parameterGroups = VALID_PARAMETER_GROUPS;
97+
currentTemplate.version = VALID_VERSION;
9198
return admin.remoteConfig().validateTemplate(currentTemplate)
9299
.then((template) => {
93100
expect(template.etag).matches(/^etag-[0-9]*-[0-9]*$/);
94101
expect(template.conditions.length).to.equal(2);
95102
expect(template.conditions).to.deep.equal(VALID_CONDITIONS);
96103
expect(template.parameters).to.deep.equal(VALID_PARAMETERS);
97104
expect(template.parameterGroups).to.deep.equal(VALID_PARAMETER_GROUPS);
105+
expect(template.version).to.be.not.undefined;
106+
expect(template.version!.description).equals(VALID_VERSION.description);
98107
});
99108
});
100109

@@ -103,6 +112,7 @@ describe('admin.remoteConfig', () => {
103112
currentTemplate.conditions = [];
104113
currentTemplate.parameters = VALID_PARAMETERS;
105114
currentTemplate.parameterGroups = VALID_PARAMETER_GROUPS;
115+
currentTemplate.version = VALID_VERSION;
106116
return admin.remoteConfig().validateTemplate(currentTemplate)
107117
.should.eventually.be.rejected.and.have.property('code', 'remote-config/invalid-argument');
108118
});
@@ -114,13 +124,16 @@ describe('admin.remoteConfig', () => {
114124
currentTemplate.conditions = VALID_CONDITIONS;
115125
currentTemplate.parameters = VALID_PARAMETERS;
116126
currentTemplate.parameterGroups = VALID_PARAMETER_GROUPS;
127+
currentTemplate.version = VALID_VERSION;
117128
return admin.remoteConfig().publishTemplate(currentTemplate)
118129
.then((template) => {
119130
expect(template.etag).matches(/^etag-[0-9]*-[0-9]*$/);
120131
expect(template.conditions.length).to.equal(2);
121132
expect(template.conditions).to.deep.equal(VALID_CONDITIONS);
122133
expect(template.parameters).to.deep.equal(VALID_PARAMETERS);
123134
expect(template.parameterGroups).to.deep.equal(VALID_PARAMETER_GROUPS);
135+
expect(template.version).to.be.not.undefined;
136+
expect(template.version!.description).equals(VALID_VERSION.description);
124137
});
125138
});
126139

@@ -129,20 +142,92 @@ describe('admin.remoteConfig', () => {
129142
currentTemplate.conditions = [];
130143
currentTemplate.parameters = VALID_PARAMETERS;
131144
currentTemplate.parameterGroups = VALID_PARAMETER_GROUPS;
145+
currentTemplate.version = VALID_VERSION;
132146
return admin.remoteConfig().publishTemplate(currentTemplate)
133147
.should.eventually.be.rejected.and.have.property('code', 'remote-config/invalid-argument');
134148
});
135149
});
136150

137151
describe('getTemplate', () => {
138-
it('verfy that getTemplate() returns the most recently published template', () => {
152+
it('should return the most recently published template', () => {
139153
return admin.remoteConfig().getTemplate()
140154
.then((template) => {
141155
expect(template.etag).matches(/^etag-[0-9]*-[0-9]*$/);
142156
expect(template.conditions.length).to.equal(2);
143157
expect(template.conditions).to.deep.equal(VALID_CONDITIONS);
144158
expect(template.parameters).to.deep.equal(VALID_PARAMETERS);
145159
expect(template.parameterGroups).to.deep.equal(VALID_PARAMETER_GROUPS);
160+
expect(template.version).to.be.not.undefined;
161+
expect(template.version!.description).equals(VALID_VERSION.description);
162+
});
163+
});
164+
});
165+
166+
let versionOneNumber: string;
167+
let versionTwoNumber: string;
168+
const versionOneDescription = `getTemplateAtVersion test v1 ${Date.now()}`;
169+
const versionTwoDescription = `getTemplateAtVersion test v2 ${Date.now()}`;
170+
171+
describe('getTemplateAtVersion', () => {
172+
before(async () => {
173+
// obtain the current active template
174+
let activeTemplate = await admin.remoteConfig().getTemplate();
175+
176+
// publish a new template to create a new version number
177+
activeTemplate.version = { description: versionOneDescription };
178+
activeTemplate = await admin.remoteConfig().publishTemplate(activeTemplate)
179+
expect(activeTemplate.version).to.be.not.undefined;
180+
versionOneNumber = activeTemplate.version!.versionNumber!;
181+
182+
// publish another template to create a second version number
183+
activeTemplate.version = { description: versionTwoDescription };
184+
activeTemplate = await admin.remoteConfig().publishTemplate(activeTemplate)
185+
expect(activeTemplate.version).to.be.not.undefined;
186+
versionTwoNumber = activeTemplate.version!.versionNumber!;
187+
});
188+
189+
it('should return the requested template version v1', () => {
190+
return admin.remoteConfig().getTemplateAtVersion(versionOneNumber)
191+
.then((template) => {
192+
expect(template.etag).matches(/^etag-[0-9]*-[0-9]*$/);
193+
expect(template.version).to.be.not.undefined;
194+
expect(template.version!.versionNumber).equals(versionOneNumber);
195+
expect(template.version!.description).equals(versionOneDescription);
196+
});
197+
});
198+
});
199+
200+
describe('listVersions', () => {
201+
it('should return the most recently published 2 versions', () => {
202+
return admin.remoteConfig().listVersions({
203+
pageSize: 2,
204+
})
205+
.then((response) => {
206+
expect(response.versions.length).to.equal(2);
207+
// versions should be in reverse chronological order
208+
expect(response.versions[0].description).equals(versionTwoDescription);
209+
expect(response.versions[0].versionNumber).equals(versionTwoNumber);
210+
expect(response.versions[1].description).equals(versionOneDescription);
211+
expect(response.versions[1].versionNumber).equals(versionOneNumber);
212+
});
213+
});
214+
});
215+
216+
describe('rollback', () => {
217+
it('verify the most recent template version before rollback to the one prior', () => {
218+
return admin.remoteConfig().getTemplate()
219+
.then((template) => {
220+
expect(template.version).to.be.not.undefined;
221+
expect(template.version!.versionNumber).equals(versionTwoNumber);
222+
});
223+
});
224+
225+
it('should rollback to the requested version', () => {
226+
return admin.remoteConfig().rollback(versionOneNumber)
227+
.then((template) => {
228+
expect(template.version).to.be.not.undefined;
229+
expect(template.version!.updateType).equals('ROLLBACK');
230+
expect(template.version!.description).equals(`Rollback to version ${versionOneNumber}`);
146231
});
147232
});
148233
});

test/unit/remote-config/remote-config-api-client.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,28 @@ describe('RemoteConfigApiClient', () => {
599599
});
600600
});
601601

602+
it('should remove undefined fields from options', () => {
603+
const stub = sinon
604+
.stub(HttpClient.prototype, 'send')
605+
.resolves(utils.responseFrom(TEST_VERSIONS_RESULT, 200));
606+
stubs.push(stub);
607+
return apiClient.listVersions({
608+
pageSize: undefined,
609+
pageToken: undefined,
610+
endVersionNumber: 70,
611+
})
612+
.then(() => {
613+
expect(stub).to.have.been.calledOnce.and.calledWith({
614+
method: 'GET',
615+
url: 'https://firebaseremoteconfig.googleapis.com/v1/projects/test-project/remoteConfig:listVersions',
616+
headers: EXPECTED_HEADERS,
617+
data: {
618+
endVersionNumber: '70'
619+
}
620+
});
621+
});
622+
});
623+
602624
it('should resolve with a list of template versions on success', () => {
603625
const startTime = new Date(2020, 4, 2);
604626
const endTime = 'Thu, 07 May 2020 18:44:41 GMT';

test/unit/remote-config/remote-config.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,21 @@ describe('RemoteConfig', () => {
366366
});
367367
});
368368

369+
it('should resolve with an empty versions list if the no results are availble for requested list options', () => {
370+
const stub = sinon
371+
.stub(RemoteConfigApiClient.prototype, 'listVersions')
372+
.resolves({});
373+
stubs.push(stub);
374+
return remoteConfig.listVersions({
375+
pageSize: 2,
376+
endVersionNumber: 10,
377+
})
378+
.then((response) => {
379+
expect(response.versions.length).to.equal(0);
380+
expect(response.nextPageToken).to.be.undefined;
381+
});
382+
});
383+
369384
it('should resolve with template versions list on success', () => {
370385
const stub = sinon
371386
.stub(RemoteConfigApiClient.prototype, 'listVersions')
@@ -378,6 +393,7 @@ describe('RemoteConfig', () => {
378393
expect(response.versions.length).to.equal(2);
379394
expect(response.versions[0].updateTime).equals('Thu, 07 May 2020 18:46:09 GMT');
380395
expect(response.versions[1].updateTime).equals('Thu, 07 May 2020 18:44:41 GMT');
396+
expect(response.nextPageToken).to.equal('76');
381397
});
382398
});
383399
});

0 commit comments

Comments
 (0)