Skip to content
Prev Previous commit
Next Next commit
Merge ssrc changes
  • Loading branch information
trekforever committed Apr 2, 2024
commit de597ee9b9eb65d36f8280919c7a7d159dd118f9
14 changes: 8 additions & 6 deletions src/remote-config/remote-config-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,14 +354,21 @@ export interface ServerTemplateData {
/**
* Represents optional arguments that can be used when instantiating {@link ServerTemplate}.
*/
export interface ServerTemplateOptions {
export interface GetServerTemplateOptions {

/**
* Defines in-app default parameter values, so that your app behaves as
* intended before it connects to the Remote Config backend, and so that
* default values are available if none are set on the backend.
*/
defaultConfig?: ServerConfig,
}

/**
* Represents optional arguments that can be used when instantiating
* {@link ServerTemplate} synchonously.
*/
export interface InitServerTemplateOptions extends GetServerTemplateOptions {

/**
* Enables integrations to use template data loaded independently. For
Expand All @@ -382,11 +389,6 @@ export interface ServerTemplate {
*/
cache: ServerTemplateData;

/**
* A {@link ServerConfig} that contains default Config values.
*/
defaultConfig: ServerConfig;

/**
* Evaluates the current template to produce a {@link ServerConfig}.
*/
Expand Down
28 changes: 3 additions & 25 deletions src/remote-config/remote-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ export class RemoteConfig {
* Instantiates {@link ServerTemplate} and then fetches and caches the latest
* template version of the project.
*/
public async getServerTemplate(options?: ServerTemplateOptions): Promise<ServerTemplate> {
public async getServerTemplate(options?: GetServerTemplateOptions): Promise<ServerTemplate> {
const template = this.initServerTemplate(options);
await template.load();
return template;
Expand All @@ -195,7 +195,7 @@ export class RemoteConfig {
/**
* Synchronously instantiates {@link ServerTemplate}.
*/
public initServerTemplate(options?: ServerTemplateOptions): ServerTemplate {
public initServerTemplate(options?: InitServerTemplateOptions): ServerTemplate {
const template = new ServerTemplateImpl(
this.client, new ConditionEvaluator(), options?.defaultConfig);
if (options?.template) {
Expand All @@ -213,20 +213,6 @@ export class RemoteConfig {
// check and instantiates via ServerTemplateData
template.cache = options?.template;
}
// Check and instantiates via json string
if (isString(options?.template)) {
try {
template.cache = new ServerTemplateDataImpl(JSON.parse(options?.template));
} catch (e) {
throw new FirebaseRemoteConfigError(
'invalid-argument',
`Failed to parse the JSON string: ${options?.template}. ` + e
);
}
} else {
// check and instantiates via ServerTemplateData
template.cache = options?.template;
}
}
return template;
}
Expand Down Expand Up @@ -325,7 +311,7 @@ class ServerTemplateImpl implements ServerTemplate {
constructor(
private readonly apiClient: RemoteConfigApiClient,
private readonly conditionEvaluator: ConditionEvaluator,
public readonly defaultConfig: ServerConfig = {}
private readonly defaultConfig: ServerConfig = {}
) { }

/**
Expand Down Expand Up @@ -423,14 +409,6 @@ class ServerTemplateImpl implements ServerTemplate {
return JSON.stringify(this.cache);
}

/**
* Convenient method that returns the JSON string of the cached template data
* @returns A JSON-string of this object.
*/
public toJSON(): string {
return JSON.stringify(this.cache);
}

/**
* Private helper method that coerces a parameter value string to the {@link ParameterValueType}.
*/
Expand Down
101 changes: 28 additions & 73 deletions test/unit/remote-config/remote-config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import {
import { deepCopy } from '../../../src/utils/deep-copy';
import {
NamedCondition, ServerTemplate, ServerTemplateData, Version
NamedCondition, ServerTemplate, ServerTemplateData, Version
} from '../../../src/remote-config/remote-config-api';

const expect = chai.expect;
Expand Down Expand Up @@ -611,20 +610,28 @@ describe('RemoteConfig', () => {
});

it('should set defaultConfig when passed', () => {
const defaultConfig = {
holiday_promo_enabled: false,
holiday_promo_discount: 20,
};
// Defines template with no parameters to demonstrate
// default config will be used instead,
const template = deepCopy(SERVER_REMOTE_CONFIG_RESPONSE) as ServerTemplateData;
template.parameters = {};

const stub = sinon
.stub(RemoteConfigApiClient.prototype, operationName)
.resolves(SERVER_REMOTE_CONFIG_RESPONSE as ServerTemplateData);
.resolves(template);
stubs.push(stub);

const defaultConfig = {
holiday_promo_enabled: false,
holiday_promo_discount: 20,
};

return remoteConfig.getServerTemplate({ defaultConfig })
.then((template) => {
expect(template.defaultConfig.holiday_promo_enabled).to.equal(false);
expect(template.defaultConfig.holiday_promo_discount).to.equal(20);
const config = template.evaluate();
expect(config.holiday_promo_enabled).to.equal(
defaultConfig.holiday_promo_enabled);
expect(config.holiday_promo_discount).to.equal(
defaultConfig.holiday_promo_discount);
});
});
});
Expand All @@ -643,8 +650,6 @@ describe('RemoteConfig', () => {
};
const initializedTemplate = remoteConfig.initServerTemplate({ template });
const parsed = JSON.parse(initializedTemplate.toJSON());
const initializedTemplate = remoteConfig.initServerTemplate({ template });
const parsed = JSON.parse(initializedTemplate.toJSON());
expect(parsed).deep.equals(deepCopy(template));
});

Expand Down Expand Up @@ -698,57 +703,6 @@ describe('RemoteConfig', () => {
});
});
});

it('should set and instantiates template when json string is passed', () => {
const template = deepCopy(SERVER_REMOTE_CONFIG_RESPONSE) as ServerTemplateData;
template.parameters = {
dog_type: {
defaultValue: {
value: 'shiba'
},
description: 'Type of dog breed',
valueType: 'STRING'
}
};
const templateJson = JSON.stringify(template);
const initializedTemplate = remoteConfig.initServerTemplate({ template: templateJson });
const parsed = JSON.parse(initializedTemplate.toJSON());
const expectedVersion = deepCopy(VERSION_INFO);
expectedVersion.updateTime = new Date(expectedVersion.updateTime).toUTCString();
template.version = expectedVersion as Version;
expect(parsed).deep.equals(deepCopy(template));
});

describe('should throw error if invalid template JSON is passed', () => {
const INVALID_PARAMETERS: any[] = [null, '', 'abc', 1, true, []];
const INVALID_CONDITIONS: any[] = [null, '', 'abc', 1, true, {}];

let sourceTemplate = deepCopy(SERVER_REMOTE_CONFIG_RESPONSE);
const jsonString = '{invalidJson: null}';
it('should throw if template is an invalid JSON', () => {
expect(() => remoteConfig.initServerTemplate({ template: jsonString }))
.to.throw(/Failed to parse the JSON string: ([\D\w]*)\./);
});

INVALID_PARAMETERS.forEach((invalidParameter) => {
sourceTemplate.parameters = invalidParameter;
const jsonString = JSON.stringify(sourceTemplate);
it(`should throw if the parameters is ${JSON.stringify(invalidParameter)}`, () => {
expect(() => remoteConfig.initServerTemplate({ template: jsonString }))
.to.throw('Remote Config parameters must be a non-null object');
});
});

sourceTemplate = deepCopy(SERVER_REMOTE_CONFIG_RESPONSE);
INVALID_CONDITIONS.forEach((invalidConditions) => {
sourceTemplate.conditions = invalidConditions;
const jsonString = JSON.stringify(sourceTemplate);
it(`should throw if the conditions is ${JSON.stringify(invalidConditions)}`, () => {
expect(() => remoteConfig.initServerTemplate({ template: jsonString }))
.to.throw('Remote Config conditions must be an array');
});
});
});
});

describe('RemoteConfigServerTemplate', () => {
Expand Down Expand Up @@ -1139,7 +1093,7 @@ describe('RemoteConfig', () => {

const stub = sinon
.stub(RemoteConfigApiClient.prototype, 'getServerTemplate')
.resolves(SERVER_REMOTE_CONFIG_RESPONSE_2 as ServerTemplateData);
.resolves(template);
stubs.push(stub);

const defaultConfig = {
Expand All @@ -1148,8 +1102,8 @@ describe('RemoteConfig', () => {

return remoteConfig.getServerTemplate({ defaultConfig })
.then((template: ServerTemplate) => {
const config = template.evaluate!();
expect(config.dog_coat).to.equal(template.defaultConfig.dog_coat);
const config = template.evaluate();
expect(config.dog_coat).to.equal(defaultConfig.dog_coat);
});
});

Expand All @@ -1161,7 +1115,7 @@ describe('RemoteConfig', () => {

const stub = sinon
.stub(RemoteConfigApiClient.prototype, 'getServerTemplate')
.resolves(SERVER_REMOTE_CONFIG_RESPONSE_2 as ServerTemplateData);
.resolves(template);
stubs.push(stub);

const defaultConfig = {
Expand All @@ -1171,7 +1125,7 @@ describe('RemoteConfig', () => {
return remoteConfig.getServerTemplate({ defaultConfig })
.then((template: ServerTemplate) => {
const config = template.evaluate!();
expect(config.dog_no_remote_default_value).to.equal(template.defaultConfig.dog_no_remote_default_value);
expect(config.dog_no_remote_default_value).to.equal(defaultConfig.dog_no_remote_default_value);
});
});

Expand All @@ -1183,16 +1137,17 @@ describe('RemoteConfig', () => {

const stub = sinon
.stub(RemoteConfigApiClient.prototype, 'getServerTemplate')
.resolves(SERVER_REMOTE_CONFIG_RESPONSE_2 as ServerTemplateData);
.resolves(template);
stubs.push(stub);
return remoteConfig.getServerTemplate({
defaultConfig: {
dog_use_inapp_default: '🐕'
}
})

const defaultConfig = {
dog_use_inapp_default: '🐕'
};

return remoteConfig.getServerTemplate({ defaultConfig })
.then((template: ServerTemplate) => {
const config = template.evaluate!();
expect(config.dog_use_inapp_default).to.equal(template.defaultConfig.dog_use_inapp_default);
expect(config.dog_use_inapp_default).to.equal(defaultConfig.dog_use_inapp_default);
});
});

Expand Down