Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit 5cf5ddc

Browse files
refactor: Removed cloneDeep dependency from the sdk package (optimizely#415)
Summary: To reduce package size, we are gradually removing lodash library. This PR removes lodash.cloneDeep from optimizely-sdk package. It is still part of the repository but it is only being used to run tests. lodash has been removed from dependencies and moved to dev-dependencies in package.json Test plan: All unit tests and Full Stack compatibility tests pass after this change Co-authored-by: zashraf1985 <[email protected]>
1 parent 026a21c commit 5cf5ddc

File tree

13 files changed

+51
-50
lines changed

13 files changed

+51
-50
lines changed

packages/optimizely-sdk/lib/core/bucketer/index.tests.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ describe('lib/core/bucketer', function() {
4747

4848
describe('return values for bucketing (excluding groups)', function() {
4949
beforeEach(function() {
50-
configObj = projectConfig.createProjectConfig(testData);
50+
configObj = projectConfig.createProjectConfig(cloneDeep(testData));
5151
bucketerParams = {
5252
experimentId: configObj.experiments[0].id,
5353
experimentKey: configObj.experiments[0].key,
@@ -103,7 +103,7 @@ describe('lib/core/bucketer', function() {
103103
describe('return values for bucketing (including groups)', function() {
104104
var bucketerStub;
105105
beforeEach(function() {
106-
configObj = projectConfig.createProjectConfig(testData);
106+
configObj = projectConfig.createProjectConfig(cloneDeep(testData));
107107
bucketerParams = {
108108
experimentId: configObj.experiments[0].id,
109109
experimentKey: configObj.experiments[0].key,
@@ -284,7 +284,7 @@ describe('lib/core/bucketer', function() {
284284

285285
describe('when the bucket value falls into empty traffic allocation ranges', function() {
286286
beforeEach(function() {
287-
configObj = projectConfig.createProjectConfig(testData);
287+
configObj = projectConfig.createProjectConfig(cloneDeep(testData));
288288
bucketerParams = {
289289
experimentId: configObj.experiments[0].id,
290290
experimentKey: configObj.experiments[0].key,
@@ -314,7 +314,7 @@ describe('lib/core/bucketer', function() {
314314

315315
describe('when the traffic allocation has invalid variation ids', function() {
316316
beforeEach(function() {
317-
configObj = projectConfig.createProjectConfig(testData);
317+
configObj = projectConfig.createProjectConfig(cloneDeep(testData));
318318
bucketerParams = {
319319
experimentId: configObj.experiments[0].id,
320320
experimentKey: configObj.experiments[0].key,
@@ -371,7 +371,7 @@ describe('lib/core/bucketer', function() {
371371
});
372372

373373
beforeEach(function() {
374-
configObj = projectConfig.createProjectConfig(testData);
374+
configObj = projectConfig.createProjectConfig(cloneDeep(testData));
375375
bucketerParams = {
376376
trafficAllocationConfig: configObj.experiments[0].trafficAllocation,
377377
variationIdMap: configObj.variationIdMap,

packages/optimizely-sdk/lib/core/decision_service/index.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -300,14 +300,13 @@ DecisionService.prototype.__saveUserProfile = function(experiment, variation, us
300300
}
301301

302302
try {
303-
var newBucketMap = fns.cloneDeep(experimentBucketMap);
304-
newBucketMap[experiment.id] = {
305-
variation_id: variation.id,
303+
experimentBucketMap[experiment.id] = {
304+
variation_id: variation.id
306305
};
307306

308307
this.userProfileService.save({
309308
user_id: userId,
310-
experiment_bucket_map: newBucketMap,
309+
experiment_bucket_map: experimentBucketMap,
311310
});
312311

313312
this.logger.log(

packages/optimizely-sdk/lib/core/decision_service/index.tests.js

+9-9
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ var errorHandler = require('../../plugins/error_handler');
2121
var bucketer = require('../bucketer');
2222
var DecisionService = require('./');
2323
var enums = require('../../utils/enums');
24-
var fns = require('../../utils/fns');
24+
var cloneDeep = require('lodash/cloneDeep');
2525
var logger = require('../../plugins/logger');
2626
var projectConfig = require('../project_config');
2727
var sprintf = require('@optimizely/js-sdk-utils').sprintf;
@@ -40,7 +40,7 @@ var DECISION_SOURCES = enums.DECISION_SOURCES;
4040

4141
describe('lib/core/decision_service', function() {
4242
describe('APIs', function() {
43-
var configObj = projectConfig.createProjectConfig(testData);
43+
var configObj = projectConfig.createProjectConfig(cloneDeep(testData));
4444
var decisionServiceInstance;
4545
var mockLogger = logger.createLogger({ logLevel: LOG_LEVEL.INFO });
4646
var bucketerStub;
@@ -860,7 +860,7 @@ describe('lib/core/decision_service', function() {
860860
'control'
861861
);
862862
assert.strictEqual(didSetVariation, true);
863-
var newDatafile = fns.cloneDeep(testData);
863+
var newDatafile = cloneDeep(testData);
864864
// Remove 'control' variation from variations, traffic allocation, and datafile forcedVariations.
865865
newDatafile.experiments[0].variations = [
866866
{
@@ -892,7 +892,7 @@ describe('lib/core/decision_service', function() {
892892
'control'
893893
);
894894
assert.strictEqual(didSetVariation, true);
895-
var newConfigObj = projectConfig.createProjectConfig(testDataWithFeatures);
895+
var newConfigObj = projectConfig.createProjectConfig(cloneDeep(testDataWithFeatures));
896896
var forcedVar = decisionServiceInstance.getForcedVariation(newConfigObj, 'testExperiment', 'user1');
897897
assert.strictEqual(forcedVar, null);
898898
});
@@ -917,7 +917,7 @@ describe('lib/core/decision_service', function() {
917917

918918
// TODO: Move tests that test methods of Optimizely to lib/optimizely/index.tests.js
919919
describe('when a bucketingID is provided', function() {
920-
var configObj = projectConfig.createProjectConfig(testData);
920+
var configObj = projectConfig.createProjectConfig(cloneDeep(testData));
921921
var createdLogger = logger.createLogger({
922922
logLevel: LOG_LEVEL.DEBUG,
923923
logToConsole: false,
@@ -926,7 +926,7 @@ describe('lib/core/decision_service', function() {
926926
beforeEach(function() {
927927
optlyInstance = new Optimizely({
928928
clientEngine: 'node-sdk',
929-
datafile: testData,
929+
datafile: cloneDeep(testData),
930930
jsonSchemaValidator: jsonSchemaValidator,
931931
isValidInstance: true,
932932
logger: createdLogger,
@@ -1050,7 +1050,7 @@ describe('lib/core/decision_service', function() {
10501050

10511051
beforeEach(function() {
10521052
sinon.stub(mockLogger, 'log');
1053-
configObj = projectConfig.createProjectConfig(testData);
1053+
configObj = projectConfig.createProjectConfig(cloneDeep(testData));
10541054
decisionService = DecisionService.createDecisionService({
10551055
logger: mockLogger,
10561056
});
@@ -1088,7 +1088,7 @@ describe('lib/core/decision_service', function() {
10881088
var sandbox;
10891089
var mockLogger = logger.createLogger({ logLevel: LOG_LEVEL.INFO });
10901090
beforeEach(function() {
1091-
configObj = projectConfig.createProjectConfig(testDataWithFeatures);
1091+
configObj = projectConfig.createProjectConfig(cloneDeep(testDataWithFeatures));
10921092
sandbox = sinon.sandbox.create();
10931093
sandbox.stub(mockLogger, 'log');
10941094
decisionServiceInstance = DecisionService.createDecisionService({
@@ -1978,7 +1978,7 @@ describe('lib/core/decision_service', function() {
19781978
var __buildBucketerParamsSpy;
19791979

19801980
beforeEach(function() {
1981-
configObj = projectConfig.createProjectConfig(testDataWithFeatures);
1981+
configObj = projectConfig.createProjectConfig(cloneDeep(testDataWithFeatures));
19821982
feature = configObj.featureKeyMap.test_feature;
19831983
decisionService = DecisionService.createDecisionService({
19841984
logger: logger.createLogger({ logLevel: LOG_LEVEL.INFO }),

packages/optimizely-sdk/lib/core/optimizely_config/index.tests.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616
var assert = require('chai').assert;
17-
17+
var cloneDeep = require('lodash/cloneDeep');
1818
var datafile = require('../../tests/test_data').getTestProjectConfigWithFeatures();
1919
var projectConfig = require('../project_config');
2020
var optimizelyConfig = require('./index');
@@ -37,7 +37,7 @@ describe('lib/core/optimizely_config', function() {
3737
var optimizelyConfigObject;
3838
var projectConfigObject;
3939
beforeEach(function() {
40-
projectConfigObject = projectConfig.createProjectConfig(datafile);
40+
projectConfigObject = projectConfig.createProjectConfig(cloneDeep(datafile));
4141
optimizelyConfigObject = optimizelyConfig.getOptimizelyConfig(projectConfigObject);
4242
});
4343

packages/optimizely-sdk/lib/core/project_config/index.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ module.exports = {
3535
* @return {Object} Object representing project configuration
3636
*/
3737
createProjectConfig: function(datafile) {
38-
var projectConfig = fns.cloneDeep(datafile);
38+
var projectConfig = fns.assign({}, datafile);
3939

4040
/*
4141
* Conditions of audiences in projectConfig.typedAudiences are not
@@ -53,16 +53,16 @@ module.exports = {
5353

5454
var experiments;
5555
Object.keys(projectConfig.groupIdMap || {}).forEach(function(Id) {
56-
experiments = fns.cloneDeep(projectConfig.groupIdMap[Id].experiments);
56+
experiments = projectConfig.groupIdMap[Id].experiments;
5757
(experiments || []).forEach(function(experiment) {
5858
projectConfig.experiments.push(fns.assign(experiment, { groupId: Id }));
5959
});
6060
});
6161

6262
projectConfig.rolloutIdMap = fns.keyBy(projectConfig.rollouts || [], 'id');
63-
jsSdkUtils.objectValues(projectConfig.rolloutIdMap || {}).forEach(function(rollout) {
63+
jsSdkUtils.objectValues(projectConfig.rolloutIdMap || {}).forEach(function (rollout) {
6464
(rollout.experiments || []).forEach(function(experiment) {
65-
projectConfig.experiments.push(fns.cloneDeep(experiment));
65+
projectConfig.experiments.push(experiment);
6666
// Creates { <variationKey>: <variation> } map inside of the experiment
6767
experiment.variationKeyMap = fns.keyBy(experiment.variations, 'key');
6868
});

packages/optimizely-sdk/lib/core/project_config/index.tests.js

+11-10
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ var logging = require('@optimizely/js-sdk-logging');
2121

2222
var logger = logging.getLogger();
2323

24-
var _ = require('lodash/core');
24+
var forEach = require('lodash/forEach');
25+
var cloneDeep = require('lodash/cloneDeep');
2526
var fns = require('../../utils/fns');
2627
var chai = require('chai');
2728
var assert = chai.assert;
@@ -40,8 +41,8 @@ describe('lib/core/project_config', function() {
4041
var testData = testDatafile.getTestProjectConfig();
4142
var configObj = projectConfig.createProjectConfig(testData);
4243

43-
_.forEach(testData.audiences, function(audience) {
44-
audience.conditions = JSON.parse(audience.conditions);
44+
forEach(testData.audiences, function(audience) {
45+
audience.conditions = audience.conditions;
4546
});
4647

4748
assert.strictEqual(configObj.accountId, testData.accountId);
@@ -59,14 +60,14 @@ describe('lib/core/project_config', function() {
5960
assert.deepEqual(configObj.groupIdMap, expectedGroupIdMap);
6061

6162
var expectedExperiments = testData.experiments;
62-
_.forEach(configObj.groupIdMap, function(group, Id) {
63-
_.forEach(group.experiments, function(experiment) {
63+
forEach(configObj.groupIdMap, function(group, Id) {
64+
forEach(group.experiments, function(experiment) {
6465
experiment.groupId = Id;
6566
expectedExperiments.push(experiment);
6667
});
6768
});
6869

69-
_.forEach(expectedExperiments, function(experiment) {
70+
forEach(expectedExperiments, function(experiment) {
7071
experiment.variationKeyMap = fns.keyBy(experiment.variations, 'key');
7172
});
7273

@@ -242,12 +243,12 @@ describe('lib/core/project_config', function() {
242243
});
243244

244245
describe('projectConfig helper methods', function() {
245-
var testData = testDatafile.getTestProjectConfig();
246+
var testData = cloneDeep(testDatafile.getTestProjectConfig());
246247
var configObj;
247248
var createdLogger = loggerPlugin.createLogger({ logLevel: LOG_LEVEL.INFO });
248249

249250
beforeEach(function() {
250-
configObj = projectConfig.createProjectConfig(testData);
251+
configObj = projectConfig.createProjectConfig(cloneDeep(testData));
251252
sinon.stub(createdLogger, 'log');
252253
});
253254

@@ -630,14 +631,14 @@ describe('lib/core/project_config', function() {
630631

631632
describe('#getExperimentAudienceConditions', function() {
632633
it('should retrieve audiences for valid experiment key', function() {
633-
configObj = projectConfig.createProjectConfig(testData);
634+
configObj = projectConfig.createProjectConfig(cloneDeep(testData));
634635
assert.deepEqual(projectConfig.getExperimentAudienceConditions(configObj, testData.experiments[1].key), [
635636
'11154',
636637
]);
637638
});
638639

639640
it('should throw error for invalid experiment key', function() {
640-
configObj = projectConfig.createProjectConfig(testData);
641+
configObj = projectConfig.createProjectConfig(cloneDeep(testData));
641642
assert.throws(function() {
642643
projectConfig.getExperimentAudienceConditions(configObj, 'invalidExperimentKey');
643644
}, sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, 'PROJECT_CONFIG', 'invalidExperimentKey'));

packages/optimizely-sdk/lib/core/project_config/project_config_manager.tests.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ var assert = require('chai').assert;
1818
var datafileManager = require('@optimizely/js-sdk-datafile-manager');
1919
var logging = require('@optimizely/js-sdk-logging');
2020
var sinon = require('sinon');
21+
var cloneDeep = require('lodash/cloneDeep');
2122
var sprintf = require('@optimizely/js-sdk-utils').sprintf;
2223
var enums = require('../../utils/enums');
2324
var jsonSchemaValidator = require('../../utils/json_schema_validator');
@@ -156,7 +157,7 @@ describe('lib/core/project_config/project_config_manager', function() {
156157
it('should return a valid datafile from getConfig and resolve onReady with a successful result', function() {
157158
var configWithFeatures = testData.getTestProjectConfigWithFeatures();
158159
var manager = new projectConfigManager.ProjectConfigManager({
159-
datafile: configWithFeatures,
160+
datafile: cloneDeep(configWithFeatures),
160161
});
161162
assert.deepEqual(manager.getConfig(), projectConfig.createProjectConfig(configWithFeatures));
162163
return manager.onReady().then(function(result) {
@@ -180,8 +181,9 @@ describe('lib/core/project_config/project_config_manager', function() {
180181

181182
describe('with a datafile manager', function() {
182183
it('passes the correct options to datafile manager', function() {
184+
var config = testData.getTestProjectConfig()
183185
new projectConfigManager.ProjectConfigManager({
184-
datafile: testData.getTestProjectConfig(),
186+
datafile: config,
185187
sdkKey: '12345',
186188
datafileOptions: {
187189
autoUpdate: true,
@@ -192,7 +194,7 @@ describe('lib/core/project_config/project_config_manager', function() {
192194
sinon.assert.calledWithExactly(
193195
datafileManager.HttpPollingDatafileManager,
194196
sinon.match({
195-
datafile: testData.getTestProjectConfig(),
197+
datafile: config,
196198
sdkKey: '12345',
197199
autoUpdate: true,
198200
updateInterval: 10000,
@@ -206,7 +208,7 @@ describe('lib/core/project_config/project_config_manager', function() {
206208
datafileManager.HttpPollingDatafileManager.returns({
207209
start: sinon.stub(),
208210
stop: sinon.stub(),
209-
get: sinon.stub().returns(configWithFeatures),
211+
get: sinon.stub().returns(cloneDeep(configWithFeatures)),
210212
on: sinon.stub().returns(function() {}),
211213
onReady: sinon.stub().returns(Promise.resolve()),
212214
});
@@ -233,7 +235,7 @@ describe('lib/core/project_config/project_config_manager', function() {
233235
});
234236
nextDatafile.revision = '36';
235237
var fakeDatafileManager = datafileManager.HttpPollingDatafileManager.getCall(0).returnValue;
236-
fakeDatafileManager.get.returns(nextDatafile);
238+
fakeDatafileManager.get.returns(cloneDeep(nextDatafile));
237239
var updateListener = fakeDatafileManager.on.getCall(0).args[1];
238240
updateListener({ datafile: nextDatafile });
239241
assert.deepEqual(manager.getConfig(), projectConfig.createProjectConfig(nextDatafile));

packages/optimizely-sdk/lib/index.browser.tests.js

-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ var eventProcessorConfigValidator = require('./utils/event_processor_config_vali
2525

2626
var chai = require('chai');
2727
var assert = chai.assert;
28-
var find = require('lodash/find');
2928
var sinon = require('sinon');
3029

3130
var LocalStoragePendingEventsDispatcher = eventProcessor.LocalStoragePendingEventsDispatcher;

packages/optimizely-sdk/lib/optimizely/index.tests.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,10 @@ describe('lib/optimizely', function() {
222222
});
223223

224224
it('passes datafile, datafileOptions, sdkKey, and other options to the project config manager', function() {
225+
var config = testData.getTestProjectConfig();
225226
new Optimizely({
226227
clientEngine: 'node-sdk',
227-
datafile: testData.getTestProjectConfig(),
228+
datafile: config,
228229
datafileOptions: {
229230
autoUpdate: true,
230231
updateInterval: 2 * 60 * 1000,
@@ -239,7 +240,7 @@ describe('lib/optimizely', function() {
239240
});
240241
sinon.assert.calledOnce(projectConfigManager.ProjectConfigManager);
241242
sinon.assert.calledWithExactly(projectConfigManager.ProjectConfigManager, {
242-
datafile: testData.getTestProjectConfig(),
243+
datafile: config,
243244
datafileOptions: {
244245
autoUpdate: true,
245246
updateInterval: 2 * 60 * 1000,
@@ -4201,7 +4202,7 @@ describe('lib/optimizely', function() {
42014202
describe('when the variation is missing the toggle', function() {
42024203
beforeEach(function() {
42034204
var experiment = optlyInstance.projectConfigManager.getConfig().experimentKeyMap.test_shared_feature;
4204-
var variation = fns.cloneDeep(experiment.variations[0]);
4205+
var variation = experiment.variations[0];
42054206
delete variation['featureEnabled'];
42064207
sandbox.stub(optlyInstance.decisionService, 'getVariationForFeature').returns({
42074208
experiment: experiment,

packages/optimizely-sdk/lib/utils/attributes_validator/index.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
*/
2020

2121
var sprintf = require('@optimizely/js-sdk-utils').sprintf;
22-
var lodashForOwn = require('lodash/forOwn');
2322
var fns = require('../../utils/fns');
2423

2524
var ERROR_MESSAGES = require('../enums').ERROR_MESSAGES;
@@ -34,8 +33,8 @@ module.exports = {
3433
*/
3534
validate: function(attributes) {
3635
if (typeof attributes === 'object' && !Array.isArray(attributes) && attributes !== null) {
37-
lodashForOwn(attributes, function(value, key) {
38-
if (typeof value === 'undefined') {
36+
Object.keys(attributes).forEach(function(key) {
37+
if (typeof attributes[key] === 'undefined') {
3938
throw new Error(sprintf(ERROR_MESSAGES.UNDEFINED_ATTRIBUTE, MODULE_NAME, key));
4039
}
4140
});

packages/optimizely-sdk/lib/utils/fns/index.js

-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ module.exports = {
3939
return to;
4040
}
4141
},
42-
cloneDeep: require('lodash/cloneDeep'),
4342
currentTimestamp: function() {
4443
return Math.round(new Date().getTime());
4544
},

packages/optimizely-sdk/package-lock.json

+2-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)