From 24080956437fce16a6500da61b3d3cf8c6106e0d Mon Sep 17 00:00:00 2001 From: Brandon Date: Thu, 27 Jun 2019 10:51:33 -0700 Subject: [PATCH 01/10] commenting out lines using variableType --- .../optimizely-sdk/lib/optimizely/index.js | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/packages/optimizely-sdk/lib/optimizely/index.js b/packages/optimizely-sdk/lib/optimizely/index.js index 08dbfa4db..2c0d32334 100644 --- a/packages/optimizely-sdk/lib/optimizely/index.js +++ b/packages/optimizely-sdk/lib/optimizely/index.js @@ -667,6 +667,94 @@ Optimizely.prototype.getEnabledFeatures = function(userId, attributes) { * variable key is invalid, or there is a mismatch * with the type of the variable */ + +Optimizely.prototype.getFeatureVariable = function(featureKey, variableKey, userId, attributes) { + if (!this.__isValidInstance()) { + // var apiName = 'getFeatureVariable' + variableType.charAt(0).toUpperCase() + variableType.slice(1); + var apiName = 'getFeatureVariable'; + this.logger.log(LOG_LEVEL.ERROR, sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, apiName)); + return null; + } + + if (!this.__validateInputs({ feature_key: featureKey, variable_key: variableKey, user_id: userId }, attributes)) { + return null; + } + + var configObj = this.projectConfigManager.getConfig(); + if (!configObj) { + return null; + } + + var featureFlag = projectConfig.getFeatureFromKey(configObj, featureKey, this.logger); + if (!featureFlag) { + return null; + } + + var variable = projectConfig.getVariableForFeature(configObj, featureKey, variableKey, this.logger); + if (!variable) { + return null; + } + + // if (variable.type !== variableType) { + // this.logger.log( + // LOG_LEVEL.WARNING, + // sprintf(LOG_MESSAGES.VARIABLE_REQUESTED_WITH_WRONG_TYPE, MODULE_NAME, variableType, variable.type) + // ); + // return null; + // } + + var featureEnabled = false; + var variableValue = variable.defaultValue; + var decision = this.decisionService.getVariationForFeature(configObj, featureFlag, userId, attributes); + + if (decision.variation !== null) { + featureEnabled = decision.variation.featureEnabled; + var value = projectConfig.getVariableValueForVariation(configObj, variable, decision.variation, this.logger); + if (value !== null) { + if (featureEnabled === true) { + variableValue = value; + this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.USER_RECEIVED_VARIABLE_VALUE, MODULE_NAME, variableKey, featureFlag.key, variableValue, userId)); + } else { + this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.FEATURE_NOT_ENABLED_RETURN_DEFAULT_VARIABLE_VALUE, MODULE_NAME, + featureFlag.key, userId, variableKey)); + } + } else { + this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.VARIABLE_NOT_USED_RETURN_DEFAULT_VARIABLE_VALUE, MODULE_NAME, variableKey, decision.variation.key)); + } + } else { + this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.USER_RECEIVED_DEFAULT_VARIABLE_VALUE, MODULE_NAME, userId, + variableKey, featureFlag.key)); + } + + var sourceInfo = {}; + if (decision.decisionSource === DECISION_SOURCES.FEATURE_TEST) { + sourceInfo = { + experimentKey: decision.experiment.key, + variationKey: decision.variation.key, + } + } + + var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variableType, this.logger); + this.notificationCenter.sendNotifications( + NOTIFICATION_TYPES.DECISION, + { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: userId, + attributes: attributes || {}, + decisionInfo: { + featureKey: featureKey, + featureEnabled: featureEnabled, + source: decision.decisionSource, + variableKey: variableKey, + variableValue: typeCastedValue, + variableType: variableType, + sourceInfo: sourceInfo, + } + } + ); + return typeCastedValue; +}; + Optimizely.prototype._getFeatureVariableForType = function(featureKey, variableKey, variableType, userId, attributes) { if (!this.__isValidInstance()) { var apiName = 'getFeatureVariable' + variableType.charAt(0).toUpperCase() + variableType.slice(1); From d3fe50108d6f8902473812b39e05338a8399ea84 Mon Sep 17 00:00:00 2001 From: Brandon Date: Thu, 27 Jun 2019 13:34:33 -0700 Subject: [PATCH 02/10] initial refactor for getFeatureVariable --- .../optimizely-sdk/lib/optimizely/index.js | 179 +++++++++--------- 1 file changed, 90 insertions(+), 89 deletions(-) diff --git a/packages/optimizely-sdk/lib/optimizely/index.js b/packages/optimizely-sdk/lib/optimizely/index.js index 2c0d32334..7e2b706af 100644 --- a/packages/optimizely-sdk/lib/optimizely/index.js +++ b/packages/optimizely-sdk/lib/optimizely/index.js @@ -734,7 +734,7 @@ Optimizely.prototype.getFeatureVariable = function(featureKey, variableKey, user } } - var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variableType, this.logger); + // var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variableType, this.logger); this.notificationCenter.sendNotifications( NOTIFICATION_TYPES.DECISION, { @@ -746,100 +746,101 @@ Optimizely.prototype.getFeatureVariable = function(featureKey, variableKey, user featureEnabled: featureEnabled, source: decision.decisionSource, variableKey: variableKey, - variableValue: typeCastedValue, - variableType: variableType, + variableValue: variableValue, + variableType: variable.type, sourceInfo: sourceInfo, } } ); - return typeCastedValue; + return variableValue; + // return typeCastedValue; }; -Optimizely.prototype._getFeatureVariableForType = function(featureKey, variableKey, variableType, userId, attributes) { - if (!this.__isValidInstance()) { - var apiName = 'getFeatureVariable' + variableType.charAt(0).toUpperCase() + variableType.slice(1); - this.logger.log(LOG_LEVEL.ERROR, sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, apiName)); - return null; - } - - if (!this.__validateInputs({ feature_key: featureKey, variable_key: variableKey, user_id: userId }, attributes)) { - return null; - } - - var configObj = this.projectConfigManager.getConfig(); - if (!configObj) { - return null; - } - - var featureFlag = projectConfig.getFeatureFromKey(configObj, featureKey, this.logger); - if (!featureFlag) { - return null; - } - - var variable = projectConfig.getVariableForFeature(configObj, featureKey, variableKey, this.logger); - if (!variable) { - return null; - } - - if (variable.type !== variableType) { - this.logger.log( - LOG_LEVEL.WARNING, - sprintf(LOG_MESSAGES.VARIABLE_REQUESTED_WITH_WRONG_TYPE, MODULE_NAME, variableType, variable.type) - ); - return null; - } - - var featureEnabled = false; - var variableValue = variable.defaultValue; - var decision = this.decisionService.getVariationForFeature(configObj, featureFlag, userId, attributes); - - if (decision.variation !== null) { - featureEnabled = decision.variation.featureEnabled; - var value = projectConfig.getVariableValueForVariation(configObj, variable, decision.variation, this.logger); - if (value !== null) { - if (featureEnabled === true) { - variableValue = value; - this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.USER_RECEIVED_VARIABLE_VALUE, MODULE_NAME, variableKey, featureFlag.key, variableValue, userId)); - } else { - this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.FEATURE_NOT_ENABLED_RETURN_DEFAULT_VARIABLE_VALUE, MODULE_NAME, - featureFlag.key, userId, variableKey)); - } - } else { - this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.VARIABLE_NOT_USED_RETURN_DEFAULT_VARIABLE_VALUE, MODULE_NAME, variableKey, decision.variation.key)); - } - } else { - this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.USER_RECEIVED_DEFAULT_VARIABLE_VALUE, MODULE_NAME, userId, - variableKey, featureFlag.key)); - } - - var sourceInfo = {}; - if (decision.decisionSource === DECISION_SOURCES.FEATURE_TEST) { - sourceInfo = { - experimentKey: decision.experiment.key, - variationKey: decision.variation.key, - } - } - - var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variableType, this.logger); - this.notificationCenter.sendNotifications( - NOTIFICATION_TYPES.DECISION, - { - type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, - userId: userId, - attributes: attributes || {}, - decisionInfo: { - featureKey: featureKey, - featureEnabled: featureEnabled, - source: decision.decisionSource, - variableKey: variableKey, - variableValue: typeCastedValue, - variableType: variableType, - sourceInfo: sourceInfo, - } - } - ); - return typeCastedValue; -}; +// Optimizely.prototype._getFeatureVariableForType = function(featureKey, variableKey, variableType, userId, attributes) { +// if (!this.__isValidInstance()) { +// var apiName = 'getFeatureVariable' + variableType.charAt(0).toUpperCase() + variableType.slice(1); +// this.logger.log(LOG_LEVEL.ERROR, sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, apiName)); +// return null; +// } + +// if (!this.__validateInputs({ feature_key: featureKey, variable_key: variableKey, user_id: userId }, attributes)) { +// return null; +// } + +// var configObj = this.projectConfigManager.getConfig(); +// if (!configObj) { +// return null; +// } + +// var featureFlag = projectConfig.getFeatureFromKey(configObj, featureKey, this.logger); +// if (!featureFlag) { +// return null; +// } + +// var variable = projectConfig.getVariableForFeature(configObj, featureKey, variableKey, this.logger); +// if (!variable) { +// return null; +// } + +// if (variable.type !== variableType) { +// this.logger.log( +// LOG_LEVEL.WARNING, +// sprintf(LOG_MESSAGES.VARIABLE_REQUESTED_WITH_WRONG_TYPE, MODULE_NAME, variableType, variable.type) +// ); +// return null; +// } + +// var featureEnabled = false; +// var variableValue = variable.defaultValue; +// var decision = this.decisionService.getVariationForFeature(configObj, featureFlag, userId, attributes); + +// if (decision.variation !== null) { +// featureEnabled = decision.variation.featureEnabled; +// var value = projectConfig.getVariableValueForVariation(configObj, variable, decision.variation, this.logger); +// if (value !== null) { +// if (featureEnabled === true) { +// variableValue = value; +// this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.USER_RECEIVED_VARIABLE_VALUE, MODULE_NAME, variableKey, featureFlag.key, variableValue, userId)); +// } else { +// this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.FEATURE_NOT_ENABLED_RETURN_DEFAULT_VARIABLE_VALUE, MODULE_NAME, +// featureFlag.key, userId, variableKey)); +// } +// } else { +// this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.VARIABLE_NOT_USED_RETURN_DEFAULT_VARIABLE_VALUE, MODULE_NAME, variableKey, decision.variation.key)); +// } +// } else { +// this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.USER_RECEIVED_DEFAULT_VARIABLE_VALUE, MODULE_NAME, userId, +// variableKey, featureFlag.key)); +// } + +// var sourceInfo = {}; +// if (decision.decisionSource === DECISION_SOURCES.FEATURE_TEST) { +// sourceInfo = { +// experimentKey: decision.experiment.key, +// variationKey: decision.variation.key, +// } +// } + +// var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variableType, this.logger); +// this.notificationCenter.sendNotifications( +// NOTIFICATION_TYPES.DECISION, +// { +// type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, +// userId: userId, +// attributes: attributes || {}, +// decisionInfo: { +// featureKey: featureKey, +// featureEnabled: featureEnabled, +// source: decision.decisionSource, +// variableKey: variableKey, +// variableValue: typeCastedValue, +// variableType: variableType, +// sourceInfo: sourceInfo, +// } +// } +// ); +// return typeCastedValue; +// }; /** * Returns value for the given boolean variable attached to the given feature From 8089dcff6681725e0d663c45f49061ffd9b80326 Mon Sep 17 00:00:00 2001 From: Brandon Date: Thu, 27 Jun 2019 14:05:03 -0700 Subject: [PATCH 03/10] re-add typeCastedValue --- .../optimizely-sdk/lib/optimizely/index.js | 8 +- .../lib/optimizely/index.tests.js | 344 +++++++++--------- packages/optimizely-sdk/package-lock.json | 45 ++- 3 files changed, 209 insertions(+), 188 deletions(-) diff --git a/packages/optimizely-sdk/lib/optimizely/index.js b/packages/optimizely-sdk/lib/optimizely/index.js index 7e2b706af..88f5be20f 100644 --- a/packages/optimizely-sdk/lib/optimizely/index.js +++ b/packages/optimizely-sdk/lib/optimizely/index.js @@ -734,7 +734,7 @@ Optimizely.prototype.getFeatureVariable = function(featureKey, variableKey, user } } - // var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variableType, this.logger); + var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variable.type, this.logger); this.notificationCenter.sendNotifications( NOTIFICATION_TYPES.DECISION, { @@ -746,14 +746,14 @@ Optimizely.prototype.getFeatureVariable = function(featureKey, variableKey, user featureEnabled: featureEnabled, source: decision.decisionSource, variableKey: variableKey, - variableValue: variableValue, + variableValue: typeCastedValue, variableType: variable.type, sourceInfo: sourceInfo, } } ); - return variableValue; - // return typeCastedValue; + // return variableValue; + return typeCastedValue; }; // Optimizely.prototype._getFeatureVariableForType = function(featureKey, variableKey, variableType, userId, attributes) { diff --git a/packages/optimizely-sdk/lib/optimizely/index.tests.js b/packages/optimizely-sdk/lib/optimizely/index.tests.js index 28597c194..e84e38f09 100644 --- a/packages/optimizely-sdk/lib/optimizely/index.tests.js +++ b/packages/optimizely-sdk/lib/optimizely/index.tests.js @@ -2644,8 +2644,8 @@ describe('lib/optimizely', function() { }); }); - it('returns the right value from getFeatureVariableBoolean and send notification with featureEnabled true', function() { - var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); + it('returns the right value from getFeatureVariable and send notification with featureEnabled true', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, true); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2666,8 +2666,8 @@ describe('lib/optimizely', function() { }); }); - it('returns the right value from getFeatureVariableDouble and send notification with featureEnabled true', function() { - var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); + it('returns the right value from getFeatureVariable and send notification with featureEnabled true', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 20.25); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2688,8 +2688,8 @@ describe('lib/optimizely', function() { }); }); - it('returns the right value from getFeatureVariableInteger and send notification with featureEnabled true', function() { - var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); + it('returns the right value from getFeatureVariable and send notification with featureEnabled true', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 2); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2710,8 +2710,8 @@ describe('lib/optimizely', function() { }); }); - it('returns the right value from getFeatureVariableString and send notification with featureEnabled true', function() { - var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); + it('returns the right value from getFeatureVariable and send notification with featureEnabled true', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 'Buy me NOW'); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2744,8 +2744,8 @@ describe('lib/optimizely', function() { }); }); - it('returns the default value from getFeatureVariableBoolean and send notification with featureEnabled false', function() { - var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); + it('returns the default value from getFeatureVariable and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, false); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2766,8 +2766,8 @@ describe('lib/optimizely', function() { }); }); - it('returns the default value from getFeatureVariableDouble and send notification with featureEnabled false', function() { - var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); + it('returns the default value from getFeatureVariable and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 50.55); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2788,8 +2788,8 @@ describe('lib/optimizely', function() { }); }); - it('returns the default value from getFeatureVariableInteger and send notification with featureEnabled false', function() { - var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); + it('returns the default value from getFeatureVariable and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 10); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2810,8 +2810,8 @@ describe('lib/optimizely', function() { }); }); - it('returns the default value from getFeatureVariableString and send notification with featureEnabled false', function() { - var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); + it('returns the default value from getFeatureVariable and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 'Buy me'); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2846,8 +2846,8 @@ describe('lib/optimizely', function() { }); }); - it('should return the right value from getFeatureVariableBoolean and send notification with featureEnabled true', function() { - var result = optlyInstance.getFeatureVariableBoolean('test_feature', 'new_content', 'user1', { test_attribute: 'test_value' }); + it('should return the right value from getFeatureVariable and send notification with featureEnabled true', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'new_content', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, true); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2865,8 +2865,8 @@ describe('lib/optimizely', function() { }); }); - it('should return the right value from getFeatureVariableDouble and send notification with featureEnabled true', function() { - var result = optlyInstance.getFeatureVariableDouble('test_feature', 'price', 'user1', { test_attribute: 'test_value' }); + it('should return the right value from getFeatureVariable and send notification with featureEnabled true', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'price', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 4.99); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2884,8 +2884,8 @@ describe('lib/optimizely', function() { }); }); - it('should return the right value from getFeatureVariableInteger and send notification with featureEnabled true', function() { - var result = optlyInstance.getFeatureVariableInteger('test_feature', 'lasers', 'user1', { test_attribute: 'test_value' }); + it('should return the right value from getFeatureVariable and send notification with featureEnabled true', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'lasers', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 395); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2903,8 +2903,8 @@ describe('lib/optimizely', function() { }); }); - it('should return the right value from getFeatureVariableString and send notification with featureEnabled true', function() { - var result = optlyInstance.getFeatureVariableString('test_feature', 'message', 'user1', { test_attribute: 'test_value' }); + it('should return the right value from getFeatureVariable and send notification with featureEnabled true', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'message', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 'Hello audience'); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2934,8 +2934,8 @@ describe('lib/optimizely', function() { }); }); - it('should return the default value from getFeatureVariableBoolean and send notification with featureEnabled false', function() { - var result = optlyInstance.getFeatureVariableBoolean('test_feature', 'new_content', 'user1', { test_attribute: 'test_value' }); + it('should return the default value from getFeatureVariable and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'new_content', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, false); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2953,8 +2953,8 @@ describe('lib/optimizely', function() { }); }); - it('should return the default value from getFeatureVariableDouble and send notification with featureEnabled false', function() { - var result = optlyInstance.getFeatureVariableDouble('test_feature', 'price', 'user1', { test_attribute: 'test_value' }); + it('should return the default value from getFeatureVariable and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'price', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 14.99); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2972,8 +2972,8 @@ describe('lib/optimizely', function() { }); }); - it('should return the default value from getFeatureVariableInteger and send notification with featureEnabled false', function() { - var result = optlyInstance.getFeatureVariableInteger('test_feature', 'lasers', 'user1', { test_attribute: 'test_value' }); + it('should return the default value from getFeatureVariable and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'lasers', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 400); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2991,8 +2991,8 @@ describe('lib/optimizely', function() { }); }); - it('should return the default value from getFeatureVariableString and send notification with featureEnabled false', function() { - var result = optlyInstance.getFeatureVariableString('test_feature', 'message', 'user1', { test_attribute: 'test_value' }); + it('should return the default value from getFeatureVariable and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'message', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 'Hello'); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -3021,8 +3021,8 @@ describe('lib/optimizely', function() { }); }); - it('returns the variable default value from getFeatureVariableBoolean and send notification with featureEnabled false', function() { - var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, false); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -3040,8 +3040,8 @@ describe('lib/optimizely', function() { }); }); - it('returns the variable default value from getFeatureVariableDouble and send notification with featureEnabled false', function() { - var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 50.55); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -3059,8 +3059,8 @@ describe('lib/optimizely', function() { }); }); - it('returns the variable default value from getFeatureVariableInteger and send notification with featureEnabled false', function() { - var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 10); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -3078,8 +3078,8 @@ describe('lib/optimizely', function() { }); }); - it('returns the variable default value from getFeatureVariableString and send notification with featureEnabled false', function() { - var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 'Buy me'); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -3763,26 +3763,26 @@ describe('lib/optimizely', function() { }); }); - it('returns the right value from getFeatureVariableBoolean', function() { - var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); + it('returns the right value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, true); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Value for variable "is_button_animated" of feature flag "test_feature_for_experiment" is true for user "user1"'); }); - it('returns the right value from getFeatureVariableDouble', function() { - var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); + it('returns the right value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 20.25); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Value for variable "button_width" of feature flag "test_feature_for_experiment" is 20.25 for user "user1"'); }); - it('returns the right value from getFeatureVariableInteger', function() { - var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); + it('returns the right value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 2); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Value for variable "num_buttons" of feature flag "test_feature_for_experiment" is 2 for user "user1"'); }); - it('returns the right value from getFeatureVariableString', function() { - var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); + it('returns the right value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 'Buy me NOW'); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Value for variable "button_txt" of feature flag "test_feature_for_experiment" is Buy me NOW for user "user1"'); }); @@ -3792,26 +3792,26 @@ describe('lib/optimizely', function() { sandbox.stub(projectConfig, 'getVariableValueForVariation').returns(null); }); - it('returns the variable default value from getFeatureVariableBoolean', function() { - var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, false); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Variable "is_button_animated" is not used in variation "variation". Returning default value.'); }); - it('returns the variable default value from getFeatureVariableDouble', function() { - var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 50.55); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Variable "button_width" is not used in variation "variation". Returning default value.'); }); - it('returns the variable default value from getFeatureVariableInteger', function() { - var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 10); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Variable "num_buttons" is not used in variation "variation". Returning default value.'); }); - it('returns the variable default value from getFeatureVariableString', function() { - var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 'Buy me'); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Variable "button_txt" is not used in variation "variation". Returning default value.'); }); @@ -3829,26 +3829,26 @@ describe('lib/optimizely', function() { }); }); - it('returns the variable default value from getFeatureVariableBoolean', function() { - var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, false); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature_for_experiment" is not enabled for user user1. Returning default value for variable "is_button_animated".'); }); - it('returns the variable default value from getFeatureVariableDouble', function() { - var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 50.55); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature_for_experiment" is not enabled for user user1. Returning default value for variable "button_width".'); }); - it('returns the variable default value from getFeatureVariableInteger', function() { - var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 10); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature_for_experiment" is not enabled for user user1. Returning default value for variable "num_buttons".'); }); - it('returns the variable default value from getFeatureVariableString', function() { - var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 'Buy me'); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature_for_experiment" is not enabled for user user1. Returning default value for variable "button_txt".'); }); @@ -3867,26 +3867,26 @@ describe('lib/optimizely', function() { }); }); - it('returns the right value from getFeatureVariableBoolean', function() { - var result = optlyInstance.getFeatureVariableBoolean('test_feature', 'new_content', 'user1', { test_attribute: 'test_value' }); + it('returns the right value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'new_content', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, true); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Value for variable "new_content" of feature flag "test_feature" is true for user "user1"'); }); - it('returns the right value from getFeatureVariableDouble', function() { - var result = optlyInstance.getFeatureVariableDouble('test_feature', 'price', 'user1', { test_attribute: 'test_value' }); + it('returns the right value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'price', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 4.99); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Value for variable "price" of feature flag "test_feature" is 4.99 for user "user1"'); }); - it('returns the right value from getFeatureVariableInteger', function() { - var result = optlyInstance.getFeatureVariableInteger('test_feature', 'lasers', 'user1', { test_attribute: 'test_value' }); + it('returns the right value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'lasers', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 395); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Value for variable "lasers" of feature flag "test_feature" is 395 for user "user1"'); }); - it('returns the right value from getFeatureVariableString', function() { - var result = optlyInstance.getFeatureVariableString('test_feature', 'message', 'user1', { test_attribute: 'test_value' }); + it('returns the right value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'message', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 'Hello audience'); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Value for variable "message" of feature flag "test_feature" is Hello audience for user "user1"'); }); @@ -3896,26 +3896,26 @@ describe('lib/optimizely', function() { sandbox.stub(projectConfig, 'getVariableValueForVariation').returns(null); }); - it('returns the variable default value from getFeatureVariableBoolean', function() { - var result = optlyInstance.getFeatureVariableBoolean('test_feature', 'new_content', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'new_content', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, false); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Variable "new_content" is not used in variation "594032". Returning default value.'); }); - it('returns the variable default value from getFeatureVariableDouble', function() { - var result = optlyInstance.getFeatureVariableDouble('test_feature', 'price', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'price', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 14.99); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Variable "price" is not used in variation "594032". Returning default value.'); }); - it('returns the variable default value from getFeatureVariableInteger', function() { - var result = optlyInstance.getFeatureVariableInteger('test_feature', 'lasers', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'lasers', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 400); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Variable "lasers" is not used in variation "594032". Returning default value.'); }); - it('returns the variable default value from getFeatureVariableString', function() { - var result = optlyInstance.getFeatureVariableString('test_feature', 'message', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'message', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 'Hello'); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Variable "message" is not used in variation "594032". Returning default value.'); }); @@ -3933,26 +3933,26 @@ describe('lib/optimizely', function() { }); }); - it('returns the variable default value from getFeatureVariableBoolean', function() { - var result = optlyInstance.getFeatureVariableBoolean('test_feature', 'new_content', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'new_content', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, false); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature" is not enabled for user user1. Returning default value for variable "new_content".'); }); - it('returns the variable default value from getFeatureVariableDouble', function() { - var result = optlyInstance.getFeatureVariableDouble('test_feature', 'price', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'price', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 14.99); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature" is not enabled for user user1. Returning default value for variable "price".'); }); - it('returns the variable default value from getFeatureVariableInteger', function() { - var result = optlyInstance.getFeatureVariableInteger('test_feature', 'lasers', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'lasers', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 400); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature" is not enabled for user user1. Returning default value for variable "lasers".'); }); - it('returns the variable default value from getFeatureVariableString', function() { - var result = optlyInstance.getFeatureVariableString('test_feature', 'message', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature', 'message', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 'Hello'); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature" is not enabled for user user1. Returning default value for variable "message".'); }); @@ -3968,123 +3968,123 @@ describe('lib/optimizely', function() { }); }); - it('returns the variable default value from getFeatureVariableBoolean', function() { - var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, false); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: User "user1" is not in any variation or rollout rule. Returning default value for variable "is_button_animated" of feature flag "test_feature_for_experiment".'); }); - it('returns the variable default value from getFeatureVariableDouble', function() { - var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 50.55); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: User "user1" is not in any variation or rollout rule. Returning default value for variable "button_width" of feature flag "test_feature_for_experiment".'); }); - it('returns the variable default value from getFeatureVariableInteger', function() { - var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 10); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: User "user1" is not in any variation or rollout rule. Returning default value for variable "num_buttons" of feature flag "test_feature_for_experiment".'); }); - it('returns the variable default value from getFeatureVariableString', function() { - var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 'Buy me'); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: User "user1" is not in any variation or rollout rule. Returning default value for variable "button_txt" of feature flag "test_feature_for_experiment".'); }); }); - it('returns null from getFeatureVariableBoolean when called with a non-boolean variable', function() { - var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'button_width', 'user1'); + it('returns null from getFeatureVariable when called with a non-boolean variable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', 'user1'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "boolean", but variable is of type "double". Use correct API to retrieve value. Returning None.'); }); - it('returns null from getFeatureVariableDouble when called with a non-double variable', function() { - var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'is_button_animated', 'user1'); + it('returns null from getFeatureVariable when called with a non-double variable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated', 'user1'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "double", but variable is of type "boolean". Use correct API to retrieve value. Returning None.'); }); - it('returns null from getFeatureVariableInteger when called with a non-integer variable', function() { - var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'button_width', 'user1'); + it('returns null from getFeatureVariable when called with a non-integer variable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', 'user1'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "integer", but variable is of type "double". Use correct API to retrieve value. Returning None.'); }); - it('returns null from getFeatureVariableString when called with a non-string variable', function() { - var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'num_buttons', 'user1'); + it('returns null from getFeatureVariable when called with a non-string variable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons', 'user1'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "string", but variable is of type "integer". Use correct API to retrieve value. Returning None.'); }); - it('returns null from getFeatureVariableBoolean if user id is null', function() { - var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', null, { test_attribute: 'test_value' }); + it('returns null from getFeatureVariable if user id is null', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated', null, { test_attribute: 'test_value' }); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); }); - it('returns null from getFeatureVariableBoolean if user id is undefined', function() { - var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', undefined, { test_attribute: 'test_value' }); + it('returns null from getFeatureVariable if user id is undefined', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated', undefined, { test_attribute: 'test_value' }); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); }); - it('returns null from getFeatureVariableBoolean if user id is not provided', function() { - var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated'); + it('returns null from getFeatureVariable if user id is not provided', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); }); - it('returns null from getFeatureVariableDouble if user id is null', function() { - var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', null, { test_attribute: 'test_value' }); + it('returns null from getFeatureVariable if user id is null', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', null, { test_attribute: 'test_value' }); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); }); - it('returns null from getFeatureVariableDouble if user id is undefined', function() { - var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', undefined, { test_attribute: 'test_value' }); + it('returns null from getFeatureVariable if user id is undefined', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', undefined, { test_attribute: 'test_value' }); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); }); - it('returns null from getFeatureVariableDouble if user id is not provided', function() { - var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width'); + it('returns null from getFeatureVariable if user id is not provided', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); }); - it('returns null from getFeatureVariableInteger if user id is null', function() { - var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', null, { test_attribute: 'test_value' }); + it('returns null from getFeatureVariable if user id is null', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons', null, { test_attribute: 'test_value' }); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); }); - it('returns null from getFeatureVariableInteger if user id is undefined', function() { - var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', undefined, { test_attribute: 'test_value' }); + it('returns null from getFeatureVariable if user id is undefined', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons', undefined, { test_attribute: 'test_value' }); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); }); - it('returns null from getFeatureVariableInteger if user id is not provided', function() { - var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons'); + it('returns null from getFeatureVariable if user id is not provided', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); }); - it('returns null from getFeatureVariableString if user id is null', function() { - var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt', null, { test_attribute: 'test_value' }); + it('returns null from getFeatureVariable if user id is null', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_txt', null, { test_attribute: 'test_value' }); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); }); - it('returns null from getFeatureVariableString if user id is undefined', function() { - var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt', undefined, { test_attribute: 'test_value' }); + it('returns null from getFeatureVariable if user id is undefined', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_txt', undefined, { test_attribute: 'test_value' }); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); }); - it('returns null from getFeatureVariableString if user id is not provided', function() { - var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt'); + it('returns null from getFeatureVariable if user id is not provided', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_txt'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); }); @@ -4096,7 +4096,7 @@ describe('lib/optimizely', function() { }); it('should return null and log an error', function() { - var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', 'user1'); + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated', 'user1'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Unable to cast value falsezzz to type boolean, returning null.'); }); @@ -4108,7 +4108,7 @@ describe('lib/optimizely', function() { }); it('should return null and log an error', function() { - var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', 'user1'); + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons', 'user1'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Unable to cast value zzz123 to type integer, returning null.'); }); @@ -4120,62 +4120,62 @@ describe('lib/optimizely', function() { }); it('should return null and log an error', function() { - var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', 'user1'); + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', 'user1'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Unable to cast value zzz44.55 to type double, returning null.'); }); }); }); - it('returns null from getFeatureVariableBoolean if the argument feature key is invalid', function() { - var result = optlyInstance.getFeatureVariableBoolean('thisIsNotAValidKey<><><>', 'is_button_animated', 'user1'); + it('returns null from getFeatureVariable if the argument feature key is invalid', function() { + var result = optlyInstance.getFeatureVariable('thisIsNotAValidKey<><><>', 'is_button_animated', 'user1'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Feature key thisIsNotAValidKey<><><> is not in datafile.'); }); - it('returns null from getFeatureVariableDouble if the argument feature key is invalid', function() { - var result = optlyInstance.getFeatureVariableDouble('thisIsNotAValidKey<><><>', 'button_width', 'user1'); + it('returns null from getFeatureVariable if the argument feature key is invalid', function() { + var result = optlyInstance.getFeatureVariable('thisIsNotAValidKey<><><>', 'button_width', 'user1'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Feature key thisIsNotAValidKey<><><> is not in datafile.'); }); - it('returns null from getFeatureVariableInteger if the argument feature key is invalid', function() { - var result = optlyInstance.getFeatureVariableInteger('thisIsNotAValidKey<><><>', 'num_buttons', 'user1'); + it('returns null from getFeatureVariable if the argument feature key is invalid', function() { + var result = optlyInstance.getFeatureVariable('thisIsNotAValidKey<><><>', 'num_buttons', 'user1'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Feature key thisIsNotAValidKey<><><> is not in datafile.'); }); - it('returns null from getFeatureVariableString if the argument feature key is invalid', function() { - var result = optlyInstance.getFeatureVariableString('thisIsNotAValidKey<><><>', 'button_txt', 'user1'); + it('returns null from getFeatureVariable if the argument feature key is invalid', function() { + var result = optlyInstance.getFeatureVariable('thisIsNotAValidKey<><><>', 'button_txt', 'user1'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Feature key thisIsNotAValidKey<><><> is not in datafile.'); }); - it('returns null from getFeatureVariableBoolean if the argument variable key is invalid', function() { - var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); + it('returns null from getFeatureVariable if the argument variable key is invalid', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Variable with key "thisIsNotAVariableKey****" associated with feature with key "test_feature_for_experiment" is not in datafile.'); }); - it('returns null from getFeatureVariableDouble if the argument variable key is invalid', function() { - var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); + it('returns null from getFeatureVariable if the argument variable key is invalid', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Variable with key "thisIsNotAVariableKey****" associated with feature with key "test_feature_for_experiment" is not in datafile.'); }); - it('returns null from getFeatureVariableInteger if the argument variable key is invalid', function() { - var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); + it('returns null from getFeatureVariable if the argument variable key is invalid', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Variable with key "thisIsNotAVariableKey****" associated with feature with key "test_feature_for_experiment" is not in datafile.'); }); - it('returns null from getFeatureVariableString if the argument variable key is invalid', function() { - var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); + it('returns null from getFeatureVariable if the argument variable key is invalid', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Variable with key "thisIsNotAVariableKey****" associated with feature with key "test_feature_for_experiment" is not in datafile.'); }); - it('returns null from getFeatureVariableBoolean when optimizely object is not a valid instance', function() { + it('returns null from getFeatureVariable when optimizely object is not a valid instance', function() { var instance = new Optimizely({ datafile: {}, errorHandler: errorHandler, @@ -4185,14 +4185,14 @@ describe('lib/optimizely', function() { createdLogger.log.reset(); - instance.getFeatureVariableBoolean('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); + instance.getFeatureVariable('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); sinon.assert.calledOnce(createdLogger.log); var logMessage = createdLogger.log.args[0][1]; - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariableBoolean')); + assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariable')); }); - it('returns null from getFeatureVariableDouble when optimizely object is not a valid instance', function() { + it('returns null from getFeatureVariable when optimizely object is not a valid instance', function() { var instance = new Optimizely({ datafile: {}, errorHandler: errorHandler, @@ -4202,14 +4202,14 @@ describe('lib/optimizely', function() { createdLogger.log.reset(); - instance.getFeatureVariableDouble('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); + instance.getFeatureVariable('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); sinon.assert.calledOnce(createdLogger.log); var logMessage = createdLogger.log.args[0][1]; - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariableDouble')); + assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariable')); }); - it('returns null from getFeatureVariableInteger when optimizely object is not a valid instance', function() { + it('returns null from getFeatureVariable when optimizely object is not a valid instance', function() { var instance = new Optimizely({ datafile: {}, errorHandler: errorHandler, @@ -4219,14 +4219,14 @@ describe('lib/optimizely', function() { createdLogger.log.reset(); - instance.getFeatureVariableInteger('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); + instance.getFeatureVariable('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); sinon.assert.calledOnce(createdLogger.log); var logMessage = createdLogger.log.args[0][1]; - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariableInteger')); + assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariable')); }); - it('returns null from getFeatureVariableString when optimizely object is not a valid instance', function() { + it('returns null from getFeatureVariable when optimizely object is not a valid instance', function() { var instance = new Optimizely({ datafile: {}, errorHandler: errorHandler, @@ -4236,11 +4236,11 @@ describe('lib/optimizely', function() { createdLogger.log.reset(); - instance.getFeatureVariableString('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); + instance.getFeatureVariable('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); sinon.assert.calledOnce(createdLogger.log); var logMessage = createdLogger.log.args[0][1]; - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariableString')); + assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariable')); }); }); }); @@ -4336,22 +4336,22 @@ describe('lib/optimizely', function() { assert.isFalse(featureEnabled); }); - it('can return a variable value from a feature test with a typed audience via getFeatureVariableString', function() { - var variableValue = optlyInstance.getFeatureVariableString('feat_with_var', 'x', 'user1', { + it('can return a variable value from a feature test with a typed audience via getFeatureVariable', function() { + var variableValue = optlyInstance.getFeatureVariable('feat_with_var', 'x', 'user1', { // Should be included in the feature test via greater-than match audience with id '3468206647' lasers: 71, }); assert.strictEqual(variableValue, 'xyz'); - variableValue = optlyInstance.getFeatureVariableString('feat_with_var', 'x', 'user1', { + variableValue = optlyInstance.getFeatureVariable('feat_with_var', 'x', 'user1', { // Should be included in the feature test via exact match boolean audience with id '3468206643' should_do_it: true, }); assert.strictEqual(variableValue, 'xyz'); }); - it('can return the default value from a feature variable from getFeatureVariableString, via excluding a user from a feature test with a typed audience', function() { - var variableValue = optlyInstance.getFeatureVariableString('feat_with_var', 'x', 'user1', { + it('can return the default value from a feature variable from getFeatureVariable, via excluding a user from a feature test with a typed audience', function() { + var variableValue = optlyInstance.getFeatureVariable('feat_with_var', 'x', 'user1', { lasers: 50, }); assert.strictEqual(variableValue, 'x'); @@ -4478,8 +4478,8 @@ describe('lib/optimizely', function() { ); }); - it('can return a variable value from a feature test with complex audience conditions via getFeatureVariableString', function() { - var variableValue = optlyInstance.getFeatureVariableInteger('feat2_with_var', 'z', 'user1', { + it('can return a variable value from a feature test with complex audience conditions via getFeatureVariable', function() { + var variableValue = optlyInstance.getFeatureVariable('feat2_with_var', 'z', 'user1', { // Should be included via exact match string audience with id '3468206642', and // greater than audience with id '3468206647' house: 'Gryffindor', @@ -4494,8 +4494,8 @@ describe('lib/optimizely', function() { ); }); - it('can return the default value for a feature variable from getFeatureVariableString, via excluding a user from a feature test with complex audience conditions', function() { - var variableValue = optlyInstance.getFeatureVariableInteger('feat2_with_var', 'z', 'user1', { + it('can return the default value for a feature variable from getFeatureVariable, via excluding a user from a feature test with complex audience conditions', function() { + var variableValue = optlyInstance.getFeatureVariable('feat2_with_var', 'z', 'user1', { // Should be excluded - no audiences match with no attributes }); assert.strictEqual(variableValue, 10); @@ -4888,10 +4888,10 @@ describe('lib/optimizely', function() { assert.isNull(optlyInstance.getForcedVariation('my_experiment', 'user1')); assert.isFalse(optlyInstance.isFeatureEnabled('my_feature', 'user1')); assert.deepEqual(optlyInstance.getEnabledFeatures('user1'), []); - assert.isNull(optlyInstance.getFeatureVariableBoolean('my_feature', 'my_bool_var', 'user1')); - assert.isNull(optlyInstance.getFeatureVariableDouble('my_feature', 'my_double_var', 'user1')); - assert.isNull(optlyInstance.getFeatureVariableInteger('my_feature', 'my_int_var', 'user1')); - assert.isNull(optlyInstance.getFeatureVariableString('my_feature', 'my_str_var', 'user1')); + assert.isNull(optlyInstance.getFeatureVariable('my_feature', 'my_bool_var', 'user1')); + assert.isNull(optlyInstance.getFeatureVariable('my_feature', 'my_double_var', 'user1')); + assert.isNull(optlyInstance.getFeatureVariable('my_feature', 'my_int_var', 'user1')); + assert.isNull(optlyInstance.getFeatureVariable('my_feature', 'my_str_var', 'user1')); }); it('does not dispatch any events in API methods that dispatch events', function() { diff --git a/packages/optimizely-sdk/package-lock.json b/packages/optimizely-sdk/package-lock.json index 58efb968e..6a41548fb 100644 --- a/packages/optimizely-sdk/package-lock.json +++ b/packages/optimizely-sdk/package-lock.json @@ -299,6 +299,7 @@ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, + "optional": true, "requires": { "kind-of": "^3.0.2", "longest": "^1.0.1", @@ -2355,7 +2356,8 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -2379,13 +2381,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2402,19 +2406,22 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -2545,7 +2552,8 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -2559,6 +2567,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -2575,6 +2584,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2583,13 +2593,15 @@ "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz", "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==", "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -2610,6 +2622,7 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -2698,7 +2711,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -2712,6 +2726,7 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -2807,7 +2822,8 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -2849,6 +2865,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -2870,6 +2887,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -2918,13 +2936,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", - "dev": true + "dev": true, + "optional": true } } }, @@ -4571,7 +4591,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true + "dev": true, + "optional": true }, "loud-rejection": { "version": "1.6.0", From dbb1f22c006b3966cbb5de4952a35b123aa537f6 Mon Sep 17 00:00:00 2001 From: Brandon Date: Thu, 27 Jun 2019 14:09:57 -0700 Subject: [PATCH 04/10] remove unit tests involving wrong requested variable type --- .../lib/optimizely/index.tests.js | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/packages/optimizely-sdk/lib/optimizely/index.tests.js b/packages/optimizely-sdk/lib/optimizely/index.tests.js index e84e38f09..b9faee091 100644 --- a/packages/optimizely-sdk/lib/optimizely/index.tests.js +++ b/packages/optimizely-sdk/lib/optimizely/index.tests.js @@ -3993,29 +3993,29 @@ describe('lib/optimizely', function() { }); }); - it('returns null from getFeatureVariable when called with a non-boolean variable', function() { - var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', 'user1'); - assert.strictEqual(result, null); - sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "boolean", but variable is of type "double". Use correct API to retrieve value. Returning None.'); - }); - - it('returns null from getFeatureVariable when called with a non-double variable', function() { - var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated', 'user1'); - assert.strictEqual(result, null); - sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "double", but variable is of type "boolean". Use correct API to retrieve value. Returning None.'); - }); - - it('returns null from getFeatureVariable when called with a non-integer variable', function() { - var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', 'user1'); - assert.strictEqual(result, null); - sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "integer", but variable is of type "double". Use correct API to retrieve value. Returning None.'); - }); - - it('returns null from getFeatureVariable when called with a non-string variable', function() { - var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons', 'user1'); - assert.strictEqual(result, null); - sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "string", but variable is of type "integer". Use correct API to retrieve value. Returning None.'); - }); + // it('returns null from getFeatureVariable when called with a non-boolean variable', function() { + // var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', 'user1'); + // assert.strictEqual(result, null); + // sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "boolean", but variable is of type "double". Use correct API to retrieve value. Returning None.'); + // }); + + // it('returns null from getFeatureVariable when called with a non-double variable', function() { + // var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated', 'user1'); + // assert.strictEqual(result, null); + // sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "double", but variable is of type "boolean". Use correct API to retrieve value. Returning None.'); + // }); + + // it('returns null from getFeatureVariable when called with a non-integer variable', function() { + // var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', 'user1'); + // assert.strictEqual(result, null); + // sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "integer", but variable is of type "double". Use correct API to retrieve value. Returning None.'); + // }); + + // it('returns null from getFeatureVariable when called with a non-string variable', function() { + // var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons', 'user1'); + // assert.strictEqual(result, null); + // sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "string", but variable is of type "integer". Use correct API to retrieve value. Returning None.'); + // }); it('returns null from getFeatureVariable if user id is null', function() { var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated', null, { test_attribute: 'test_value' }); From 48c615d257abde76f068b9baf6cfe97541d0eda2 Mon Sep 17 00:00:00 2001 From: Brandon Date: Thu, 27 Jun 2019 17:04:32 -0700 Subject: [PATCH 05/10] add unit tests for getFeatureVariable --- .../optimizely-sdk/lib/optimizely/index.js | 204 ++--- .../lib/optimizely/index.tests.js | 803 +++++++++++++++++- 2 files changed, 867 insertions(+), 140 deletions(-) diff --git a/packages/optimizely-sdk/lib/optimizely/index.js b/packages/optimizely-sdk/lib/optimizely/index.js index 88f5be20f..db1540767 100644 --- a/packages/optimizely-sdk/lib/optimizely/index.js +++ b/packages/optimizely-sdk/lib/optimizely/index.js @@ -647,6 +647,99 @@ Optimizely.prototype.getEnabledFeatures = function(userId, attributes) { } }; +/** + * Returns value of the variable attached to the given feature flag. + * Returns null if the feature key or variable key is invalid. + * + * @param {string} featureKey Key of the feature whose variable's value is + * being accessed + * @param {string} variableKey Key of the variable whose value is being + * accessed + * @param {string} userId ID for the user + * @param {Object} attributes Optional user attributes + * @return {*} Value of the variable cast to the appropriate + * type, or null if the feature key is invalid or + * the variable key is invalid. + */ + +Optimizely.prototype.getFeatureVariable = function(featureKey, variableKey, userId, attributes) { + if (!this.__isValidInstance()) { + var apiName = 'getFeatureVariable'; + this.logger.log(LOG_LEVEL.ERROR, sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, apiName)); + return null; + } + + if (!this.__validateInputs({ feature_key: featureKey, variable_key: variableKey, user_id: userId }, attributes)) { + return null; + } + + var configObj = this.projectConfigManager.getConfig(); + if (!configObj) { + return null; + } + + var featureFlag = projectConfig.getFeatureFromKey(configObj, featureKey, this.logger); + if (!featureFlag) { + return null; + } + + var variable = projectConfig.getVariableForFeature(configObj, featureKey, variableKey, this.logger); + if (!variable) { + return null; + } + + var featureEnabled = false; + var variableValue = variable.defaultValue; + var decision = this.decisionService.getVariationForFeature(configObj, featureFlag, userId, attributes); + + if (decision.variation !== null) { + featureEnabled = decision.variation.featureEnabled; + var value = projectConfig.getVariableValueForVariation(configObj, variable, decision.variation, this.logger); + if (value !== null) { + if (featureEnabled === true) { + variableValue = value; + this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.USER_RECEIVED_VARIABLE_VALUE, MODULE_NAME, variableKey, featureFlag.key, variableValue, userId)); + } else { + this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.FEATURE_NOT_ENABLED_RETURN_DEFAULT_VARIABLE_VALUE, MODULE_NAME, + featureFlag.key, userId, variableKey)); + } + } else { + this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.VARIABLE_NOT_USED_RETURN_DEFAULT_VARIABLE_VALUE, MODULE_NAME, variableKey, decision.variation.key)); + } + } else { + this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.USER_RECEIVED_DEFAULT_VARIABLE_VALUE, MODULE_NAME, userId, + variableKey, featureFlag.key)); + } + + var sourceInfo = {}; + if (decision.decisionSource === DECISION_SOURCES.FEATURE_TEST) { + sourceInfo = { + experimentKey: decision.experiment.key, + variationKey: decision.variation.key, + } + } + + var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variable.type, this.logger); + this.notificationCenter.sendNotifications( + NOTIFICATION_TYPES.DECISION, + { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: userId, + attributes: attributes || {}, + decisionInfo: { + featureKey: featureKey, + featureEnabled: featureEnabled, + source: decision.decisionSource, + variableKey: variableKey, + variableValue: typeCastedValue, + variableType: variable.type, + sourceInfo: sourceInfo, + } + } + ); + return typeCastedValue; +}; + /** * Helper method to get the value for a variable of a certain type attached to a * feature flag. Returns null if the feature key is invalid, the variable key is @@ -667,11 +760,9 @@ Optimizely.prototype.getEnabledFeatures = function(userId, attributes) { * variable key is invalid, or there is a mismatch * with the type of the variable */ - -Optimizely.prototype.getFeatureVariable = function(featureKey, variableKey, userId, attributes) { +Optimizely.prototype._getFeatureVariableForType = function(featureKey, variableKey, variableType, userId, attributes) { if (!this.__isValidInstance()) { - // var apiName = 'getFeatureVariable' + variableType.charAt(0).toUpperCase() + variableType.slice(1); - var apiName = 'getFeatureVariable'; + var apiName = 'getFeatureVariable' + variableType.charAt(0).toUpperCase() + variableType.slice(1); this.logger.log(LOG_LEVEL.ERROR, sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, apiName)); return null; } @@ -695,13 +786,13 @@ Optimizely.prototype.getFeatureVariable = function(featureKey, variableKey, user return null; } - // if (variable.type !== variableType) { - // this.logger.log( - // LOG_LEVEL.WARNING, - // sprintf(LOG_MESSAGES.VARIABLE_REQUESTED_WITH_WRONG_TYPE, MODULE_NAME, variableType, variable.type) - // ); - // return null; - // } + if (variable.type !== variableType) { + this.logger.log( + LOG_LEVEL.WARNING, + sprintf(LOG_MESSAGES.VARIABLE_REQUESTED_WITH_WRONG_TYPE, MODULE_NAME, variableType, variable.type) + ); + return null; + } var featureEnabled = false; var variableValue = variable.defaultValue; @@ -734,7 +825,7 @@ Optimizely.prototype.getFeatureVariable = function(featureKey, variableKey, user } } - var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variable.type, this.logger); + var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variableType, this.logger); this.notificationCenter.sendNotifications( NOTIFICATION_TYPES.DECISION, { @@ -747,101 +838,14 @@ Optimizely.prototype.getFeatureVariable = function(featureKey, variableKey, user source: decision.decisionSource, variableKey: variableKey, variableValue: typeCastedValue, - variableType: variable.type, + variableType: variableType, sourceInfo: sourceInfo, } } ); - // return variableValue; return typeCastedValue; }; -// Optimizely.prototype._getFeatureVariableForType = function(featureKey, variableKey, variableType, userId, attributes) { -// if (!this.__isValidInstance()) { -// var apiName = 'getFeatureVariable' + variableType.charAt(0).toUpperCase() + variableType.slice(1); -// this.logger.log(LOG_LEVEL.ERROR, sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, apiName)); -// return null; -// } - -// if (!this.__validateInputs({ feature_key: featureKey, variable_key: variableKey, user_id: userId }, attributes)) { -// return null; -// } - -// var configObj = this.projectConfigManager.getConfig(); -// if (!configObj) { -// return null; -// } - -// var featureFlag = projectConfig.getFeatureFromKey(configObj, featureKey, this.logger); -// if (!featureFlag) { -// return null; -// } - -// var variable = projectConfig.getVariableForFeature(configObj, featureKey, variableKey, this.logger); -// if (!variable) { -// return null; -// } - -// if (variable.type !== variableType) { -// this.logger.log( -// LOG_LEVEL.WARNING, -// sprintf(LOG_MESSAGES.VARIABLE_REQUESTED_WITH_WRONG_TYPE, MODULE_NAME, variableType, variable.type) -// ); -// return null; -// } - -// var featureEnabled = false; -// var variableValue = variable.defaultValue; -// var decision = this.decisionService.getVariationForFeature(configObj, featureFlag, userId, attributes); - -// if (decision.variation !== null) { -// featureEnabled = decision.variation.featureEnabled; -// var value = projectConfig.getVariableValueForVariation(configObj, variable, decision.variation, this.logger); -// if (value !== null) { -// if (featureEnabled === true) { -// variableValue = value; -// this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.USER_RECEIVED_VARIABLE_VALUE, MODULE_NAME, variableKey, featureFlag.key, variableValue, userId)); -// } else { -// this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.FEATURE_NOT_ENABLED_RETURN_DEFAULT_VARIABLE_VALUE, MODULE_NAME, -// featureFlag.key, userId, variableKey)); -// } -// } else { -// this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.VARIABLE_NOT_USED_RETURN_DEFAULT_VARIABLE_VALUE, MODULE_NAME, variableKey, decision.variation.key)); -// } -// } else { -// this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.USER_RECEIVED_DEFAULT_VARIABLE_VALUE, MODULE_NAME, userId, -// variableKey, featureFlag.key)); -// } - -// var sourceInfo = {}; -// if (decision.decisionSource === DECISION_SOURCES.FEATURE_TEST) { -// sourceInfo = { -// experimentKey: decision.experiment.key, -// variationKey: decision.variation.key, -// } -// } - -// var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variableType, this.logger); -// this.notificationCenter.sendNotifications( -// NOTIFICATION_TYPES.DECISION, -// { -// type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, -// userId: userId, -// attributes: attributes || {}, -// decisionInfo: { -// featureKey: featureKey, -// featureEnabled: featureEnabled, -// source: decision.decisionSource, -// variableKey: variableKey, -// variableValue: typeCastedValue, -// variableType: variableType, -// sourceInfo: sourceInfo, -// } -// } -// ); -// return typeCastedValue; -// }; - /** * Returns value for the given boolean variable attached to the given feature * flag. diff --git a/packages/optimizely-sdk/lib/optimizely/index.tests.js b/packages/optimizely-sdk/lib/optimizely/index.tests.js index b9faee091..86b3872f3 100644 --- a/packages/optimizely-sdk/lib/optimizely/index.tests.js +++ b/packages/optimizely-sdk/lib/optimizely/index.tests.js @@ -2731,6 +2731,94 @@ describe('lib/optimizely', function() { } }); }); + + it('returns the right value from getFeatureVariableBoolean and send notification with featureEnabled true', function() { + var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, true); + sinon.assert.calledWith(decisionListener, { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: 'user1', + attributes: { test_attribute: 'test_value' }, + decisionInfo: { + featureKey: 'test_feature_for_experiment', + featureEnabled: true, + variableKey: 'is_button_animated', + variableValue: true, + variableType: FEATURE_VARIABLE_TYPES.BOOLEAN, + source: DECISION_SOURCES.FEATURE_TEST, + sourceInfo: { + experimentKey: 'testing_my_feature', + variationKey: 'variation' + } + } + }); + }); + + it('returns the right value from getFeatureVariableDouble and send notification with featureEnabled true', function() { + var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 20.25); + sinon.assert.calledWith(decisionListener, { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: 'user1', + attributes: { test_attribute: 'test_value' }, + decisionInfo: { + featureKey: 'test_feature_for_experiment', + featureEnabled: true, + variableKey: 'button_width', + variableValue: 20.25, + variableType: FEATURE_VARIABLE_TYPES.DOUBLE, + source: DECISION_SOURCES.FEATURE_TEST, + sourceInfo: { + experimentKey: 'testing_my_feature', + variationKey: 'variation' + } + } + }); + }); + + it('returns the right value from getFeatureVariableInteger and send notification with featureEnabled true', function() { + var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 2); + sinon.assert.calledWith(decisionListener, { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: 'user1', + attributes: { test_attribute: 'test_value' }, + decisionInfo: { + featureKey: 'test_feature_for_experiment', + featureEnabled: true, + variableKey: 'num_buttons', + variableValue: 2, + variableType: FEATURE_VARIABLE_TYPES.INTEGER, + source: DECISION_SOURCES.FEATURE_TEST, + sourceInfo: { + experimentKey: 'testing_my_feature', + variationKey: 'variation' + } + } + }); + }); + + it('returns the right value from getFeatureVariableString and send notification with featureEnabled true', function() { + var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 'Buy me NOW'); + sinon.assert.calledWith(decisionListener, { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: 'user1', + attributes: { test_attribute: 'test_value' }, + decisionInfo: { + featureKey: 'test_feature_for_experiment', + featureEnabled: true, + variableKey: 'button_txt', + variableValue: 'Buy me NOW', + variableType: FEATURE_VARIABLE_TYPES.STRING, + source: DECISION_SOURCES.FEATURE_TEST, + sourceInfo: { + experimentKey: 'testing_my_feature', + variationKey: 'variation' + } + } + }); + }); }); describe('when the variation is toggled OFF', function() { @@ -2744,8 +2832,8 @@ describe('lib/optimizely', function() { }); }); - it('returns the default value from getFeatureVariable and send notification with featureEnabled false', function() { - var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); + it('returns the default value from getFeatureVariableBoolean and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, false); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2766,8 +2854,8 @@ describe('lib/optimizely', function() { }); }); - it('returns the default value from getFeatureVariable and send notification with featureEnabled false', function() { - var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); + it('returns the default value from getFeatureVariableDouble and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 50.55); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2788,8 +2876,8 @@ describe('lib/optimizely', function() { }); }); - it('returns the default value from getFeatureVariable and send notification with featureEnabled false', function() { - var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); + it('returns the default value from getFeatureVariableInteger and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 10); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2810,8 +2898,8 @@ describe('lib/optimizely', function() { }); }); - it('returns the default value from getFeatureVariable and send notification with featureEnabled false', function() { - var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); + it('returns the default value from getFeatureVariableString and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 'Buy me'); sinon.assert.calledWith(decisionListener, { type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, @@ -2921,6 +3009,82 @@ describe('lib/optimizely', function() { } }); }); + + it('should return the right value from getFeatureVariableBoolean and send notification with featureEnabled true', function() { + var result = optlyInstance.getFeatureVariableBoolean('test_feature', 'new_content', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, true); + sinon.assert.calledWith(decisionListener, { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: 'user1', + attributes: { test_attribute: 'test_value' }, + decisionInfo: { + featureKey: 'test_feature', + featureEnabled: true, + variableKey: 'new_content', + variableValue: true, + variableType: FEATURE_VARIABLE_TYPES.BOOLEAN, + source: DECISION_SOURCES.ROLLOUT, + sourceInfo: {} + } + }); + }); + + it('should return the right value from getFeatureVariableDouble and send notification with featureEnabled true', function() { + var result = optlyInstance.getFeatureVariableDouble('test_feature', 'price', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 4.99); + sinon.assert.calledWith(decisionListener, { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: 'user1', + attributes: { test_attribute: 'test_value' }, + decisionInfo: { + featureKey: 'test_feature', + featureEnabled: true, + variableKey: 'price', + variableValue: 4.99, + variableType: FEATURE_VARIABLE_TYPES.DOUBLE, + source: DECISION_SOURCES.ROLLOUT, + sourceInfo: {} + } + }); + }); + + it('should return the right value from getFeatureVariableInteger and send notification with featureEnabled true', function() { + var result = optlyInstance.getFeatureVariableInteger('test_feature', 'lasers', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 395); + sinon.assert.calledWith(decisionListener, { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: 'user1', + attributes: { test_attribute: 'test_value' }, + decisionInfo: { + featureKey: 'test_feature', + featureEnabled: true, + variableKey: 'lasers', + variableValue: 395, + variableType: FEATURE_VARIABLE_TYPES.INTEGER, + source: DECISION_SOURCES.ROLLOUT, + sourceInfo: {} + } + }); + }); + + it('should return the right value from getFeatureVariableString and send notification with featureEnabled true', function() { + var result = optlyInstance.getFeatureVariableString('test_feature', 'message', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 'Hello audience'); + sinon.assert.calledWith(decisionListener, { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: 'user1', + attributes: { test_attribute: 'test_value' }, + decisionInfo: { + featureKey: 'test_feature', + featureEnabled: true, + variableKey: 'message', + variableValue: 'Hello audience', + variableType: FEATURE_VARIABLE_TYPES.STRING, + source: DECISION_SOURCES.ROLLOUT, + sourceInfo: {} + } + }); + }); }); describe('when the variation is toggled OFF', function() { @@ -3009,6 +3173,82 @@ describe('lib/optimizely', function() { } }); }); + + it('should return the default value from getFeatureVariableBoolean and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariableBoolean('test_feature', 'new_content', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, false); + sinon.assert.calledWith(decisionListener, { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: 'user1', + attributes: { test_attribute: 'test_value' }, + decisionInfo: { + featureKey: 'test_feature', + featureEnabled: false, + variableKey: 'new_content', + variableValue: false, + variableType: FEATURE_VARIABLE_TYPES.BOOLEAN, + source: DECISION_SOURCES.ROLLOUT, + sourceInfo: {} + } + }); + }); + + it('should return the default value from getFeatureVariableDouble and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariableDouble('test_feature', 'price', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 14.99); + sinon.assert.calledWith(decisionListener, { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: 'user1', + attributes: { test_attribute: 'test_value' }, + decisionInfo: { + featureKey: 'test_feature', + featureEnabled: false, + variableKey: 'price', + variableValue: 14.99, + variableType: FEATURE_VARIABLE_TYPES.DOUBLE, + source: DECISION_SOURCES.ROLLOUT, + sourceInfo: {} + } + }); + }); + + it('should return the default value from getFeatureVariableInteger and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariableInteger('test_feature', 'lasers', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 400); + sinon.assert.calledWith(decisionListener, { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: 'user1', + attributes: { test_attribute: 'test_value' }, + decisionInfo: { + featureKey: 'test_feature', + featureEnabled: false, + variableKey: 'lasers', + variableValue: 400, + variableType: FEATURE_VARIABLE_TYPES.INTEGER, + source: DECISION_SOURCES.ROLLOUT, + sourceInfo: {} + } + }); + }); + + it('should return the default value from getFeatureVariableString and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariableString('test_feature', 'message', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 'Hello'); + sinon.assert.calledWith(decisionListener, { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: 'user1', + attributes: { test_attribute: 'test_value' }, + decisionInfo: { + featureKey: 'test_feature', + featureEnabled: false, + variableKey: 'message', + variableValue: 'Hello', + variableType: FEATURE_VARIABLE_TYPES.STRING, + source: DECISION_SOURCES.ROLLOUT, + sourceInfo: {} + } + }); + }); }); }); @@ -3096,6 +3336,82 @@ describe('lib/optimizely', function() { } }); }); + + it('returns the variable default value from getFeatureVariableBoolean and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, false); + sinon.assert.calledWith(decisionListener, { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: 'user1', + attributes: { test_attribute: 'test_value' }, + decisionInfo: { + featureKey: 'test_feature_for_experiment', + featureEnabled: false, + variableKey: 'is_button_animated', + variableValue: false, + variableType: FEATURE_VARIABLE_TYPES.BOOLEAN, + source: DECISION_SOURCES.ROLLOUT, + sourceInfo: {} + } + }); + }); + + it('returns the variable default value from getFeatureVariableDouble and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 50.55); + sinon.assert.calledWith(decisionListener, { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: 'user1', + attributes: { test_attribute: 'test_value' }, + decisionInfo: { + featureKey: 'test_feature_for_experiment', + featureEnabled: false, + variableKey: 'button_width', + variableValue: 50.55, + variableType: FEATURE_VARIABLE_TYPES.DOUBLE, + source: DECISION_SOURCES.ROLLOUT, + sourceInfo: {} + } + }); + }); + + it('returns the variable default value from getFeatureVariableInteger and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 10); + sinon.assert.calledWith(decisionListener, { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: 'user1', + attributes: { test_attribute: 'test_value' }, + decisionInfo: { + featureKey: 'test_feature_for_experiment', + featureEnabled: false, + variableKey: 'num_buttons', + variableValue: 10, + variableType: FEATURE_VARIABLE_TYPES.INTEGER, + source: DECISION_SOURCES.ROLLOUT, + sourceInfo: {} + } + }); + }); + + it('returns the variable default value from getFeatureVariableString and send notification with featureEnabled false', function() { + var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 'Buy me'); + sinon.assert.calledWith(decisionListener, { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: 'user1', + attributes: { test_attribute: 'test_value' }, + decisionInfo: { + featureKey: 'test_feature_for_experiment', + featureEnabled: false, + variableKey: 'button_txt', + variableValue: 'Buy me', + variableType: FEATURE_VARIABLE_TYPES.STRING, + source: DECISION_SOURCES.ROLLOUT, + sourceInfo: {} + } + }); + }); }); }); }); @@ -3787,6 +4103,30 @@ describe('lib/optimizely', function() { sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Value for variable "button_txt" of feature flag "test_feature_for_experiment" is Buy me NOW for user "user1"'); }); + it('returns the right value from getFeatureVariableBoolean', function() { + var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, true); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Value for variable "is_button_animated" of feature flag "test_feature_for_experiment" is true for user "user1"'); + }); + + it('returns the right value from getFeatureVariableDouble', function() { + var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 20.25); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Value for variable "button_width" of feature flag "test_feature_for_experiment" is 20.25 for user "user1"'); + }); + + it('returns the right value from getFeatureVariableInteger', function() { + var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 2); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Value for variable "num_buttons" of feature flag "test_feature_for_experiment" is 2 for user "user1"'); + }); + + it('returns the right value from getFeatureVariableString', function() { + var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 'Buy me NOW'); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Value for variable "button_txt" of feature flag "test_feature_for_experiment" is Buy me NOW for user "user1"'); + }); + describe('when the variable is not used in the variation', function() { beforeEach(function() { sandbox.stub(projectConfig, 'getVariableValueForVariation').returns(null); @@ -3815,6 +4155,30 @@ describe('lib/optimizely', function() { assert.strictEqual(result, 'Buy me'); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Variable "button_txt" is not used in variation "variation". Returning default value.'); }); + + it('returns the variable default value from getFeatureVariableBoolean', function() { + var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, false); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Variable "is_button_animated" is not used in variation "variation". Returning default value.'); + }); + + it('returns the variable default value from getFeatureVariableDouble', function() { + var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 50.55); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Variable "button_width" is not used in variation "variation". Returning default value.'); + }); + + it('returns the variable default value from getFeatureVariableInteger', function() { + var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 10); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Variable "num_buttons" is not used in variation "variation". Returning default value.'); + }); + + it('returns the variable default value from getFeatureVariableString', function() { + var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 'Buy me'); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Variable "button_txt" is not used in variation "variation". Returning default value.'); + }); }); }); @@ -3841,14 +4205,38 @@ describe('lib/optimizely', function() { sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature_for_experiment" is not enabled for user user1. Returning default value for variable "button_width".'); }); - it('returns the variable default value from getFeatureVariable', function() { - var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 10); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature_for_experiment" is not enabled for user user1. Returning default value for variable "num_buttons".'); + }); + + it('returns the variable default value from getFeatureVariable', function() { + var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 'Buy me'); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature_for_experiment" is not enabled for user user1. Returning default value for variable "button_txt".'); + }); + + it('returns the variable default value from getFeatureVariableBoolean', function() { + var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, false); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature_for_experiment" is not enabled for user user1. Returning default value for variable "is_button_animated".'); + }); + + it('returns the variable default value from getFeatureVariableDouble', function() { + var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 50.55); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature_for_experiment" is not enabled for user user1. Returning default value for variable "button_width".'); + }); + + it('returns the variable default value from getFeatureVariableInteger', function() { + var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 10); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature_for_experiment" is not enabled for user user1. Returning default value for variable "num_buttons".'); }); - it('returns the variable default value from getFeatureVariable', function() { - var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); + it('returns the variable default value from getFeatureVariableString', function() { + var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); assert.strictEqual(result, 'Buy me'); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature_for_experiment" is not enabled for user user1. Returning default value for variable "button_txt".'); }); @@ -3891,6 +4279,30 @@ describe('lib/optimizely', function() { sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Value for variable "message" of feature flag "test_feature" is Hello audience for user "user1"'); }); + it('returns the right value from getFeatureVariableBoolean', function() { + var result = optlyInstance.getFeatureVariableBoolean('test_feature', 'new_content', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, true); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Value for variable "new_content" of feature flag "test_feature" is true for user "user1"'); + }); + + it('returns the right value from getFeatureVariableDouble', function() { + var result = optlyInstance.getFeatureVariableDouble('test_feature', 'price', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 4.99); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Value for variable "price" of feature flag "test_feature" is 4.99 for user "user1"'); + }); + + it('returns the right value from getFeatureVariableInteger', function() { + var result = optlyInstance.getFeatureVariableInteger('test_feature', 'lasers', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 395); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Value for variable "lasers" of feature flag "test_feature" is 395 for user "user1"'); + }); + + it('returns the right value from getFeatureVariableString', function() { + var result = optlyInstance.getFeatureVariableString('test_feature', 'message', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 'Hello audience'); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Value for variable "message" of feature flag "test_feature" is Hello audience for user "user1"'); + }); + describe('when the variable is not used in the variation', function() { beforeEach(function() { sandbox.stub(projectConfig, 'getVariableValueForVariation').returns(null); @@ -3919,6 +4331,30 @@ describe('lib/optimizely', function() { assert.strictEqual(result, 'Hello'); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Variable "message" is not used in variation "594032". Returning default value.'); }); + + it('returns the variable default value from getFeatureVariableBoolean', function() { + var result = optlyInstance.getFeatureVariableBoolean('test_feature', 'new_content', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, false); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Variable "new_content" is not used in variation "594032". Returning default value.'); + }); + + it('returns the variable default value from getFeatureVariableDouble', function() { + var result = optlyInstance.getFeatureVariableDouble('test_feature', 'price', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 14.99); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Variable "price" is not used in variation "594032". Returning default value.'); + }); + + it('returns the variable default value from getFeatureVariableInteger', function() { + var result = optlyInstance.getFeatureVariableInteger('test_feature', 'lasers', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 400); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Variable "lasers" is not used in variation "594032". Returning default value.'); + }); + + it('returns the variable default value from getFeatureVariableString', function() { + var result = optlyInstance.getFeatureVariableString('test_feature', 'message', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 'Hello'); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Variable "message" is not used in variation "594032". Returning default value.'); + }); }); }); @@ -3956,6 +4392,30 @@ describe('lib/optimizely', function() { assert.strictEqual(result, 'Hello'); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature" is not enabled for user user1. Returning default value for variable "message".'); }); + + it('returns the variable default value from getFeatureVariableBoolean', function() { + var result = optlyInstance.getFeatureVariableBoolean('test_feature', 'new_content', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, false); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature" is not enabled for user user1. Returning default value for variable "new_content".'); + }); + + it('returns the variable default value from getFeatureVariableDouble', function() { + var result = optlyInstance.getFeatureVariableDouble('test_feature', 'price', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 14.99); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature" is not enabled for user user1. Returning default value for variable "price".'); + }); + + it('returns the variable default value from getFeatureVariableInteger', function() { + var result = optlyInstance.getFeatureVariableInteger('test_feature', 'lasers', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 400); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature" is not enabled for user user1. Returning default value for variable "lasers".'); + }); + + it('returns the variable default value from getFeatureVariableString', function() { + var result = optlyInstance.getFeatureVariableString('test_feature', 'message', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 'Hello'); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: Feature "test_feature" is not enabled for user user1. Returning default value for variable "message".'); + }); }); }); @@ -3991,31 +4451,31 @@ describe('lib/optimizely', function() { assert.strictEqual(result, 'Buy me'); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: User "user1" is not in any variation or rollout rule. Returning default value for variable "button_txt" of feature flag "test_feature_for_experiment".'); }); - }); - // it('returns null from getFeatureVariable when called with a non-boolean variable', function() { - // var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', 'user1'); - // assert.strictEqual(result, null); - // sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "boolean", but variable is of type "double". Use correct API to retrieve value. Returning None.'); - // }); + it('returns the variable default value from getFeatureVariableBoolean', function() { + var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, false); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: User "user1" is not in any variation or rollout rule. Returning default value for variable "is_button_animated" of feature flag "test_feature_for_experiment".'); + }); - // it('returns null from getFeatureVariable when called with a non-double variable', function() { - // var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated', 'user1'); - // assert.strictEqual(result, null); - // sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "double", but variable is of type "boolean". Use correct API to retrieve value. Returning None.'); - // }); + it('returns the variable default value from getFeatureVariableDouble', function() { + var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 50.55); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: User "user1" is not in any variation or rollout rule. Returning default value for variable "button_width" of feature flag "test_feature_for_experiment".'); + }); - // it('returns null from getFeatureVariable when called with a non-integer variable', function() { - // var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', 'user1'); - // assert.strictEqual(result, null); - // sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "integer", but variable is of type "double". Use correct API to retrieve value. Returning None.'); - // }); + it('returns the variable default value from getFeatureVariableInteger', function() { + var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 10); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: User "user1" is not in any variation or rollout rule. Returning default value for variable "num_buttons" of feature flag "test_feature_for_experiment".'); + }); - // it('returns null from getFeatureVariable when called with a non-string variable', function() { - // var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons', 'user1'); - // assert.strictEqual(result, null); - // sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "string", but variable is of type "integer". Use correct API to retrieve value. Returning None.'); - // }); + it('returns the variable default value from getFeatureVariableString', function() { + var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt', 'user1', { test_attribute: 'test_value' }); + assert.strictEqual(result, 'Buy me'); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.INFO, 'OPTIMIZELY: User "user1" is not in any variation or rollout rule. Returning default value for variable "button_txt" of feature flag "test_feature_for_experiment".'); + }); + }); it('returns null from getFeatureVariable if user id is null', function() { var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated', null, { test_attribute: 'test_value' }); @@ -4089,6 +4549,102 @@ describe('lib/optimizely', function() { sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); }); + it('returns null from getFeatureVariableBoolean when called with a non-boolean variable', function() { + var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'button_width', 'user1'); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "boolean", but variable is of type "double". Use correct API to retrieve value. Returning None.'); + }); + + it('returns null from getFeatureVariableDouble when called with a non-double variable', function() { + var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'is_button_animated', 'user1'); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "double", but variable is of type "boolean". Use correct API to retrieve value. Returning None.'); + }); + + it('returns null from getFeatureVariableInteger when called with a non-integer variable', function() { + var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'button_width', 'user1'); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "integer", but variable is of type "double". Use correct API to retrieve value. Returning None.'); + }); + + it('returns null from getFeatureVariableString when called with a non-string variable', function() { + var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'num_buttons', 'user1'); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.WARNING, 'OPTIMIZELY: Requested variable type "string", but variable is of type "integer". Use correct API to retrieve value. Returning None.'); + }); + + it('returns null from getFeatureVariableBoolean if user id is null', function() { + var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', null, { test_attribute: 'test_value' }); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); + }); + + it('returns null from getFeatureVariableBoolean if user id is undefined', function() { + var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', undefined, { test_attribute: 'test_value' }); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); + }); + + it('returns null from getFeatureVariableBoolean if user id is not provided', function() { + var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated'); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); + }); + + it('returns null from getFeatureVariableDouble if user id is null', function() { + var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', null, { test_attribute: 'test_value' }); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); + }); + + it('returns null from getFeatureVariableDouble if user id is undefined', function() { + var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', undefined, { test_attribute: 'test_value' }); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); + }); + + it('returns null from getFeatureVariableDouble if user id is not provided', function() { + var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width'); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); + }); + + it('returns null from getFeatureVariableInteger if user id is null', function() { + var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', null, { test_attribute: 'test_value' }); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); + }); + + it('returns null from getFeatureVariableInteger if user id is undefined', function() { + var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', undefined, { test_attribute: 'test_value' }); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); + }); + + it('returns null from getFeatureVariableInteger if user id is not provided', function() { + var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons'); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); + }); + + it('returns null from getFeatureVariableString if user id is null', function() { + var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt', null, { test_attribute: 'test_value' }); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); + }); + + it('returns null from getFeatureVariableString if user id is undefined', function() { + var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt', undefined, { test_attribute: 'test_value' }); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); + }); + + it('returns null from getFeatureVariableString if user id is not provided', function() { + var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'button_txt'); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'OPTIMIZELY: Provided user_id is in an invalid format.'); + }); + describe('type casting failures', function() { describe('invalid boolean', function() { beforeEach(function() { @@ -4096,7 +4652,7 @@ describe('lib/optimizely', function() { }); it('should return null and log an error', function() { - var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'is_button_animated', 'user1'); + var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'is_button_animated', 'user1'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Unable to cast value falsezzz to type boolean, returning null.'); }); @@ -4108,7 +4664,7 @@ describe('lib/optimizely', function() { }); it('should return null and log an error', function() { - var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'num_buttons', 'user1'); + var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'num_buttons', 'user1'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Unable to cast value zzz123 to type integer, returning null.'); }); @@ -4120,7 +4676,7 @@ describe('lib/optimizely', function() { }); it('should return null and log an error', function() { - var result = optlyInstance.getFeatureVariable('test_feature_for_experiment', 'button_width', 'user1'); + var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'button_width', 'user1'); assert.strictEqual(result, null); sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Unable to cast value zzz44.55 to type double, returning null.'); }); @@ -4175,6 +4731,54 @@ describe('lib/optimizely', function() { sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Variable with key "thisIsNotAVariableKey****" associated with feature with key "test_feature_for_experiment" is not in datafile.'); }); + it('returns null from getFeatureVariableBoolean if the argument feature key is invalid', function() { + var result = optlyInstance.getFeatureVariableBoolean('thisIsNotAValidKey<><><>', 'is_button_animated', 'user1'); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Feature key thisIsNotAValidKey<><><> is not in datafile.'); + }); + + it('returns null from getFeatureVariableDouble if the argument feature key is invalid', function() { + var result = optlyInstance.getFeatureVariableDouble('thisIsNotAValidKey<><><>', 'button_width', 'user1'); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Feature key thisIsNotAValidKey<><><> is not in datafile.'); + }); + + it('returns null from getFeatureVariableInteger if the argument feature key is invalid', function() { + var result = optlyInstance.getFeatureVariableInteger('thisIsNotAValidKey<><><>', 'num_buttons', 'user1'); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Feature key thisIsNotAValidKey<><><> is not in datafile.'); + }); + + it('returns null from getFeatureVariableString if the argument feature key is invalid', function() { + var result = optlyInstance.getFeatureVariableString('thisIsNotAValidKey<><><>', 'button_txt', 'user1'); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Feature key thisIsNotAValidKey<><><> is not in datafile.'); + }); + + it('returns null from getFeatureVariableBoolean if the argument variable key is invalid', function() { + var result = optlyInstance.getFeatureVariableBoolean('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Variable with key "thisIsNotAVariableKey****" associated with feature with key "test_feature_for_experiment" is not in datafile.'); + }); + + it('returns null from getFeatureVariableDouble if the argument variable key is invalid', function() { + var result = optlyInstance.getFeatureVariableDouble('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Variable with key "thisIsNotAVariableKey****" associated with feature with key "test_feature_for_experiment" is not in datafile.'); + }); + + it('returns null from getFeatureVariableInteger if the argument variable key is invalid', function() { + var result = optlyInstance.getFeatureVariableInteger('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Variable with key "thisIsNotAVariableKey****" associated with feature with key "test_feature_for_experiment" is not in datafile.'); + }); + + it('returns null from getFeatureVariableString if the argument variable key is invalid', function() { + var result = optlyInstance.getFeatureVariableString('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); + assert.strictEqual(result, null); + sinon.assert.calledWith(createdLogger.log, LOG_LEVEL.ERROR, 'PROJECT_CONFIG: Variable with key "thisIsNotAVariableKey****" associated with feature with key "test_feature_for_experiment" is not in datafile.'); + }); + it('returns null from getFeatureVariable when optimizely object is not a valid instance', function() { var instance = new Optimizely({ datafile: {}, @@ -4192,6 +4796,23 @@ describe('lib/optimizely', function() { assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariable')); }); + it('returns null from getFeatureVariableBoolean when optimizely object is not a valid instance', function() { + var instance = new Optimizely({ + datafile: {}, + errorHandler: errorHandler, + eventDispatcher: eventDispatcher, + logger: createdLogger, + }); + + createdLogger.log.reset(); + + instance.getFeatureVariableBoolean('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); + + sinon.assert.calledOnce(createdLogger.log); + var logMessage = createdLogger.log.args[0][1]; + assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariableBoolean')); + }); + it('returns null from getFeatureVariable when optimizely object is not a valid instance', function() { var instance = new Optimizely({ datafile: {}, @@ -4209,6 +4830,23 @@ describe('lib/optimizely', function() { assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariable')); }); + it('returns null from getFeatureVariableDouble when optimizely object is not a valid instance', function() { + var instance = new Optimizely({ + datafile: {}, + errorHandler: errorHandler, + eventDispatcher: eventDispatcher, + logger: createdLogger, + }); + + createdLogger.log.reset(); + + instance.getFeatureVariableDouble('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); + + sinon.assert.calledOnce(createdLogger.log); + var logMessage = createdLogger.log.args[0][1]; + assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariableDouble')); + }); + it('returns null from getFeatureVariable when optimizely object is not a valid instance', function() { var instance = new Optimizely({ datafile: {}, @@ -4226,6 +4864,23 @@ describe('lib/optimizely', function() { assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariable')); }); + it('returns null from getFeatureVariableInteger when optimizely object is not a valid instance', function() { + var instance = new Optimizely({ + datafile: {}, + errorHandler: errorHandler, + eventDispatcher: eventDispatcher, + logger: createdLogger, + }); + + createdLogger.log.reset(); + + instance.getFeatureVariableInteger('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); + + sinon.assert.calledOnce(createdLogger.log); + var logMessage = createdLogger.log.args[0][1]; + assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariableInteger')); + }); + it('returns null from getFeatureVariable when optimizely object is not a valid instance', function() { var instance = new Optimizely({ datafile: {}, @@ -4242,6 +4897,23 @@ describe('lib/optimizely', function() { var logMessage = createdLogger.log.args[0][1]; assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariable')); }); + + it('returns null from getFeatureVariableString when optimizely object is not a valid instance', function() { + var instance = new Optimizely({ + datafile: {}, + errorHandler: errorHandler, + eventDispatcher: eventDispatcher, + logger: createdLogger, + }); + + createdLogger.log.reset(); + + instance.getFeatureVariableString('test_feature_for_experiment', 'thisIsNotAVariableKey****', 'user1'); + + sinon.assert.calledOnce(createdLogger.log); + var logMessage = createdLogger.log.args[0][1]; + assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariableString')); + }); }); }); @@ -4350,12 +5022,33 @@ describe('lib/optimizely', function() { assert.strictEqual(variableValue, 'xyz'); }); + it('can return a variable value from a feature test with a typed audience via getFeatureVariableString', function() { + var variableValue = optlyInstance.getFeatureVariableString('feat_with_var', 'x', 'user1', { + // Should be included in the feature test via greater-than match audience with id '3468206647' + lasers: 71, + }); + assert.strictEqual(variableValue, 'xyz'); + + variableValue = optlyInstance.getFeatureVariableString('feat_with_var', 'x', 'user1', { + // Should be included in the feature test via exact match boolean audience with id '3468206643' + should_do_it: true, + }); + assert.strictEqual(variableValue, 'xyz'); + }); + it('can return the default value from a feature variable from getFeatureVariable, via excluding a user from a feature test with a typed audience', function() { var variableValue = optlyInstance.getFeatureVariable('feat_with_var', 'x', 'user1', { lasers: 50, }); assert.strictEqual(variableValue, 'x'); }); + + it('can return the default value from a feature variable from getFeatureVariableString, via excluding a user from a feature test with a typed audience', function() { + var variableValue = optlyInstance.getFeatureVariableString('feat_with_var', 'x', 'user1', { + lasers: 50, + }); + assert.strictEqual(variableValue, 'x'); + }); }); describe('audience combinations', function() { @@ -4478,6 +5171,22 @@ describe('lib/optimizely', function() { ); }); + it('can return a variable value from a feature test with complex audience conditions via getFeatureVariableString', function() { + var variableValue = optlyInstance.getFeatureVariableInteger('feat2_with_var', 'z', 'user1', { + // Should be included via exact match string audience with id '3468206642', and + // greater than audience with id '3468206647' + house: 'Gryffindor', + lasers: 700, + }); + assert.strictEqual(variableValue, 150); + sinon.assert.calledWithExactly( + audienceEvaluator.evaluate, + optlyInstance.projectConfigManager.getConfig().experiments[3].audienceConditions, + optlyInstance.projectConfigManager.getConfig().audiencesById, + { house: 'Gryffindor', lasers: 700 } + ); + }); + it('can return a variable value from a feature test with complex audience conditions via getFeatureVariable', function() { var variableValue = optlyInstance.getFeatureVariable('feat2_with_var', 'z', 'user1', { // Should be included via exact match string audience with id '3468206642', and @@ -4506,6 +5215,19 @@ describe('lib/optimizely', function() { {} ); }); + + it('can return the default value for a feature variable from getFeatureVariableString, via excluding a user from a feature test with complex audience conditions', function() { + var variableValue = optlyInstance.getFeatureVariableInteger('feat2_with_var', 'z', 'user1', { + // Should be excluded - no audiences match with no attributes + }); + assert.strictEqual(variableValue, 10); + sinon.assert.calledWithExactly( + audienceEvaluator.evaluate, + optlyInstance.projectConfigManager.getConfig().experiments[3].audienceConditions, + optlyInstance.projectConfigManager.getConfig().audiencesById, + {} + ); + }); }); describe('event batching', function() { @@ -4888,10 +5610,11 @@ describe('lib/optimizely', function() { assert.isNull(optlyInstance.getForcedVariation('my_experiment', 'user1')); assert.isFalse(optlyInstance.isFeatureEnabled('my_feature', 'user1')); assert.deepEqual(optlyInstance.getEnabledFeatures('user1'), []); - assert.isNull(optlyInstance.getFeatureVariable('my_feature', 'my_bool_var', 'user1')); - assert.isNull(optlyInstance.getFeatureVariable('my_feature', 'my_double_var', 'user1')); - assert.isNull(optlyInstance.getFeatureVariable('my_feature', 'my_int_var', 'user1')); - assert.isNull(optlyInstance.getFeatureVariable('my_feature', 'my_str_var', 'user1')); + assert.isNull(optlyInstance.getFeatureVariable('my_feature', 'my_var', 'user1')); + assert.isNull(optlyInstance.getFeatureVariableBoolean('my_feature', 'my_bool_var', 'user1')); + assert.isNull(optlyInstance.getFeatureVariableDouble('my_feature', 'my_double_var', 'user1')); + assert.isNull(optlyInstance.getFeatureVariableInteger('my_feature', 'my_int_var', 'user1')); + assert.isNull(optlyInstance.getFeatureVariableString('my_feature', 'my_str_var', 'user1')); }); it('does not dispatch any events in API methods that dispatch events', function() { From 3926a575c0dd99941da818ebac8ad926ea13305e Mon Sep 17 00:00:00 2001 From: Brandon Date: Thu, 27 Jun 2019 17:07:53 -0700 Subject: [PATCH 06/10] comment change --- packages/optimizely-sdk/lib/optimizely/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/optimizely-sdk/lib/optimizely/index.js b/packages/optimizely-sdk/lib/optimizely/index.js index db1540767..69e54f3b9 100644 --- a/packages/optimizely-sdk/lib/optimizely/index.js +++ b/packages/optimizely-sdk/lib/optimizely/index.js @@ -659,7 +659,7 @@ Optimizely.prototype.getEnabledFeatures = function(userId, attributes) { * @param {Object} attributes Optional user attributes * @return {*} Value of the variable cast to the appropriate * type, or null if the feature key is invalid or - * the variable key is invalid. + * the variable key is invalid */ Optimizely.prototype.getFeatureVariable = function(featureKey, variableKey, userId, attributes) { From f0d1cb8c25639827b8280680611b0a3b8aa3aa42 Mon Sep 17 00:00:00 2001 From: Brandon Date: Fri, 28 Jun 2019 11:01:55 -0700 Subject: [PATCH 07/10] replace wildcard return type, use private method in getFeatureVariable --- .../optimizely-sdk/lib/optimizely/index.js | 150 +++++------------- 1 file changed, 40 insertions(+), 110 deletions(-) diff --git a/packages/optimizely-sdk/lib/optimizely/index.js b/packages/optimizely-sdk/lib/optimizely/index.js index 69e54f3b9..443d880d3 100644 --- a/packages/optimizely-sdk/lib/optimizely/index.js +++ b/packages/optimizely-sdk/lib/optimizely/index.js @@ -648,121 +648,49 @@ Optimizely.prototype.getEnabledFeatures = function(userId, attributes) { }; /** - * Returns value of the variable attached to the given feature flag. - * Returns null if the feature key or variable key is invalid. + * Returns dynamically-typed value of the variable attached to the given + * feature flag. Returns null if the feature key or variable key is invalid. * - * @param {string} featureKey Key of the feature whose variable's value is - * being accessed - * @param {string} variableKey Key of the variable whose value is being - * accessed - * @param {string} userId ID for the user - * @param {Object} attributes Optional user attributes - * @return {*} Value of the variable cast to the appropriate - * type, or null if the feature key is invalid or - * the variable key is invalid + * @param {string} featureKey Key of the feature whose variable's + * value is being accessed + * @param {string} variableKey Key of the variable whose value is + * being accessed + * @param {string} userId ID for the user + * @param {Object} attributes Optional user attributes + * @return {string|boolean|number|null} Value of the variable cast to the appropriate + * type, or null if the feature key is invalid or + * the variable key is invalid */ Optimizely.prototype.getFeatureVariable = function(featureKey, variableKey, userId, attributes) { - if (!this.__isValidInstance()) { - var apiName = 'getFeatureVariable'; - this.logger.log(LOG_LEVEL.ERROR, sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, apiName)); - return null; - } - - if (!this.__validateInputs({ feature_key: featureKey, variable_key: variableKey, user_id: userId }, attributes)) { - return null; - } - - var configObj = this.projectConfigManager.getConfig(); - if (!configObj) { - return null; - } - - var featureFlag = projectConfig.getFeatureFromKey(configObj, featureKey, this.logger); - if (!featureFlag) { - return null; - } - - var variable = projectConfig.getVariableForFeature(configObj, featureKey, variableKey, this.logger); - if (!variable) { - return null; - } - - var featureEnabled = false; - var variableValue = variable.defaultValue; - var decision = this.decisionService.getVariationForFeature(configObj, featureFlag, userId, attributes); - - if (decision.variation !== null) { - featureEnabled = decision.variation.featureEnabled; - var value = projectConfig.getVariableValueForVariation(configObj, variable, decision.variation, this.logger); - if (value !== null) { - if (featureEnabled === true) { - variableValue = value; - this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.USER_RECEIVED_VARIABLE_VALUE, MODULE_NAME, variableKey, featureFlag.key, variableValue, userId)); - } else { - this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.FEATURE_NOT_ENABLED_RETURN_DEFAULT_VARIABLE_VALUE, MODULE_NAME, - featureFlag.key, userId, variableKey)); - } - } else { - this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.VARIABLE_NOT_USED_RETURN_DEFAULT_VARIABLE_VALUE, MODULE_NAME, variableKey, decision.variation.key)); - } - } else { - this.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.USER_RECEIVED_DEFAULT_VARIABLE_VALUE, MODULE_NAME, userId, - variableKey, featureFlag.key)); - } - - var sourceInfo = {}; - if (decision.decisionSource === DECISION_SOURCES.FEATURE_TEST) { - sourceInfo = { - experimentKey: decision.experiment.key, - variationKey: decision.variation.key, - } - } - - var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variable.type, this.logger); - this.notificationCenter.sendNotifications( - NOTIFICATION_TYPES.DECISION, - { - type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, - userId: userId, - attributes: attributes || {}, - decisionInfo: { - featureKey: featureKey, - featureEnabled: featureEnabled, - source: decision.decisionSource, - variableKey: variableKey, - variableValue: typeCastedValue, - variableType: variable.type, - sourceInfo: sourceInfo, - } - } - ); - return typeCastedValue; + return this._getFeatureVariableForType(featureKey, variableKey, null, userId, attributes); }; /** * Helper method to get the value for a variable of a certain type attached to a * feature flag. Returns null if the feature key is invalid, the variable key is * invalid, the given variable type does not match the variable's actual type, - * or the variable value cannot be cast to the required type. + * or the variable value cannot be cast to the required type. If the given variable + * type is null, the value of the variable cast to the appropriate type is returned. * - * @param {string} featureKey Key of the feature whose variable's value is - * being accessed - * @param {string} variableKey Key of the variable whose value is being - * accessed - * @param {string} variableType Type of the variable whose value is being - * accessed (must be one of FEATURE_VARIABLE_TYPES - * in lib/utils/enums/index.js) - * @param {string} userId ID for the user - * @param {Object} attributes Optional user attributes - * @return {*} Value of the variable cast to the appropriate - * type, or null if the feature key is invalid, the - * variable key is invalid, or there is a mismatch - * with the type of the variable + * @param {string} featureKey Key of the feature whose variable's value is + * being accessed + * @param {string} variableKey Key of the variable whose value is being + * accessed + * @param {string|null} variableType Type of the variable whose value is being + * accessed (must be one of FEATURE_VARIABLE_TYPES + * in lib/utils/enums/index.js), or null to return the + * value of the variable cast to the appropriate type + * @param {string} userId ID for the user + * @param {Object} attributes Optional user attributes + * @return {string|boolean|number|null} Value of the variable cast to the appropriate + * type, or null if the feature key is invalid, the + * variable key is invalid, or there is a mismatch + * with the type of the variable */ Optimizely.prototype._getFeatureVariableForType = function(featureKey, variableKey, variableType, userId, attributes) { if (!this.__isValidInstance()) { - var apiName = 'getFeatureVariable' + variableType.charAt(0).toUpperCase() + variableType.slice(1); + var apiName = (variableType) ? 'getFeatureVariable' + variableType.charAt(0).toUpperCase() + variableType.slice(1) : 'getFeatureVariable'; this.logger.log(LOG_LEVEL.ERROR, sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, apiName)); return null; } @@ -785,13 +713,15 @@ Optimizely.prototype._getFeatureVariableForType = function(featureKey, variableK if (!variable) { return null; } - - if (variable.type !== variableType) { - this.logger.log( - LOG_LEVEL.WARNING, - sprintf(LOG_MESSAGES.VARIABLE_REQUESTED_WITH_WRONG_TYPE, MODULE_NAME, variableType, variable.type) - ); - return null; + + if (variableType) { + if (variable.type !== variableType) { + this.logger.log( + LOG_LEVEL.WARNING, + sprintf(LOG_MESSAGES.VARIABLE_REQUESTED_WITH_WRONG_TYPE, MODULE_NAME, variableType, variable.type) + ); + return null; + } } var featureEnabled = false; @@ -825,7 +755,7 @@ Optimizely.prototype._getFeatureVariableForType = function(featureKey, variableK } } - var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variableType, this.logger); + var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variable.type, this.logger); this.notificationCenter.sendNotifications( NOTIFICATION_TYPES.DECISION, { @@ -838,7 +768,7 @@ Optimizely.prototype._getFeatureVariableForType = function(featureKey, variableK source: decision.decisionSource, variableKey: variableKey, variableValue: typeCastedValue, - variableType: variableType, + variableType: variable.type, sourceInfo: sourceInfo, } } From 420ff4684824e29f4d7feda46013b714406b2ad0 Mon Sep 17 00:00:00 2001 From: Brandon Date: Mon, 1 Jul 2019 10:58:28 -0700 Subject: [PATCH 08/10] minor package-lock json change --- package-lock.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index e556c97c9..1e42f5534 100644 --- a/package-lock.json +++ b/package-lock.json @@ -778,6 +778,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "optional": true, "requires": { "kind-of": "^3.0.2", "longest": "^1.0.1", @@ -788,6 +789,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "optional": true, "requires": { "is-buffer": "^1.1.5" } @@ -2970,7 +2972,8 @@ "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "optional": true }, "loud-rejection": { "version": "1.6.0", From f5de45298b3847d3c5d789524aca5f17488f176e Mon Sep 17 00:00:00 2001 From: Brandon Date: Mon, 1 Jul 2019 15:59:51 -0700 Subject: [PATCH 09/10] add try catch to getFeatureVariable, collapse if statements --- .../optimizely-sdk/lib/optimizely/index.js | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/optimizely-sdk/lib/optimizely/index.js b/packages/optimizely-sdk/lib/optimizely/index.js index 443d880d3..7c588d079 100644 --- a/packages/optimizely-sdk/lib/optimizely/index.js +++ b/packages/optimizely-sdk/lib/optimizely/index.js @@ -663,7 +663,13 @@ Optimizely.prototype.getEnabledFeatures = function(userId, attributes) { */ Optimizely.prototype.getFeatureVariable = function(featureKey, variableKey, userId, attributes) { - return this._getFeatureVariableForType(featureKey, variableKey, null, userId, attributes); + try { + return this._getFeatureVariableForType(featureKey, variableKey, null, userId, attributes); + } catch (e) { + this.logger.log(LOG_LEVEL.ERROR, e.message); + this.errorHandler.handleError(e); + return null; + } }; /** @@ -714,14 +720,12 @@ Optimizely.prototype._getFeatureVariableForType = function(featureKey, variableK return null; } - if (variableType) { - if (variable.type !== variableType) { - this.logger.log( - LOG_LEVEL.WARNING, - sprintf(LOG_MESSAGES.VARIABLE_REQUESTED_WITH_WRONG_TYPE, MODULE_NAME, variableType, variable.type) - ); - return null; - } + if (variableType && variable.type !== variableType) { + this.logger.log( + LOG_LEVEL.WARNING, + sprintf(LOG_MESSAGES.VARIABLE_REQUESTED_WITH_WRONG_TYPE, MODULE_NAME, variableType, variable.type) + ); + return null; } var featureEnabled = false; From 38f4fb7c815a7a0442e516d429a684302c3a2455 Mon Sep 17 00:00:00 2001 From: Brandon Date: Tue, 2 Jul 2019 15:26:15 -0700 Subject: [PATCH 10/10] set variableType = variable.type to avoid changes downstream --- packages/optimizely-sdk/lib/optimizely/index.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/optimizely-sdk/lib/optimizely/index.js b/packages/optimizely-sdk/lib/optimizely/index.js index 7c588d079..27854918d 100644 --- a/packages/optimizely-sdk/lib/optimizely/index.js +++ b/packages/optimizely-sdk/lib/optimizely/index.js @@ -719,8 +719,10 @@ Optimizely.prototype._getFeatureVariableForType = function(featureKey, variableK if (!variable) { return null; } - - if (variableType && variable.type !== variableType) { + + if (!variableType) { + variableType = variable.type; + } else if (variable.type !== variableType) { this.logger.log( LOG_LEVEL.WARNING, sprintf(LOG_MESSAGES.VARIABLE_REQUESTED_WITH_WRONG_TYPE, MODULE_NAME, variableType, variable.type) @@ -759,7 +761,7 @@ Optimizely.prototype._getFeatureVariableForType = function(featureKey, variableK } } - var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variable.type, this.logger); + var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variableType, this.logger); this.notificationCenter.sendNotifications( NOTIFICATION_TYPES.DECISION, { @@ -772,7 +774,7 @@ Optimizely.prototype._getFeatureVariableForType = function(featureKey, variableK source: decision.decisionSource, variableKey: variableKey, variableValue: typeCastedValue, - variableType: variable.type, + variableType: variableType, sourceInfo: sourceInfo, } }