diff --git a/lib/core/audience_evaluator/index.ts b/lib/core/audience_evaluator/index.ts index b39cacb8a..5bb9f5a15 100644 --- a/lib/core/audience_evaluator/index.ts +++ b/lib/core/audience_evaluator/index.ts @@ -18,13 +18,13 @@ import { getLogger } from '../../modules/logging'; import fns from '../../utils/fns'; import { LOG_LEVEL, - LOG_MESSAGES, - ERROR_MESSAGES, } from '../../utils/enums'; import * as conditionTreeEvaluator from '../condition_tree_evaluator'; import * as customAttributeConditionEvaluator from '../custom_attribute_condition_evaluator'; import * as odpSegmentsConditionEvaluator from './odp_segment_condition_evaluator'; import { Audience, Condition, OptimizelyUserContext } from '../../shared_types'; +import { CONDITION_EVALUATOR_ERROR, UNKNOWN_CONDITION_TYPE } from '../../error_messages'; +import { AUDIENCE_EVALUATION_RESULT, EVALUATING_AUDIENCE} from '../../log_messages'; const logger = getLogger(); const MODULE_NAME = 'AUDIENCE_EVALUATOR'; @@ -79,14 +79,14 @@ export class AudienceEvaluator { if (audience) { logger.log( LOG_LEVEL.DEBUG, - LOG_MESSAGES.EVALUATING_AUDIENCE, MODULE_NAME, audienceId, JSON.stringify(audience.conditions) + EVALUATING_AUDIENCE, MODULE_NAME, audienceId, JSON.stringify(audience.conditions) ); const result = conditionTreeEvaluator.evaluate( audience.conditions as unknown[] , this.evaluateConditionWithUserAttributes.bind(this, user) ); const resultText = result === null ? 'UNKNOWN' : result.toString().toUpperCase(); - logger.log(LOG_LEVEL.DEBUG, LOG_MESSAGES.AUDIENCE_EVALUATION_RESULT, MODULE_NAME, audienceId, resultText); + logger.log(LOG_LEVEL.DEBUG, AUDIENCE_EVALUATION_RESULT, MODULE_NAME, audienceId, resultText); return result; } return null; @@ -105,7 +105,7 @@ export class AudienceEvaluator { evaluateConditionWithUserAttributes(user: OptimizelyUserContext, condition: Condition): boolean | null { const evaluator = this.typeToEvaluatorMap[condition.type]; if (!evaluator) { - logger.log(LOG_LEVEL.WARNING, LOG_MESSAGES.UNKNOWN_CONDITION_TYPE, MODULE_NAME, JSON.stringify(condition)); + logger.log(LOG_LEVEL.WARNING, UNKNOWN_CONDITION_TYPE, MODULE_NAME, JSON.stringify(condition)); return null; } try { @@ -113,7 +113,7 @@ export class AudienceEvaluator { } catch (err: any) { logger.log( LOG_LEVEL.ERROR, - ERROR_MESSAGES.CONDITION_EVALUATOR_ERROR, MODULE_NAME, condition.type, err.message + CONDITION_EVALUATOR_ERROR, MODULE_NAME, condition.type, err.message ); } diff --git a/lib/core/audience_evaluator/odp_segment_condition_evaluator/index.tests.js b/lib/core/audience_evaluator/odp_segment_condition_evaluator/index.tests.js index 503017545..768484b24 100644 --- a/lib/core/audience_evaluator/odp_segment_condition_evaluator/index.tests.js +++ b/lib/core/audience_evaluator/odp_segment_condition_evaluator/index.tests.js @@ -17,12 +17,10 @@ import sinon from 'sinon'; import { assert } from 'chai'; import { sprintf } from '../../../utils/fns'; -import { - LOG_LEVEL, - LOG_MESSAGES, -} from '../../../utils/enums'; +import { LOG_LEVEL } from '../../../utils/enums'; import * as logging from '../../../modules/logging'; import * as odpSegmentEvalutor from './'; +import { UNKNOWN_MATCH_TYPE } from '../../../error_messages'; var odpSegment1Condition = { "value": "odp-segment-1", @@ -68,6 +66,6 @@ describe('lib/core/audience_evaluator/odp_segment_condition_evaluator', function sinon.assert.calledOnce(stubLogHandler.log); assert.strictEqual(stubLogHandler.log.args[0][0], LOG_LEVEL.WARNING); var logMessage = stubLogHandler.log.args[0][1]; - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.UNKNOWN_MATCH_TYPE, 'ODP_SEGMENT_CONDITION_EVALUATOR', JSON.stringify(invalidOdpMatchCondition))); + assert.strictEqual(logMessage, sprintf(UNKNOWN_MATCH_TYPE, 'ODP_SEGMENT_CONDITION_EVALUATOR', JSON.stringify(invalidOdpMatchCondition))); }); }); diff --git a/lib/core/audience_evaluator/odp_segment_condition_evaluator/index.ts b/lib/core/audience_evaluator/odp_segment_condition_evaluator/index.ts index 3098ae2b0..54d7b5d93 100644 --- a/lib/core/audience_evaluator/odp_segment_condition_evaluator/index.ts +++ b/lib/core/audience_evaluator/odp_segment_condition_evaluator/index.ts @@ -13,11 +13,10 @@ * See the License for the specific language governing permissions and * * limitations under the License. * ***************************************************************************/ +import { UNKNOWN_MATCH_TYPE } from '../../../error_messages'; import { getLogger } from '../../../modules/logging'; import { Condition, OptimizelyUserContext } from '../../../shared_types'; -import { LOG_MESSAGES } from '../../../utils/enums'; - const MODULE_NAME = 'ODP_SEGMENT_CONDITION_EVALUATOR'; const logger = getLogger(); @@ -45,7 +44,7 @@ EVALUATORS_BY_MATCH_TYPE[QUALIFIED_MATCH_TYPE] = qualifiedEvaluator; export function evaluate(condition: Condition, user: OptimizelyUserContext): boolean | null { const conditionMatch = condition.match; if (typeof conditionMatch !== 'undefined' && MATCH_TYPES.indexOf(conditionMatch) === -1) { - logger.warn(LOG_MESSAGES.UNKNOWN_MATCH_TYPE, MODULE_NAME, JSON.stringify(condition)); + logger.warn(UNKNOWN_MATCH_TYPE, MODULE_NAME, JSON.stringify(condition)); return null; } diff --git a/lib/core/bucketer/index.tests.js b/lib/core/bucketer/index.tests.js index e30c9129e..eb4ec87eb 100644 --- a/lib/core/bucketer/index.tests.js +++ b/lib/core/bucketer/index.tests.js @@ -19,14 +19,17 @@ import { cloneDeep } from 'lodash'; import { sprintf } from '../../utils/fns'; import * as bucketer from './'; -import { - ERROR_MESSAGES, - LOG_MESSAGES, - LOG_LEVEL, -} from '../../utils/enums'; +import { LOG_LEVEL } from '../../utils/enums'; import { createLogger } from '../../plugins/logger'; import projectConfig from '../../project_config/project_config'; import { getTestProjectConfig } from '../../tests/test_data'; +import { INVALID_BUCKETING_ID, INVALID_GROUP_ID } from '../../error_messages'; +import { + USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP, + USER_NOT_BUCKETED_INTO_EXPERIMENT_IN_GROUP, + USER_NOT_IN_ANY_EXPERIMENT, + USER_ASSIGNED_TO_EXPERIMENT_BUCKET, +} from '.'; var buildLogMessageFromArgs = args => sprintf(args[1], ...args.splice(2)); var testData = getTestProjectConfig(); @@ -78,7 +81,7 @@ describe('lib/core/bucketer', function () { var bucketedUser_log1 = buildLogMessageFromArgs(createdLogger.log.args[0]); expect(bucketedUser_log1).to.equal( - sprintf(LOG_MESSAGES.USER_ASSIGNED_TO_EXPERIMENT_BUCKET, 'BUCKETER', '50', 'ppid1') + sprintf(USER_ASSIGNED_TO_EXPERIMENT_BUCKET, 'BUCKETER', '50', 'ppid1') ); var bucketerParamsTest2 = cloneDeep(bucketerParams); @@ -88,7 +91,7 @@ describe('lib/core/bucketer', function () { var notBucketedUser_log1 = buildLogMessageFromArgs(createdLogger.log.args[1]); expect(notBucketedUser_log1).to.equal( - sprintf(LOG_MESSAGES.USER_ASSIGNED_TO_EXPERIMENT_BUCKET, 'BUCKETER', '50000', 'ppid2') + sprintf(USER_ASSIGNED_TO_EXPERIMENT_BUCKET, 'BUCKETER', '50000', 'ppid2') ); }); }); @@ -140,13 +143,13 @@ describe('lib/core/bucketer', function () { var log1 = buildLogMessageFromArgs(createdLogger.log.args[0]); expect(log1).to.equal( - sprintf(LOG_MESSAGES.USER_ASSIGNED_TO_EXPERIMENT_BUCKET, 'BUCKETER', '50', 'testUser') + sprintf(USER_ASSIGNED_TO_EXPERIMENT_BUCKET, 'BUCKETER', '50', 'testUser') ); var log2 = buildLogMessageFromArgs(createdLogger.log.args[1]); expect(log2).to.equal( sprintf( - LOG_MESSAGES.USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP, + USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP, 'BUCKETER', 'testUser', 'groupExperiment1', @@ -156,7 +159,7 @@ describe('lib/core/bucketer', function () { var log3 = buildLogMessageFromArgs(createdLogger.log.args[2]); expect(log3).to.equal( - sprintf(LOG_MESSAGES.USER_ASSIGNED_TO_EXPERIMENT_BUCKET, 'BUCKETER', '50', 'testUser') + sprintf(USER_ASSIGNED_TO_EXPERIMENT_BUCKET, 'BUCKETER', '50', 'testUser') ); }); @@ -171,12 +174,12 @@ describe('lib/core/bucketer', function () { var log1 = buildLogMessageFromArgs(createdLogger.log.args[0]); expect(log1).to.equal( - sprintf(LOG_MESSAGES.USER_ASSIGNED_TO_EXPERIMENT_BUCKET, 'BUCKETER', '5000', 'testUser') + sprintf(USER_ASSIGNED_TO_EXPERIMENT_BUCKET, 'BUCKETER', '5000', 'testUser') ); var log2 = buildLogMessageFromArgs(createdLogger.log.args[1]); expect(log2).to.equal( sprintf( - LOG_MESSAGES.USER_NOT_BUCKETED_INTO_EXPERIMENT_IN_GROUP, + USER_NOT_BUCKETED_INTO_EXPERIMENT_IN_GROUP, 'BUCKETER', 'testUser', 'groupExperiment1', @@ -196,10 +199,10 @@ describe('lib/core/bucketer', function () { var log1 = buildLogMessageFromArgs(createdLogger.log.args[0]); expect(log1).to.equal( - sprintf(LOG_MESSAGES.USER_ASSIGNED_TO_EXPERIMENT_BUCKET, 'BUCKETER', '50000', 'testUser') + sprintf(USER_ASSIGNED_TO_EXPERIMENT_BUCKET, 'BUCKETER', '50000', 'testUser') ); var log2 = buildLogMessageFromArgs(createdLogger.log.args[1]); - expect(log2).to.equal(sprintf(LOG_MESSAGES.USER_NOT_IN_ANY_EXPERIMENT, 'BUCKETER', 'testUser', '666')); + expect(log2).to.equal(sprintf(USER_NOT_IN_ANY_EXPERIMENT, 'BUCKETER', 'testUser', '666')); }); it('should return decision response with variation null when a user is bucketed into traffic space of deleted experiment within a random group', function () { @@ -213,10 +216,10 @@ describe('lib/core/bucketer', function () { var log1 = buildLogMessageFromArgs(createdLogger.log.args[0]); expect(log1).to.equal( - sprintf(LOG_MESSAGES.USER_ASSIGNED_TO_EXPERIMENT_BUCKET, 'BUCKETER', '9000', 'testUser') + sprintf(USER_ASSIGNED_TO_EXPERIMENT_BUCKET, 'BUCKETER', '9000', 'testUser') ); var log2 = buildLogMessageFromArgs(createdLogger.log.args[1]); - expect(log2).to.equal(sprintf(LOG_MESSAGES.USER_NOT_IN_ANY_EXPERIMENT, 'BUCKETER', 'testUser', '666')); + expect(log2).to.equal(sprintf(USER_NOT_IN_ANY_EXPERIMENT, 'BUCKETER', 'testUser', '666')); }); it('should throw an error if group ID is not in the datafile', function () { @@ -225,7 +228,7 @@ describe('lib/core/bucketer', function () { assert.throws(function () { bucketer.bucket(bucketerParamsWithInvalidGroupId); - }, sprintf(ERROR_MESSAGES.INVALID_GROUP_ID, 'BUCKETER', '6969')); + }, sprintf(INVALID_GROUP_ID, 'BUCKETER', '6969')); }); }); @@ -254,7 +257,7 @@ describe('lib/core/bucketer', function () { sinon.assert.calledOnce(createdLogger.log); var log1 = buildLogMessageFromArgs(createdLogger.log.args[0]); - expect(log1).to.equal(sprintf(LOG_MESSAGES.USER_ASSIGNED_TO_EXPERIMENT_BUCKET, 'BUCKETER', '0', 'testUser')); + expect(log1).to.equal(sprintf(USER_ASSIGNED_TO_EXPERIMENT_BUCKET, 'BUCKETER', '0', 'testUser')); }); it('should return decision response with variation null when a user does not fall into an experiment within an overlapping group', function () { @@ -357,8 +360,8 @@ describe('lib/core/bucketer', function () { bucketer._generateBucketValue(null); } ); expect([ - sprintf(ERROR_MESSAGES.INVALID_BUCKETING_ID, 'BUCKETER', null, "Cannot read property 'length' of null"), // node v14 - sprintf(ERROR_MESSAGES.INVALID_BUCKETING_ID, 'BUCKETER', null, "Cannot read properties of null (reading \'length\')") // node v16 + sprintf(INVALID_BUCKETING_ID, 'BUCKETER', null, "Cannot read property 'length' of null"), // node v14 + sprintf(INVALID_BUCKETING_ID, 'BUCKETER', null, "Cannot read properties of null (reading \'length\')") // node v16 ]).contain(response.message); }); }); diff --git a/lib/core/bucketer/index.ts b/lib/core/bucketer/index.ts index c2c6a0235..96d014dcf 100644 --- a/lib/core/bucketer/index.ts +++ b/lib/core/bucketer/index.ts @@ -27,11 +27,14 @@ import { Group, } from '../../shared_types'; -import { - ERROR_MESSAGES, - LOG_LEVEL, - LOG_MESSAGES, -} from '../../utils/enums'; +import { LOG_LEVEL } from '../../utils/enums'; +import { INVALID_BUCKETING_ID, INVALID_GROUP_ID } from '../../error_messages'; + +export const USER_NOT_IN_ANY_EXPERIMENT = '%s: User %s is not in any experiment of group %s.'; +export const USER_NOT_BUCKETED_INTO_EXPERIMENT_IN_GROUP = '%s: User %s is not in experiment %s of group %s.'; +export const USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP = '%s: User %s is in experiment %s of group %s.'; +export const USER_ASSIGNED_TO_EXPERIMENT_BUCKET = '%s: Assigned bucket %s to user with bucketing ID %s.'; +export const INVALID_VARIATION_ID = '%s: Bucketed into an invalid variation ID. Returning null.'; const HASH_SEED = 1; const MAX_HASH_VALUE = Math.pow(2, 32); @@ -63,7 +66,7 @@ export const bucket = function(bucketerParams: BucketerParams): DecisionResponse if (groupId) { const group = bucketerParams.groupIdMap[groupId]; if (!group) { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_GROUP_ID, MODULE_NAME, groupId)); + throw new Error(sprintf(INVALID_GROUP_ID, MODULE_NAME, groupId)); } if (group.policy === RANDOM_POLICY) { const bucketedExperimentId = bucketUserIntoExperiment( @@ -77,13 +80,13 @@ export const bucket = function(bucketerParams: BucketerParams): DecisionResponse if (bucketedExperimentId === null) { bucketerParams.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.USER_NOT_IN_ANY_EXPERIMENT, + USER_NOT_IN_ANY_EXPERIMENT, MODULE_NAME, bucketerParams.userId, groupId, ); decideReasons.push([ - LOG_MESSAGES.USER_NOT_IN_ANY_EXPERIMENT, + USER_NOT_IN_ANY_EXPERIMENT, MODULE_NAME, bucketerParams.userId, groupId, @@ -98,14 +101,14 @@ export const bucket = function(bucketerParams: BucketerParams): DecisionResponse if (bucketedExperimentId !== bucketerParams.experimentId) { bucketerParams.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.USER_NOT_BUCKETED_INTO_EXPERIMENT_IN_GROUP, + USER_NOT_BUCKETED_INTO_EXPERIMENT_IN_GROUP, MODULE_NAME, bucketerParams.userId, bucketerParams.experimentKey, groupId, ); decideReasons.push([ - LOG_MESSAGES.USER_NOT_BUCKETED_INTO_EXPERIMENT_IN_GROUP, + USER_NOT_BUCKETED_INTO_EXPERIMENT_IN_GROUP, MODULE_NAME, bucketerParams.userId, bucketerParams.experimentKey, @@ -120,14 +123,14 @@ export const bucket = function(bucketerParams: BucketerParams): DecisionResponse // Continue bucketing if user is bucketed into specified experiment bucketerParams.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP, + USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP, MODULE_NAME, bucketerParams.userId, bucketerParams.experimentKey, groupId, ); decideReasons.push([ - LOG_MESSAGES.USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP, + USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP, MODULE_NAME, bucketerParams.userId, bucketerParams.experimentKey, @@ -140,13 +143,13 @@ export const bucket = function(bucketerParams: BucketerParams): DecisionResponse bucketerParams.logger.log( LOG_LEVEL.DEBUG, - LOG_MESSAGES.USER_ASSIGNED_TO_EXPERIMENT_BUCKET, + USER_ASSIGNED_TO_EXPERIMENT_BUCKET, MODULE_NAME, bucketValue, bucketerParams.userId, ); decideReasons.push([ - LOG_MESSAGES.USER_ASSIGNED_TO_EXPERIMENT_BUCKET, + USER_ASSIGNED_TO_EXPERIMENT_BUCKET, MODULE_NAME, bucketValue, bucketerParams.userId, @@ -156,8 +159,8 @@ export const bucket = function(bucketerParams: BucketerParams): DecisionResponse if (entityId !== null) { if (!bucketerParams.variationIdMap[entityId]) { if (entityId) { - bucketerParams.logger.log(LOG_LEVEL.WARNING, LOG_MESSAGES.INVALID_VARIATION_ID, MODULE_NAME); - decideReasons.push([LOG_MESSAGES.INVALID_VARIATION_ID, MODULE_NAME]); + bucketerParams.logger.log(LOG_LEVEL.WARNING, INVALID_VARIATION_ID, MODULE_NAME); + decideReasons.push([INVALID_VARIATION_ID, MODULE_NAME]); } return { result: null, @@ -190,7 +193,7 @@ export const bucketUserIntoExperiment = function( const bucketValue = _generateBucketValue(bucketingKey); logger.log( LOG_LEVEL.DEBUG, - LOG_MESSAGES.USER_ASSIGNED_TO_EXPERIMENT_BUCKET, + USER_ASSIGNED_TO_EXPERIMENT_BUCKET, MODULE_NAME, bucketValue, userId, @@ -235,7 +238,7 @@ export const _generateBucketValue = function(bucketingKey: string): number { const ratio = hashValue / MAX_HASH_VALUE; return Math.floor(ratio * MAX_TRAFFIC_VALUE); } catch (ex: any) { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_BUCKETING_ID, MODULE_NAME, bucketingKey, ex.message)); + throw new Error(sprintf(INVALID_BUCKETING_ID, MODULE_NAME, bucketingKey, ex.message)); } }; diff --git a/lib/core/custom_attribute_condition_evaluator/index.tests.js b/lib/core/custom_attribute_condition_evaluator/index.tests.js index b594cf898..5cf0e44c9 100644 --- a/lib/core/custom_attribute_condition_evaluator/index.tests.js +++ b/lib/core/custom_attribute_condition_evaluator/index.tests.js @@ -19,10 +19,17 @@ import { sprintf } from '../../utils/fns'; import { LOG_LEVEL, - LOG_MESSAGES, } from '../../utils/enums'; import * as logging from '../../modules/logging'; import * as customAttributeEvaluator from './'; +import { + MISSING_ATTRIBUTE_VALUE, + OUT_OF_BOUNDS, + UNEXPECTED_CONDITION_VALUE, + UNEXPECTED_TYPE, + UNEXPECTED_TYPE_NULL, +} from '../../log_messages'; +import { UNKNOWN_MATCH_TYPE } from '../../error_messages'; var browserConditionSafari = { name: 'browser_type', @@ -104,7 +111,7 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { sinon.assert.calledOnce(stubLogHandler.log); assert.strictEqual(stubLogHandler.log.args[0][0], LOG_LEVEL.WARNING); var logMessage = stubLogHandler.log.args[0][1]; - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.UNKNOWN_MATCH_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(invalidMatchCondition))); + assert.strictEqual(logMessage, sprintf(UNKNOWN_MATCH_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(invalidMatchCondition))); }); describe('exists match type', function() { @@ -186,7 +193,7 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { sinon.assert.calledOnce(stubLogHandler.log); assert.strictEqual(stubLogHandler.log.args[0][0], LOG_LEVEL.WARNING); var logMessage = stubLogHandler.log.args[0][1]; - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.UNEXPECTED_CONDITION_VALUE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(invalidExactCondition))); + assert.strictEqual(logMessage, sprintf(UNEXPECTED_CONDITION_VALUE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(invalidExactCondition))); }); it('should log and return null if the user-provided value is of a different type than the condition value', function() { @@ -204,7 +211,7 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { var logMessage = stubLogHandler.log.args[0][1]; assert.strictEqual( logMessage, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(exactStringCondition), userValueType, exactStringCondition.name) + sprintf(UNEXPECTED_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(exactStringCondition), userValueType, exactStringCondition.name) ); }); @@ -219,7 +226,7 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { var logMessage = stubLogHandler.log.args[0][1]; assert.strictEqual( logMessage, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE_NULL, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(exactStringCondition), exactStringCondition.name) + sprintf(UNEXPECTED_TYPE_NULL, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(exactStringCondition), exactStringCondition.name) ); }); @@ -231,7 +238,7 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { var logMessage = stubLogHandler.log.args[0][1]; assert.strictEqual( logMessage, - sprintf(LOG_MESSAGES.MISSING_ATTRIBUTE_VALUE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(exactStringCondition), exactStringCondition.name) + sprintf(MISSING_ATTRIBUTE_VALUE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(exactStringCondition), exactStringCondition.name) ); }); @@ -249,7 +256,7 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { var logMessage = stubLogHandler.log.args[0][1]; assert.strictEqual( logMessage, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(exactStringCondition), userValueType, exactStringCondition.name) + sprintf(UNEXPECTED_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(exactStringCondition), userValueType, exactStringCondition.name) ); }); }); @@ -299,11 +306,11 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { var logMessage2 = stubLogHandler.log.args[1][1]; assert.strictEqual( logMessage1, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(exactNumberCondition), userValueType1, exactNumberCondition.name) + sprintf(UNEXPECTED_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(exactNumberCondition), userValueType1, exactNumberCondition.name) ); assert.strictEqual( logMessage2, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(exactNumberCondition), userValueType2, exactNumberCondition.name) + sprintf(UNEXPECTED_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(exactNumberCondition), userValueType2, exactNumberCondition.name) ); }); @@ -325,11 +332,11 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { var logMessage2 = stubLogHandler.log.args[1][1]; assert.strictEqual( logMessage1, - sprintf(LOG_MESSAGES.OUT_OF_BOUNDS, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(exactNumberCondition), exactNumberCondition.name) + sprintf(OUT_OF_BOUNDS, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(exactNumberCondition), exactNumberCondition.name) ); assert.strictEqual( logMessage2, - sprintf(LOG_MESSAGES.OUT_OF_BOUNDS, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(exactNumberCondition), exactNumberCondition.name) + sprintf(OUT_OF_BOUNDS, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(exactNumberCondition), exactNumberCondition.name) ); }); @@ -365,11 +372,11 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { var logMessage2 = stubLogHandler.log.args[1][1]; assert.strictEqual( logMessage1, - sprintf(LOG_MESSAGES.UNEXPECTED_CONDITION_VALUE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(invalidValueCondition1)) + sprintf(UNEXPECTED_CONDITION_VALUE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(invalidValueCondition1)) ); assert.strictEqual( logMessage2, - sprintf(LOG_MESSAGES.UNEXPECTED_CONDITION_VALUE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(invalidValueCondition2)) + sprintf(UNEXPECTED_CONDITION_VALUE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(invalidValueCondition2)) ); }); }); @@ -446,7 +453,7 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { var logMessage = stubLogHandler.log.args[0][1]; assert.strictEqual( logMessage, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(substringCondition), userValueType, substringCondition.name) + sprintf(UNEXPECTED_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(substringCondition), userValueType, substringCondition.name) ); }); @@ -465,7 +472,7 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { var logMessage = stubLogHandler.log.args[0][1]; assert.strictEqual( logMessage, - sprintf(LOG_MESSAGES.UNEXPECTED_CONDITION_VALUE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(nonStringCondition)) + sprintf(UNEXPECTED_CONDITION_VALUE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(nonStringCondition)) ); }); @@ -477,7 +484,7 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { var logMessage = stubLogHandler.log.args[0][1]; assert.strictEqual( logMessage, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE_NULL, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(substringCondition), substringCondition.name) + sprintf(UNEXPECTED_TYPE_NULL, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(substringCondition), substringCondition.name) ); }); @@ -542,11 +549,11 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { var logMessage2 = stubLogHandler.log.args[1][1]; assert.strictEqual( logMessage1, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(gtCondition), userValueType1, gtCondition.name) + sprintf(UNEXPECTED_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(gtCondition), userValueType1, gtCondition.name) ); assert.strictEqual( logMessage2, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(gtCondition), userValueType2, gtCondition.name) + sprintf(UNEXPECTED_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(gtCondition), userValueType2, gtCondition.name) ); }); @@ -571,11 +578,11 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { var logMessage2 = stubLogHandler.log.args[1][1]; assert.strictEqual( logMessage1, - sprintf(LOG_MESSAGES.OUT_OF_BOUNDS, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(gtCondition), gtCondition.name) + sprintf(OUT_OF_BOUNDS, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(gtCondition), gtCondition.name) ); assert.strictEqual( logMessage2, - sprintf(LOG_MESSAGES.OUT_OF_BOUNDS, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(gtCondition), gtCondition.name) + sprintf(OUT_OF_BOUNDS, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(gtCondition), gtCondition.name) ); }); @@ -587,7 +594,7 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { var logMessage = stubLogHandler.log.args[0][1]; assert.strictEqual( logMessage, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE_NULL, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(gtCondition), gtCondition.name) + sprintf(UNEXPECTED_TYPE_NULL, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(gtCondition), gtCondition.name) ); }); @@ -619,7 +626,7 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { var logMessage = stubLogHandler.log.args[2][1]; assert.strictEqual( logMessage, - sprintf(LOG_MESSAGES.UNEXPECTED_CONDITION_VALUE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(invalidValueCondition)) + sprintf(UNEXPECTED_CONDITION_VALUE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(invalidValueCondition)) ); }); }); @@ -679,11 +686,11 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { var logMessage2 = stubLogHandler.log.args[1][1]; assert.strictEqual( logMessage1, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(ltCondition), userValueType1, ltCondition.name) + sprintf(UNEXPECTED_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(ltCondition), userValueType1, ltCondition.name) ); assert.strictEqual( logMessage2, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(ltCondition), userValueType2, ltCondition.name) + sprintf(UNEXPECTED_TYPE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(ltCondition), userValueType2, ltCondition.name) ); }); @@ -712,11 +719,11 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { var logMessage2 = stubLogHandler.log.args[1][1]; assert.strictEqual( logMessage1, - sprintf(LOG_MESSAGES.OUT_OF_BOUNDS, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(ltCondition), ltCondition.name) + sprintf(OUT_OF_BOUNDS, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(ltCondition), ltCondition.name) ); assert.strictEqual( logMessage2, - sprintf(LOG_MESSAGES.OUT_OF_BOUNDS, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(ltCondition), ltCondition.name) + sprintf(OUT_OF_BOUNDS, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(ltCondition), ltCondition.name) ); }); @@ -728,7 +735,7 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { var logMessage = stubLogHandler.log.args[0][1]; assert.strictEqual( logMessage, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE_NULL, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(ltCondition), ltCondition.name) + sprintf(UNEXPECTED_TYPE_NULL, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(ltCondition), ltCondition.name) ); }); @@ -760,7 +767,7 @@ describe('lib/core/custom_attribute_condition_evaluator', function() { var logMessage = stubLogHandler.log.args[2][1]; assert.strictEqual( logMessage, - sprintf(LOG_MESSAGES.UNEXPECTED_CONDITION_VALUE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(invalidValueCondition)) + sprintf(UNEXPECTED_CONDITION_VALUE, 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR', JSON.stringify(invalidValueCondition)) ); }); }); diff --git a/lib/core/custom_attribute_condition_evaluator/index.ts b/lib/core/custom_attribute_condition_evaluator/index.ts index a887a2633..ab30a214d 100644 --- a/lib/core/custom_attribute_condition_evaluator/index.ts +++ b/lib/core/custom_attribute_condition_evaluator/index.ts @@ -17,8 +17,15 @@ import { getLogger } from '../../modules/logging'; import { Condition, OptimizelyUserContext } from '../../shared_types'; import fns from '../../utils/fns'; -import { LOG_MESSAGES } from '../../utils/enums'; import { compareVersion } from '../../utils/semantic_version'; +import { + MISSING_ATTRIBUTE_VALUE, + OUT_OF_BOUNDS, + UNEXPECTED_CONDITION_VALUE, + UNEXPECTED_TYPE, + UNEXPECTED_TYPE_NULL, +} from '../../log_messages'; +import { UNKNOWN_MATCH_TYPE } from '../../error_messages'; const MODULE_NAME = 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR'; @@ -81,14 +88,14 @@ export function evaluate(condition: Condition, user: OptimizelyUserContext): boo const userAttributes = user.getAttributes(); const conditionMatch = condition.match; if (typeof conditionMatch !== 'undefined' && MATCH_TYPES.indexOf(conditionMatch) === -1) { - logger.warn(LOG_MESSAGES.UNKNOWN_MATCH_TYPE, MODULE_NAME, JSON.stringify(condition)); + logger.warn(UNKNOWN_MATCH_TYPE, MODULE_NAME, JSON.stringify(condition)); return null; } const attributeKey = condition.name; if (!userAttributes.hasOwnProperty(attributeKey) && conditionMatch != EXISTS_MATCH_TYPE) { logger.debug( - LOG_MESSAGES.MISSING_ATTRIBUTE_VALUE, MODULE_NAME, JSON.stringify(condition), attributeKey + MISSING_ATTRIBUTE_VALUE, MODULE_NAME, JSON.stringify(condition), attributeKey ); return null; } @@ -136,28 +143,28 @@ function exactEvaluator(condition: Condition, user: OptimizelyUserContext): bool (fns.isNumber(conditionValue) && !fns.isSafeInteger(conditionValue)) ) { logger.warn( - LOG_MESSAGES.UNEXPECTED_CONDITION_VALUE, MODULE_NAME, JSON.stringify(condition) + UNEXPECTED_CONDITION_VALUE, MODULE_NAME, JSON.stringify(condition) ); return null; } if (userValue === null) { logger.debug( - LOG_MESSAGES.UNEXPECTED_TYPE_NULL, MODULE_NAME, JSON.stringify(condition), conditionName + UNEXPECTED_TYPE_NULL, MODULE_NAME, JSON.stringify(condition), conditionName ); return null; } if (!isValueTypeValidForExactConditions(userValue) || conditionValueType !== userValueType) { logger.warn( - LOG_MESSAGES.UNEXPECTED_TYPE, MODULE_NAME, JSON.stringify(condition), userValueType, conditionName + UNEXPECTED_TYPE, MODULE_NAME, JSON.stringify(condition), userValueType, conditionName ); return null; } if (fns.isNumber(userValue) && !fns.isSafeInteger(userValue)) { logger.warn( - LOG_MESSAGES.OUT_OF_BOUNDS, MODULE_NAME, JSON.stringify(condition), conditionName + OUT_OF_BOUNDS, MODULE_NAME, JSON.stringify(condition), conditionName ); return null; } @@ -196,28 +203,28 @@ function validateValuesForNumericCondition(condition: Condition, user: Optimizel if (conditionValue === null || !fns.isSafeInteger(conditionValue)) { logger.warn( - LOG_MESSAGES.UNEXPECTED_CONDITION_VALUE, MODULE_NAME, JSON.stringify(condition) + UNEXPECTED_CONDITION_VALUE, MODULE_NAME, JSON.stringify(condition) ); return false; } if (userValue === null) { logger.debug( - LOG_MESSAGES.UNEXPECTED_TYPE_NULL, MODULE_NAME, JSON.stringify(condition), conditionName + UNEXPECTED_TYPE_NULL, MODULE_NAME, JSON.stringify(condition), conditionName ); return false; } if (!fns.isNumber(userValue)) { logger.warn( - LOG_MESSAGES.UNEXPECTED_TYPE, MODULE_NAME, JSON.stringify(condition), userValueType, conditionName + UNEXPECTED_TYPE, MODULE_NAME, JSON.stringify(condition), userValueType, conditionName ); return false; } if (!fns.isSafeInteger(userValue)) { logger.warn( - LOG_MESSAGES.OUT_OF_BOUNDS, MODULE_NAME, JSON.stringify(condition), conditionName + OUT_OF_BOUNDS, MODULE_NAME, JSON.stringify(condition), conditionName ); return false; } @@ -325,21 +332,21 @@ function substringEvaluator(condition: Condition, user: OptimizelyUserContext): if (typeof conditionValue !== 'string') { logger.warn( - LOG_MESSAGES.UNEXPECTED_CONDITION_VALUE, MODULE_NAME, JSON.stringify(condition) + UNEXPECTED_CONDITION_VALUE, MODULE_NAME, JSON.stringify(condition) ); return null; } if (userValue === null) { logger.debug( - LOG_MESSAGES.UNEXPECTED_TYPE_NULL, MODULE_NAME, JSON.stringify(condition), conditionName + UNEXPECTED_TYPE_NULL, MODULE_NAME, JSON.stringify(condition), conditionName ); return null; } if (typeof userValue !== 'string') { logger.warn( - LOG_MESSAGES.UNEXPECTED_TYPE, MODULE_NAME, JSON.stringify(condition), userValueType, conditionName + UNEXPECTED_TYPE, MODULE_NAME, JSON.stringify(condition), userValueType, conditionName ); return null; } @@ -363,21 +370,21 @@ function evaluateSemanticVersion(condition: Condition, user: OptimizelyUserConte if (typeof conditionValue !== 'string') { logger.warn( - LOG_MESSAGES.UNEXPECTED_CONDITION_VALUE, MODULE_NAME, JSON.stringify(condition) + UNEXPECTED_CONDITION_VALUE, MODULE_NAME, JSON.stringify(condition) ); return null; } if (userValue === null) { logger.debug( - LOG_MESSAGES.UNEXPECTED_TYPE_NULL, MODULE_NAME, JSON.stringify(condition), conditionName + UNEXPECTED_TYPE_NULL, MODULE_NAME, JSON.stringify(condition), conditionName ); return null; } if (typeof userValue !== 'string') { logger.warn( - LOG_MESSAGES.UNEXPECTED_TYPE, MODULE_NAME, JSON.stringify(condition), userValueType, conditionName + UNEXPECTED_TYPE, MODULE_NAME, JSON.stringify(condition), userValueType, conditionName ); return null; } diff --git a/lib/core/decision_service/index.ts b/lib/core/decision_service/index.ts index 5522e3905..7c21034ad 100644 --- a/lib/core/decision_service/index.ts +++ b/lib/core/decision_service/index.ts @@ -22,9 +22,7 @@ import { AUDIENCE_EVALUATION_TYPES, CONTROL_ATTRIBUTES, DECISION_SOURCES, - ERROR_MESSAGES, LOG_LEVEL, - LOG_MESSAGES, } from '../../utils/enums'; import { getAudiencesById, @@ -54,6 +52,49 @@ import { UserProfileService, Variation, } from '../../shared_types'; +import { + IMPROPERLY_FORMATTED_EXPERIMENT, + INVALID_ROLLOUT_ID, + INVALID_USER_ID, + INVALID_VARIATION_KEY, + NO_VARIATION_FOR_EXPERIMENT_KEY, + USER_NOT_IN_FORCED_VARIATION, + USER_PROFILE_LOOKUP_ERROR, + USER_PROFILE_SAVE_ERROR, +} from '../../error_messages'; +import { + AUDIENCE_EVALUATION_RESULT_COMBINED, + BUCKETING_ID_NOT_STRING, + EVALUATING_AUDIENCES_COMBINED, + EXPERIMENT_NOT_RUNNING, + FEATURE_HAS_NO_EXPERIMENTS, + FORCED_BUCKETING_FAILED, + NO_ROLLOUT_EXISTS, + RETURNING_STORED_VARIATION, + ROLLOUT_HAS_NO_EXPERIMENTS, + SAVED_USER_VARIATION, + SAVED_VARIATION_NOT_FOUND, + USER_BUCKETED_INTO_TARGETING_RULE, + USER_DOESNT_MEET_CONDITIONS_FOR_TARGETING_RULE, + USER_FORCED_IN_VARIATION, + USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED, + USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED_BUT_INVALID, + USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED, + USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED_BUT_INVALID, + USER_HAS_FORCED_VARIATION, + USER_HAS_NO_FORCED_VARIATION, + USER_HAS_NO_FORCED_VARIATION_FOR_EXPERIMENT, + USER_HAS_NO_VARIATION, + USER_HAS_VARIATION, + USER_IN_ROLLOUT, + USER_MAPPED_TO_FORCED_VARIATION, + USER_MEETS_CONDITIONS_FOR_TARGETING_RULE, + USER_NOT_BUCKETED_INTO_TARGETING_RULE, + USER_NOT_IN_EXPERIMENT, + USER_NOT_IN_ROLLOUT, + VALID_BUCKETING_ID, + VARIATION_REMOVED_FOR_USER, +} from '../../log_messages'; export const MODULE_NAME = 'DECISION_SERVICE'; @@ -129,8 +170,8 @@ export class DecisionService { const decideReasons: (string | number)[][] = []; const experimentKey = experiment.key; if (!this.checkIfExperimentIsActive(configObj, experimentKey)) { - this.logger.log(LOG_LEVEL.INFO, LOG_MESSAGES.EXPERIMENT_NOT_RUNNING, MODULE_NAME, experimentKey); - decideReasons.push([LOG_MESSAGES.EXPERIMENT_NOT_RUNNING, MODULE_NAME, experimentKey]); + this.logger.log(LOG_LEVEL.INFO, EXPERIMENT_NOT_RUNNING, MODULE_NAME, experimentKey); + decideReasons.push([EXPERIMENT_NOT_RUNNING, MODULE_NAME, experimentKey]); return { result: null, reasons: decideReasons, @@ -163,14 +204,14 @@ export class DecisionService { if (variation) { this.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.RETURNING_STORED_VARIATION, + RETURNING_STORED_VARIATION, MODULE_NAME, variation.key, experimentKey, userId, ); decideReasons.push([ - LOG_MESSAGES.RETURNING_STORED_VARIATION, + RETURNING_STORED_VARIATION, MODULE_NAME, variation.key, experimentKey, @@ -195,13 +236,13 @@ export class DecisionService { if (!decisionifUserIsInAudience.result) { this.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.USER_NOT_IN_EXPERIMENT, + USER_NOT_IN_EXPERIMENT, MODULE_NAME, userId, experimentKey, ); decideReasons.push([ - LOG_MESSAGES.USER_NOT_IN_EXPERIMENT, + USER_NOT_IN_EXPERIMENT, MODULE_NAME, userId, experimentKey, @@ -222,13 +263,13 @@ export class DecisionService { if (!variation) { this.logger.log( LOG_LEVEL.DEBUG, - LOG_MESSAGES.USER_HAS_NO_VARIATION, + USER_HAS_NO_VARIATION, MODULE_NAME, userId, experimentKey, ); decideReasons.push([ - LOG_MESSAGES.USER_HAS_NO_VARIATION, + USER_HAS_NO_VARIATION, MODULE_NAME, userId, experimentKey, @@ -241,14 +282,14 @@ export class DecisionService { this.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.USER_HAS_VARIATION, + USER_HAS_VARIATION, MODULE_NAME, userId, variation.key, experimentKey, ); decideReasons.push([ - LOG_MESSAGES.USER_HAS_VARIATION, + USER_HAS_VARIATION, MODULE_NAME, userId, variation.key, @@ -342,13 +383,13 @@ export class DecisionService { if (experiment.variationKeyMap.hasOwnProperty(forcedVariationKey)) { this.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.USER_FORCED_IN_VARIATION, + USER_FORCED_IN_VARIATION, MODULE_NAME, userId, forcedVariationKey, ); decideReasons.push([ - LOG_MESSAGES.USER_FORCED_IN_VARIATION, + USER_FORCED_IN_VARIATION, MODULE_NAME, userId, forcedVariationKey, @@ -360,13 +401,13 @@ export class DecisionService { } else { this.logger.log( LOG_LEVEL.ERROR, - LOG_MESSAGES.FORCED_BUCKETING_FAILED, + FORCED_BUCKETING_FAILED, MODULE_NAME, forcedVariationKey, userId, ); decideReasons.push([ - LOG_MESSAGES.FORCED_BUCKETING_FAILED, + FORCED_BUCKETING_FAILED, MODULE_NAME, forcedVariationKey, userId, @@ -407,14 +448,14 @@ export class DecisionService { const audiencesById = getAudiencesById(configObj); this.logger.log( LOG_LEVEL.DEBUG, - LOG_MESSAGES.EVALUATING_AUDIENCES_COMBINED, + EVALUATING_AUDIENCES_COMBINED, MODULE_NAME, evaluationAttribute, loggingKey || experiment.key, JSON.stringify(experimentAudienceConditions), ); decideReasons.push([ - LOG_MESSAGES.EVALUATING_AUDIENCES_COMBINED, + EVALUATING_AUDIENCES_COMBINED, MODULE_NAME, evaluationAttribute, loggingKey || experiment.key, @@ -423,14 +464,14 @@ export class DecisionService { const result = this.audienceEvaluator.evaluate(experimentAudienceConditions, audiencesById, user); this.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.AUDIENCE_EVALUATION_RESULT_COMBINED, + AUDIENCE_EVALUATION_RESULT_COMBINED, MODULE_NAME, evaluationAttribute, loggingKey || experiment.key, result.toString().toUpperCase(), ); decideReasons.push([ - LOG_MESSAGES.AUDIENCE_EVALUATION_RESULT_COMBINED, + AUDIENCE_EVALUATION_RESULT_COMBINED, MODULE_NAME, evaluationAttribute, loggingKey || experiment.key, @@ -493,7 +534,7 @@ export class DecisionService { } else { this.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.SAVED_VARIATION_NOT_FOUND, + SAVED_VARIATION_NOT_FOUND, MODULE_NAME, userId, variationId, experiment.key, @@ -524,7 +565,7 @@ export class DecisionService { } catch (ex: any) { this.logger.log( LOG_LEVEL.ERROR, - ERROR_MESSAGES.USER_PROFILE_LOOKUP_ERROR, + USER_PROFILE_LOOKUP_ERROR, MODULE_NAME, userId, ex.message, @@ -574,12 +615,12 @@ export class DecisionService { this.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.SAVED_USER_VARIATION, + SAVED_USER_VARIATION, MODULE_NAME, userId, ); } catch (ex: any) { - this.logger.log(LOG_LEVEL.ERROR, ERROR_MESSAGES.USER_PROFILE_SAVE_ERROR, MODULE_NAME, userId, ex.message); + this.logger.log(LOG_LEVEL.ERROR, USER_PROFILE_SAVE_ERROR, MODULE_NAME, userId, ex.message); } } @@ -630,11 +671,11 @@ export class DecisionService { const userId = user.getUserId(); if (rolloutDecision.variation) { - this.logger.log(LOG_LEVEL.DEBUG, LOG_MESSAGES.USER_IN_ROLLOUT, MODULE_NAME, userId, feature.key); - decideReasons.push([LOG_MESSAGES.USER_IN_ROLLOUT, MODULE_NAME, userId, feature.key]); + this.logger.log(LOG_LEVEL.DEBUG, USER_IN_ROLLOUT, MODULE_NAME, userId, feature.key); + decideReasons.push([USER_IN_ROLLOUT, MODULE_NAME, userId, feature.key]); } else { - this.logger.log(LOG_LEVEL.DEBUG, LOG_MESSAGES.USER_NOT_IN_ROLLOUT, MODULE_NAME, userId, feature.key); - decideReasons.push([LOG_MESSAGES.USER_NOT_IN_ROLLOUT, MODULE_NAME, userId, feature.key]); + this.logger.log(LOG_LEVEL.DEBUG, USER_NOT_IN_ROLLOUT, MODULE_NAME, userId, feature.key); + decideReasons.push([USER_NOT_IN_ROLLOUT, MODULE_NAME, userId, feature.key]); } decisions.push({ @@ -718,8 +759,8 @@ export class DecisionService { } } } else { - this.logger.log(LOG_LEVEL.DEBUG, LOG_MESSAGES.FEATURE_HAS_NO_EXPERIMENTS, MODULE_NAME, feature.key); - decideReasons.push([LOG_MESSAGES.FEATURE_HAS_NO_EXPERIMENTS, MODULE_NAME, feature.key]); + this.logger.log(LOG_LEVEL.DEBUG, FEATURE_HAS_NO_EXPERIMENTS, MODULE_NAME, feature.key); + decideReasons.push([FEATURE_HAS_NO_EXPERIMENTS, MODULE_NAME, feature.key]); } variationForFeatureExperiment = { @@ -742,8 +783,8 @@ export class DecisionService { const decideReasons: (string | number)[][] = []; let decisionObj: DecisionObj; if (!feature.rolloutId) { - this.logger.log(LOG_LEVEL.DEBUG, LOG_MESSAGES.NO_ROLLOUT_EXISTS, MODULE_NAME, feature.key); - decideReasons.push([LOG_MESSAGES.NO_ROLLOUT_EXISTS, MODULE_NAME, feature.key]); + this.logger.log(LOG_LEVEL.DEBUG, NO_ROLLOUT_EXISTS, MODULE_NAME, feature.key); + decideReasons.push([NO_ROLLOUT_EXISTS, MODULE_NAME, feature.key]); decisionObj = { experiment: null, variation: null, @@ -760,12 +801,12 @@ export class DecisionService { if (!rollout) { this.logger.log( LOG_LEVEL.ERROR, - ERROR_MESSAGES.INVALID_ROLLOUT_ID, + INVALID_ROLLOUT_ID, MODULE_NAME, feature.rolloutId, feature.key, ); - decideReasons.push([ERROR_MESSAGES.INVALID_ROLLOUT_ID, MODULE_NAME, feature.rolloutId, feature.key]); + decideReasons.push([INVALID_ROLLOUT_ID, MODULE_NAME, feature.rolloutId, feature.key]); decisionObj = { experiment: null, variation: null, @@ -781,11 +822,11 @@ export class DecisionService { if (rolloutRules.length === 0) { this.logger.log( LOG_LEVEL.ERROR, - LOG_MESSAGES.ROLLOUT_HAS_NO_EXPERIMENTS, + ROLLOUT_HAS_NO_EXPERIMENTS, MODULE_NAME, feature.rolloutId, ); - decideReasons.push([LOG_MESSAGES.ROLLOUT_HAS_NO_EXPERIMENTS, MODULE_NAME, feature.rolloutId]); + decideReasons.push([ROLLOUT_HAS_NO_EXPERIMENTS, MODULE_NAME, feature.rolloutId]); decisionObj = { experiment: null, variation: null, @@ -851,9 +892,9 @@ export class DecisionService { ) { if (typeof attributes[CONTROL_ATTRIBUTES.BUCKETING_ID] === 'string') { bucketingId = String(attributes[CONTROL_ATTRIBUTES.BUCKETING_ID]); - this.logger.log(LOG_LEVEL.DEBUG, LOG_MESSAGES.VALID_BUCKETING_ID, MODULE_NAME, bucketingId); + this.logger.log(LOG_LEVEL.DEBUG, VALID_BUCKETING_ID, MODULE_NAME, bucketingId); } else { - this.logger.log(LOG_LEVEL.WARNING, LOG_MESSAGES.BUCKETING_ID_NOT_STRING, MODULE_NAME); + this.logger.log(LOG_LEVEL.WARNING, BUCKETING_ID_NOT_STRING, MODULE_NAME); } } @@ -887,14 +928,14 @@ export class DecisionService { if (ruleKey) { this.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED, + USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED, variationKey, flagKey, ruleKey, userId ); decideReasons.push([ - LOG_MESSAGES.USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED, + USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED, variationKey, flagKey, ruleKey, @@ -903,13 +944,13 @@ export class DecisionService { } else { this.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED, + USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED, variationKey, flagKey, userId ); decideReasons.push([ - LOG_MESSAGES.USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED, + USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED, variationKey, flagKey, userId @@ -919,13 +960,13 @@ export class DecisionService { if (ruleKey) { this.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED_BUT_INVALID, + USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED_BUT_INVALID, flagKey, ruleKey, userId ); decideReasons.push([ - LOG_MESSAGES.USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED_BUT_INVALID, + USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED_BUT_INVALID, flagKey, ruleKey, userId @@ -933,12 +974,12 @@ export class DecisionService { } else { this.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED_BUT_INVALID, + USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED_BUT_INVALID, flagKey, userId ); decideReasons.push([ - LOG_MESSAGES.USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED_BUT_INVALID, + USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED_BUT_INVALID, flagKey, userId ]) @@ -961,20 +1002,20 @@ export class DecisionService { */ removeForcedVariation(userId: string, experimentId: string, experimentKey: string): void { if (!userId) { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_USER_ID, MODULE_NAME)); + throw new Error(sprintf(INVALID_USER_ID, MODULE_NAME)); } if (this.forcedVariationMap.hasOwnProperty(userId)) { delete this.forcedVariationMap[userId][experimentId]; this.logger.log( LOG_LEVEL.DEBUG, - LOG_MESSAGES.VARIATION_REMOVED_FOR_USER, + VARIATION_REMOVED_FOR_USER, MODULE_NAME, experimentKey, userId, ); } else { - throw new Error(sprintf(ERROR_MESSAGES.USER_NOT_IN_FORCED_VARIATION, MODULE_NAME, userId)); + throw new Error(sprintf(USER_NOT_IN_FORCED_VARIATION, MODULE_NAME, userId)); } } @@ -995,7 +1036,7 @@ export class DecisionService { this.logger.log( LOG_LEVEL.DEBUG, - LOG_MESSAGES.USER_MAPPED_TO_FORCED_VARIATION, + USER_MAPPED_TO_FORCED_VARIATION, MODULE_NAME, variationId, experimentId, @@ -1021,7 +1062,7 @@ export class DecisionService { if (!experimentToVariationMap) { this.logger.log( LOG_LEVEL.DEBUG, - LOG_MESSAGES.USER_HAS_NO_FORCED_VARIATION, + USER_HAS_NO_FORCED_VARIATION, MODULE_NAME, userId, ); @@ -1041,12 +1082,12 @@ export class DecisionService { // catching improperly formatted experiments this.logger.log( LOG_LEVEL.ERROR, - ERROR_MESSAGES.IMPROPERLY_FORMATTED_EXPERIMENT, + IMPROPERLY_FORMATTED_EXPERIMENT, MODULE_NAME, experimentKey, ); decideReasons.push([ - ERROR_MESSAGES.IMPROPERLY_FORMATTED_EXPERIMENT, + IMPROPERLY_FORMATTED_EXPERIMENT, MODULE_NAME, experimentKey, ]); @@ -1071,7 +1112,7 @@ export class DecisionService { if (!variationId) { this.logger.log( LOG_LEVEL.DEBUG, - LOG_MESSAGES.USER_HAS_NO_FORCED_VARIATION_FOR_EXPERIMENT, + USER_HAS_NO_FORCED_VARIATION_FOR_EXPERIMENT, MODULE_NAME, experimentKey, userId, @@ -1086,14 +1127,14 @@ export class DecisionService { if (variationKey) { this.logger.log( LOG_LEVEL.DEBUG, - LOG_MESSAGES.USER_HAS_FORCED_VARIATION, + USER_HAS_FORCED_VARIATION, MODULE_NAME, variationKey, experimentKey, userId, ); decideReasons.push([ - LOG_MESSAGES.USER_HAS_FORCED_VARIATION, + USER_HAS_FORCED_VARIATION, MODULE_NAME, variationKey, experimentKey, @@ -1102,7 +1143,7 @@ export class DecisionService { } else { this.logger.log( LOG_LEVEL.DEBUG, - LOG_MESSAGES.USER_HAS_NO_FORCED_VARIATION_FOR_EXPERIMENT, + USER_HAS_NO_FORCED_VARIATION_FOR_EXPERIMENT, MODULE_NAME, experimentKey, userId, @@ -1130,7 +1171,7 @@ export class DecisionService { variationKey: string | null ): boolean { if (variationKey != null && !stringValidator.validate(variationKey)) { - this.logger.log(LOG_LEVEL.ERROR, ERROR_MESSAGES.INVALID_VARIATION_KEY, MODULE_NAME); + this.logger.log(LOG_LEVEL.ERROR, INVALID_VARIATION_KEY, MODULE_NAME); return false; } @@ -1143,7 +1184,7 @@ export class DecisionService { // catching improperly formatted experiments this.logger.log( LOG_LEVEL.ERROR, - ERROR_MESSAGES.IMPROPERLY_FORMATTED_EXPERIMENT, + IMPROPERLY_FORMATTED_EXPERIMENT, MODULE_NAME, experimentKey, ); @@ -1170,7 +1211,7 @@ export class DecisionService { if (!variationId) { this.logger.log( LOG_LEVEL.ERROR, - ERROR_MESSAGES.NO_VARIATION_FOR_EXPERIMENT_KEY, + NO_VARIATION_FOR_EXPERIMENT_KEY, MODULE_NAME, variationKey, experimentKey, @@ -1263,13 +1304,13 @@ export class DecisionService { if (decisionifUserIsInAudience.result) { this.logger.log( LOG_LEVEL.DEBUG, - LOG_MESSAGES.USER_MEETS_CONDITIONS_FOR_TARGETING_RULE, + USER_MEETS_CONDITIONS_FOR_TARGETING_RULE, MODULE_NAME, userId, loggingKey ); decideReasons.push([ - LOG_MESSAGES.USER_MEETS_CONDITIONS_FOR_TARGETING_RULE, + USER_MEETS_CONDITIONS_FOR_TARGETING_RULE, MODULE_NAME, userId, loggingKey @@ -1285,13 +1326,13 @@ export class DecisionService { if (bucketedVariation) { this.logger.log( LOG_LEVEL.DEBUG, - LOG_MESSAGES.USER_BUCKETED_INTO_TARGETING_RULE, + USER_BUCKETED_INTO_TARGETING_RULE, MODULE_NAME, userId, loggingKey ); decideReasons.push([ - LOG_MESSAGES.USER_BUCKETED_INTO_TARGETING_RULE, + USER_BUCKETED_INTO_TARGETING_RULE, MODULE_NAME, userId, loggingKey]); @@ -1299,13 +1340,13 @@ export class DecisionService { // skip this logging for EveryoneElse since this has a message not for EveryoneElse this.logger.log( LOG_LEVEL.DEBUG, - LOG_MESSAGES.USER_NOT_BUCKETED_INTO_TARGETING_RULE, + USER_NOT_BUCKETED_INTO_TARGETING_RULE, MODULE_NAME, userId, loggingKey ); decideReasons.push([ - LOG_MESSAGES.USER_NOT_BUCKETED_INTO_TARGETING_RULE, + USER_NOT_BUCKETED_INTO_TARGETING_RULE, MODULE_NAME, userId, loggingKey @@ -1317,13 +1358,13 @@ export class DecisionService { } else { this.logger.log( LOG_LEVEL.DEBUG, - LOG_MESSAGES.USER_DOESNT_MEET_CONDITIONS_FOR_TARGETING_RULE, + USER_DOESNT_MEET_CONDITIONS_FOR_TARGETING_RULE, MODULE_NAME, userId, loggingKey ); decideReasons.push([ - LOG_MESSAGES.USER_DOESNT_MEET_CONDITIONS_FOR_TARGETING_RULE, + USER_DOESNT_MEET_CONDITIONS_FOR_TARGETING_RULE, MODULE_NAME, userId, loggingKey diff --git a/lib/error_messages.ts b/lib/error_messages.ts new file mode 100644 index 000000000..18d85ac13 --- /dev/null +++ b/lib/error_messages.ts @@ -0,0 +1,107 @@ +/** + * Copyright 2024, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export const BROWSER_ODP_MANAGER_INITIALIZATION_FAILED = '%s: Error initializing Browser ODP Manager.'; +export const CONDITION_EVALUATOR_ERROR = '%s: Error evaluating audience condition of type %s: %s'; +export const DATAFILE_AND_SDK_KEY_MISSING = + '%s: You must provide at least one of sdkKey or datafile. Cannot start Optimizely'; +export const EXPERIMENT_KEY_NOT_IN_DATAFILE = '%s: Experiment key %s is not in datafile.'; +export const FEATURE_NOT_IN_DATAFILE = '%s: Feature key %s is not in datafile.'; +export const FETCH_SEGMENTS_FAILED_NETWORK_ERROR = '%s: Audience segments fetch failed. (network error)'; +export const FETCH_SEGMENTS_FAILED_DECODE_ERROR = '%s: Audience segments fetch failed. (decode error)'; +export const IMPROPERLY_FORMATTED_EXPERIMENT = '%s: Experiment key %s is improperly formatted.'; +export const INVALID_ATTRIBUTES = '%s: Provided attributes are in an invalid format.'; +export const INVALID_BUCKETING_ID = '%s: Unable to generate hash for bucketing ID %s: %s'; +export const INVALID_DATAFILE = '%s: Datafile is invalid - property %s: %s'; +export const INVALID_DATAFILE_MALFORMED = '%s: Datafile is invalid because it is malformed.'; +export const INVALID_CONFIG = '%s: Provided Optimizely config is in an invalid format.'; +export const INVALID_JSON = '%s: JSON object is not valid.'; +export const INVALID_ERROR_HANDLER = '%s: Provided "errorHandler" is in an invalid format.'; +export const INVALID_EVENT_DISPATCHER = '%s: Provided "eventDispatcher" is in an invalid format.'; +export const INVALID_EVENT_TAGS = '%s: Provided event tags are in an invalid format.'; +export const INVALID_EXPERIMENT_KEY = + '%s: Experiment key %s is not in datafile. It is either invalid, paused, or archived.'; +export const INVALID_EXPERIMENT_ID = '%s: Experiment ID %s is not in datafile.'; +export const INVALID_GROUP_ID = '%s: Group ID %s is not in datafile.'; +export const INVALID_LOGGER = '%s: Provided "logger" is in an invalid format.'; +export const INVALID_ROLLOUT_ID = '%s: Invalid rollout ID %s attached to feature %s'; +export const INVALID_USER_ID = '%s: Provided user ID is in an invalid format.'; +export const INVALID_USER_PROFILE_SERVICE = '%s: Provided user profile service instance is in an invalid format: %s.'; +export const LOCAL_STORAGE_DOES_NOT_EXIST = 'Error accessing window localStorage.'; +export const MISSING_INTEGRATION_KEY = + '%s: Integration key missing from datafile. All integrations should include a key.'; +export const NO_DATAFILE_SPECIFIED = '%s: No datafile specified. Cannot start optimizely.'; +export const NO_JSON_PROVIDED = '%s: No JSON object to validate against schema.'; +export const NO_EVENT_PROCESSOR = 'No event processor is provided'; +export const NO_VARIATION_FOR_EXPERIMENT_KEY = '%s: No variation key %s defined in datafile for experiment %s.'; +export const ODP_CONFIG_NOT_AVAILABLE = '%s: ODP is not integrated to the project.'; +export const ODP_EVENT_FAILED = 'ODP event send failed.'; +export const ODP_EVENT_MANAGER_IS_NOT_RUNNING = 'ODP event manager is not running.'; +export const ODP_EVENTS_SHOULD_HAVE_ATLEAST_ONE_KEY_VALUE = 'ODP events should have at least one key-value pair in identifiers.'; +export const ODP_FETCH_QUALIFIED_SEGMENTS_SEGMENTS_MANAGER_MISSING = + '%s: ODP unable to fetch qualified segments (Segments Manager not initialized).'; +export const ODP_IDENTIFY_FAILED_EVENT_MANAGER_MISSING = + '%s: ODP identify event %s is not dispatched (Event Manager not instantiated).'; +export const ODP_INITIALIZATION_FAILED = '%s: ODP failed to initialize.'; +export const ODP_INVALID_DATA = '%s: ODP data is not valid'; +export const ODP_EVENT_FAILED_ODP_MANAGER_MISSING = '%s: ODP Event failed to send. (ODP Manager not initialized).'; +export const ODP_FETCH_QUALIFIED_SEGMENTS_FAILED_ODP_MANAGER_MISSING = + '%s: ODP failed to Fetch Qualified Segments. (ODP Manager not initialized).'; +export const ODP_IDENTIFY_USER_FAILED_ODP_MANAGER_MISSING = + '%s: ODP failed to Identify User. (ODP Manager not initialized).'; +export const ODP_IDENTIFY_USER_FAILED_USER_CONTEXT_INITIALIZATION = + '%s: ODP failed to Identify User. (Failed during User Context Initialization).'; +export const ODP_MANAGER_UPDATE_SETTINGS_FAILED_EVENT_MANAGER_MISSING = + '%s: ODP Manager failed to update OdpConfig settings for internal event manager. (Event Manager not initialized).'; +export const ODP_MANAGER_UPDATE_SETTINGS_FAILED_SEGMENTS_MANAGER_MISSING = + '%s: ODP Manager failed to update OdpConfig settings for internal segments manager. (Segments Manager not initialized).'; +export const ODP_NOT_ENABLED = 'ODP is not enabled'; +export const ODP_NOT_INTEGRATED = '%s: ODP is not integrated'; +export const ODP_SEND_EVENT_FAILED_EVENT_MANAGER_MISSING = + '%s: ODP send event %s was not dispatched (Event Manager not instantiated).'; +export const ODP_SEND_EVENT_FAILED_UID_MISSING = + '%s: ODP send event %s was not dispatched (No valid user identifier provided).'; +export const ODP_SEND_EVENT_FAILED_VUID_MISSING = '%s: ODP send event %s was not dispatched (Unable to fetch VUID).'; +export const ODP_VUID_INITIALIZATION_FAILED = '%s: ODP VUID initialization failed.'; +export const ODP_VUID_REGISTRATION_FAILED = '%s: ODP VUID failed to be registered.'; +export const ODP_VUID_REGISTRATION_FAILED_EVENT_MANAGER_MISSING = + '%s: ODP register vuid failed. (Event Manager not instantiated).'; +export const UNDEFINED_ATTRIBUTE = '%s: Provided attribute: %s has an undefined value.'; +export const UNRECOGNIZED_ATTRIBUTE = + '%s: Unrecognized attribute %s provided. Pruning before sending event to Optimizely.'; +export const UNABLE_TO_CAST_VALUE = '%s: Unable to cast value %s to type %s, returning null.'; +export const USER_NOT_IN_FORCED_VARIATION = + '%s: User %s is not in the forced variation map. Cannot remove their forced variation.'; +export const USER_PROFILE_LOOKUP_ERROR = '%s: Error while looking up user profile for user ID "%s": %s.'; +export const USER_PROFILE_SAVE_ERROR = '%s: Error while saving user profile for user ID "%s": %s.'; +export const VARIABLE_KEY_NOT_IN_DATAFILE = + '%s: Variable with key "%s" associated with feature with key "%s" is not in datafile.'; +export const VARIATION_ID_NOT_IN_DATAFILE = '%s: No variation ID %s defined in datafile for experiment %s.'; +export const VARIATION_ID_NOT_IN_DATAFILE_NO_EXPERIMENT = '%s: Variation ID %s is not in the datafile.'; +export const INVALID_INPUT_FORMAT = '%s: Provided %s is in an invalid format.'; +export const INVALID_DATAFILE_VERSION = + '%s: This version of the JavaScript SDK does not support the given datafile version: %s'; +export const INVALID_VARIATION_KEY = '%s: Provided variation key is in an invalid format.'; +export const UNABLE_TO_GET_VUID = 'Unable to get VUID - ODP Manager is not instantiated yet.'; +export const ERROR_FETCHING_DATAFILE = 'Error fetching datafile: %s'; +export const DATAFILE_FETCH_REQUEST_FAILED = 'Datafile fetch request failed with status: %s'; +export const EVENT_DATA_FOUND_TO_BE_INVALID = 'Event data found to be invalid.'; +export const EVENT_ACTION_INVALID = 'Event action invalid.'; +export const FAILED_TO_SEND_ODP_EVENTS = 'failed to send odp events'; +export const UNABLE_TO_GET_VUID_VUID_MANAGER_NOT_AVAILABLE = 'Unable to get VUID - VuidManager is not available' +export const UNKNOWN_CONDITION_TYPE = + '%s: Audience condition %s has an unknown condition type. You may need to upgrade to a newer release of the Optimizely SDK.'; +export const UNKNOWN_MATCH_TYPE = + '%s: Audience condition %s uses an unknown match type. You may need to upgrade to a newer release of the Optimizely SDK.'; diff --git a/lib/event_processor/batch_event_processor.ts b/lib/event_processor/batch_event_processor.ts index f37708521..76e737a9d 100644 --- a/lib/event_processor/batch_event_processor.ts +++ b/lib/event_processor/batch_event_processor.ts @@ -27,6 +27,8 @@ import { isSuccessStatusCode } from "../utils/http_request_handler/http_util"; import { EventEmitter } from "../utils/event_emitter/event_emitter"; import { IdGenerator } from "../utils/id_generator"; import { areEventContextsEqual } from "./event_builder/user_event"; +import { EVENT_PROCESSOR_STOPPED, FAILED_TO_DISPATCH_EVENTS, FAILED_TO_DISPATCH_EVENTS_WITH_ARG } from "../exception_messages"; +import { sprintf } from "../utils/fns"; export type EventWithId = { id: string; @@ -160,7 +162,7 @@ export class BatchEventProcessor extends BaseService implements EventProcessor { const dispatcher = closing && this.closingEventDispatcher ? this.closingEventDispatcher : this.eventDispatcher; return dispatcher.dispatchEvent(request).then((res) => { if (res.statusCode && !isSuccessStatusCode(res.statusCode)) { - return Promise.reject(new Error(`Failed to dispatch events: ${res.statusCode}`)); + return Promise.reject(new Error(sprintf(FAILED_TO_DISPATCH_EVENTS_WITH_ARG, res.statusCode))); } return Promise.resolve(res); }); @@ -195,7 +197,7 @@ export class BatchEventProcessor extends BaseService implements EventProcessor { }).catch((err) => { // if the dispatch fails, the events will still be // in the store for future processing - this.logger?.error('Failed to dispatch events', err); + this.logger?.error(FAILED_TO_DISPATCH_EVENTS, err); }).finally(() => { this.runningTask.delete(taskId); ids.forEach((id) => this.dispatchingEventIds.delete(id)); @@ -253,7 +255,7 @@ export class BatchEventProcessor extends BaseService implements EventProcessor { if (this.isNew()) { // TOOD: replace message with imported constants - this.startPromise.reject(new Error('Event processor stopped before it could be started')); + this.startPromise.reject(new Error(EVENT_PROCESSOR_STOPPED)); } this.state = ServiceState.Stopping; diff --git a/lib/event_processor/event_dispatcher/default_dispatcher.ts b/lib/event_processor/event_dispatcher/default_dispatcher.ts index b8c73833c..21c42bc5e 100644 --- a/lib/event_processor/event_dispatcher/default_dispatcher.ts +++ b/lib/event_processor/event_dispatcher/default_dispatcher.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { ONLY_POST_REQUESTS_ARE_SUPPORTED } from '../../exception_messages'; import { RequestHandler } from '../../utils/http_request_handler/http'; import { EventDispatcher, EventDispatcherResponse, LogEvent } from './event_dispatcher'; @@ -28,7 +29,7 @@ export class DefaultEventDispatcher implements EventDispatcher { ): Promise { // Non-POST requests not supported if (eventObj.httpVerb !== 'POST') { - return Promise.reject(new Error('Only POST requests are supported')); + return Promise.reject(new Error(ONLY_POST_REQUESTS_ARE_SUPPORTED)); } const dataString = JSON.stringify(eventObj.params); diff --git a/lib/event_processor/event_dispatcher/send_beacon_dispatcher.browser.ts b/lib/event_processor/event_dispatcher/send_beacon_dispatcher.browser.ts index a2686b316..605bae2ef 100644 --- a/lib/event_processor/event_dispatcher/send_beacon_dispatcher.browser.ts +++ b/lib/event_processor/event_dispatcher/send_beacon_dispatcher.browser.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { SEND_BEACON_FAILED } from '../../exception_messages'; import { EventDispatcher, EventDispatcherResponse } from './event_dispatcher'; export type Event = { @@ -41,7 +42,7 @@ export const dispatchEvent = function( if(success) { return Promise.resolve({}); } - return Promise.reject(new Error('sendBeacon failed')); + return Promise.reject(new Error(SEND_BEACON_FAILED)); } const eventDispatcher : EventDispatcher = { diff --git a/lib/event_processor/event_processor_factory.react_native.spec.ts b/lib/event_processor/event_processor_factory.react_native.spec.ts index 18d066366..30e300dc9 100644 --- a/lib/event_processor/event_processor_factory.react_native.spec.ts +++ b/lib/event_processor/event_processor_factory.react_native.spec.ts @@ -60,11 +60,11 @@ async function mockRequireNetInfo() { M._load = (uri: string, parent: string) => { if (uri === '@react-native-community/netinfo') { if (isNetInfoAvailable) return {}; - throw new Error('Module not found: @react-native-community/netinfo'); + throw new Error("Module not found: @react-native-community/netinfo"); } if (uri === '@react-native-async-storage/async-storage') { if (isAsyncStorageAvailable) return {}; - throw new Error('Module not found: @react-native-async-storage/async-storage'); + throw new Error("Module not found: @react-native-async-storage/async-storage"); } return M._load_original(uri, parent); @@ -80,6 +80,7 @@ import { AsyncCache, AsyncPrefixCache, SyncCache, SyncPrefixCache } from '../uti import { AsyncStorageCache } from '../utils/cache/async_storage_cache.react_native'; import { ReactNativeNetInfoEventProcessor } from './batch_event_processor.react_native'; import { BatchEventProcessor } from './batch_event_processor'; +import { MODULE_NOT_FOUND_REACT_NATIVE_ASYNC_STORAGE } from '../utils/import.react_native/@react-native-async-storage/async-storage'; describe('createForwardingEventProcessor', () => { const mockGetForwardingEventProcessor = vi.mocked(getForwardingEventProcessor); @@ -163,7 +164,7 @@ describe('createBatchEventProcessor', () => { }); expect(() => createBatchEventProcessor({})).toThrowError( - 'Module not found: @react-native-async-storage/async-storage' + MODULE_NOT_FOUND_REACT_NATIVE_ASYNC_STORAGE ); isAsyncStorageAvailable = true; diff --git a/lib/event_processor/forwarding_event_processor.ts b/lib/event_processor/forwarding_event_processor.ts index 768c10e87..dbbe7076c 100644 --- a/lib/event_processor/forwarding_event_processor.ts +++ b/lib/event_processor/forwarding_event_processor.ts @@ -23,6 +23,7 @@ import { buildLogEvent } from './event_builder/log_event'; import { BaseService, ServiceState } from '../service'; import { EventEmitter } from '../utils/event_emitter/event_emitter'; import { Consumer, Fn } from '../utils/type'; +import { SERVICE_STOPPED_BEFORE_IT_WAS_STARTED } from '../exception_messages'; class ForwardingEventProcessor extends BaseService implements EventProcessor { private dispatcher: EventDispatcher; private eventEmitter: EventEmitter<{ dispatch: LogEvent }>; @@ -54,7 +55,7 @@ class ForwardingEventProcessor extends BaseService implements EventProcessor { } if (this.isNew()) { - this.startPromise.reject(new Error('Service stopped before it was started')); + this.startPromise.reject(new Error(SERVICE_STOPPED_BEFORE_IT_WAS_STARTED)); } this.state = ServiceState.Terminated; diff --git a/lib/exception_messages.ts b/lib/exception_messages.ts new file mode 100644 index 000000000..f17fa2821 --- /dev/null +++ b/lib/exception_messages.ts @@ -0,0 +1,43 @@ +/** + * Copyright 2024, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const FAILED_TO_DISPATCH_EVENTS = 'Failed to dispatch events' +export const FAILED_TO_DISPATCH_EVENTS_WITH_ARG = 'Failed to dispatch events: %s'; +export const EVENT_PROCESSOR_STOPPED = 'Event processor stopped before it could be started'; +export const SERVICE_STOPPED_BEFORE_IT_WAS_STARTED = 'Service stopped before it was started'; +export const ONLY_POST_REQUESTS_ARE_SUPPORTED = 'Only POST requests are supported'; +export const SEND_BEACON_FAILED = 'sendBeacon failed'; +export const CANNOT_START_WITHOUT_ODP_CONFIG = 'cannot start without ODP config'; +export const START_CALLED_WHEN_ODP_IS_NOT_INTEGRATED = 'start() called when ODP is not integrated'; +export const ODP_ACTION_IS_NOT_VALID = 'ODP action is not valid (cannot be empty).'; +export const ODP_MANAGER_STOPPED_BEFORE_RUNNING = 'odp manager stopped before running'; +export const ODP_EVENT_MANAGER_STOPPED = "ODP event manager stopped before it could start"; +export const ONREADY_TIMEOUT_EXPIRED = 'onReady timeout expired after %s ms'; +export const INSTANCE_CLOSED = 'Instance closed'; +export const DATAFILE_MANAGER_STOPPED = 'Datafile manager stopped before it could be started'; +export const DATAFILE_MANAGER_FAILED_TO_START = 'Datafile manager failed to start'; +export const FAILED_TO_FETCH_DATAFILE = 'Failed to fetch datafile'; +export const FAILED_TO_STOP = 'Failed to stop'; +export const YOU_MUST_PROVIDE_DATAFILE_IN_SSR = 'You must provide datafile in SSR'; +export const YOU_MUST_PROVIDE_AT_LEAST_ONE_OF_SDKKEY_OR_DATAFILE = 'You must provide at least one of sdkKey or datafile'; +export const RETRY_CANCELLED = 'Retry cancelled'; +export const REQUEST_TIMEOUT = 'Request timeout'; +export const REQUEST_ERROR = 'Request error'; +export const REQUEST_FAILED = 'Request failed'; +export const UNSUPPORTED_PROTOCOL = 'Unsupported protocol: %s'; +export const NO_STATUS_CODE_IN_RESPONSE = 'No status code in response'; +export const PROMISE_SHOULD_NOT_HAVE_RESOLVED = 'Promise should not have resolved'; +export const VUID_IS_NOT_SUPPORTED_IN_NODEJS= 'VUID is not supported in Node.js environment'; diff --git a/lib/index.browser.tests.js b/lib/index.browser.tests.js index 0a7859353..b7bd5d0df 100644 --- a/lib/index.browser.tests.js +++ b/lib/index.browser.tests.js @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - import logging, { getLogger } from './modules/logging/logger'; import { assert } from 'chai'; @@ -25,6 +24,7 @@ import optimizelyFactory from './index.browser'; import configValidator from './utils/config_validator'; import { getMockProjectConfigManager } from './tests/mock/mock_project_config_manager'; import { createProjectConfig } from './project_config/project_config'; +import { INVALID_CONFIG_OR_SOMETHING } from './exception_messages'; class MockLocalStorage { @@ -55,7 +55,7 @@ if (!global.window) { localStorage: new MockLocalStorage(), }; } catch (e) { - console.error('Unable to overwrite global.window.'); + console.error("Unable to overwrite global.window"); } } @@ -154,7 +154,7 @@ describe('javascript-sdk (Browser)', function() { // }); it('should not throw if the provided config is not valid', function() { - configValidator.validate.throws(new Error('Invalid config or something')); + configValidator.validate.throws(new Error(INVALID_CONFIG_OR_SOMETHING)); assert.doesNotThrow(function() { var optlyInstance = optimizelyFactory.createInstance({ projectConfigManager: getMockProjectConfigManager(), diff --git a/lib/index.browser.ts b/lib/index.browser.ts index 7317540db..681c281c7 100644 --- a/lib/index.browser.ts +++ b/lib/index.browser.ts @@ -33,7 +33,7 @@ import { createPollingProjectConfigManager } from './project_config/config_manag import { createBatchEventProcessor, createForwardingEventProcessor } from './event_processor/event_processor_factory.browser'; import { createVuidManager } from './vuid/vuid_manager_factory.browser'; import { createOdpManager } from './odp/odp_manager_factory.browser'; - +import { ODP_DISABLED, UNABLE_TO_ATTACH_UNLOAD } from './log_messages'; const logger = getLogger(); logHelper.setLogHandler(loggerPlugin.createLogger()); @@ -107,7 +107,7 @@ const createInstance = function(config: Config): Client | null { } // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (e) { - logger.error(enums.LOG_MESSAGES.UNABLE_TO_ATTACH_UNLOAD, MODULE_NAME, e.message); + logger.error(UNABLE_TO_ATTACH_UNLOAD, MODULE_NAME, e.message); } return optimizely; diff --git a/lib/index.browser.umdtests.js b/lib/index.browser.umdtests.js index f8be89aca..a13f5046b 100644 --- a/lib/index.browser.umdtests.js +++ b/lib/index.browser.umdtests.js @@ -23,6 +23,7 @@ import Optimizely from './optimizely'; import testData from './tests/test_data'; import packageJSON from '../package.json'; import eventDispatcher from './plugins/event_dispatcher/index.browser'; +import { INVALID_CONFIG_OR_SOMETHING } from './exception_messages'; describe('javascript-sdk', function() { describe('APIs', function() { @@ -92,7 +93,7 @@ describe('javascript-sdk', function() { }); it('should not throw if the provided config is not valid', function() { - configValidator.validate.throws(new Error('Invalid config or something')); + configValidator.validate.throws(new Error(INVALID_CONFIG_OR_SOMETHING)); assert.doesNotThrow(function() { var optlyInstance = window.optimizelySdk.createInstance({ datafile: {}, diff --git a/lib/index.lite.tests.js b/lib/index.lite.tests.js index 076934eda..729af3b19 100644 --- a/lib/index.lite.tests.js +++ b/lib/index.lite.tests.js @@ -22,6 +22,7 @@ import * as loggerPlugin from './plugins/logger'; import optimizelyFactory from './index.lite'; import configValidator from './utils/config_validator'; import { getMockProjectConfigManager } from './tests/mock/mock_project_config_manager'; +import { INVALID_CONFIG_OR_SOMETHING } from './exception_messages'; describe('optimizelyFactory', function() { describe('APIs', function() { @@ -52,7 +53,7 @@ describe('optimizelyFactory', function() { }); it('should not throw if the provided config is not valid and log an error if logger is passed in', function() { - configValidator.validate.throws(new Error('Invalid config or something')); + configValidator.validate.throws(new Error(INVALID_CONFIG_OR_SOMETHING)); var localLogger = loggerPlugin.createLogger({ logLevel: enums.LOG_LEVEL.INFO }); assert.doesNotThrow(function() { var optlyInstance = optimizelyFactory.createInstance({ diff --git a/lib/index.node.tests.js b/lib/index.node.tests.js index 3495b036b..ee4cf1766 100644 --- a/lib/index.node.tests.js +++ b/lib/index.node.tests.js @@ -23,6 +23,7 @@ import * as loggerPlugin from './plugins/logger'; import optimizelyFactory from './index.node'; import configValidator from './utils/config_validator'; import { getMockProjectConfigManager } from './tests/mock/mock_project_config_manager'; +import { INVALID_CONFIG_OR_SOMETHING } from './exception_messages'; describe('optimizelyFactory', function() { describe('APIs', function() { @@ -66,7 +67,7 @@ describe('optimizelyFactory', function() { // }); it('should not throw if the provided config is not valid and log an error if no logger is provided', function() { - configValidator.validate.throws(new Error('Invalid config or something')); + configValidator.validate.throws(new Error(INVALID_CONFIG_OR_SOMETHING)); assert.doesNotThrow(function() { var optlyInstance = optimizelyFactory.createInstance({ projectConfigManager: getMockProjectConfigManager(), diff --git a/lib/index.node.ts b/lib/index.node.ts index 16605d246..156b06adf 100644 --- a/lib/index.node.ts +++ b/lib/index.node.ts @@ -28,6 +28,7 @@ import { createPollingProjectConfigManager } from './project_config/config_manag import { createForwardingEventProcessor, createBatchEventProcessor } from './event_processor/event_processor_factory.node'; import { createVuidManager } from './vuid/vuid_manager_factory.node'; import { createOdpManager } from './odp/odp_manager_factory.node'; +import { ODP_DISABLED } from './log_messages'; const logger = getLogger(); setLogLevel(LogLevel.ERROR); diff --git a/lib/index.react_native.ts b/lib/index.react_native.ts index 8cedf06d5..565ad0605 100644 --- a/lib/index.react_native.ts +++ b/lib/index.react_native.ts @@ -31,6 +31,7 @@ import { createVuidManager } from './vuid/vuid_manager_factory.react_native'; import 'fast-text-encoding'; import 'react-native-get-random-values'; +import { ODP_DISABLED } from './log_messages'; const logger = getLogger(); setLogHandler(loggerPlugin.createLogger()); diff --git a/lib/log_messages.ts b/lib/log_messages.ts new file mode 100644 index 000000000..4c2ab6e40 --- /dev/null +++ b/lib/log_messages.ts @@ -0,0 +1,122 @@ +/** + * Copyright 2024, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const ACTIVATE_USER = '%s: Activating user %s in experiment %s.'; +export const DISPATCH_CONVERSION_EVENT = '%s: Dispatching conversion event to URL %s with params %s.'; +export const DISPATCH_IMPRESSION_EVENT = '%s: Dispatching impression event to URL %s with params %s.'; +export const DEPRECATED_EVENT_VALUE = '%s: Event value is deprecated in %s call.'; +export const EVENT_KEY_NOT_FOUND = '%s: Event key %s is not in datafile.'; +export const EXPERIMENT_NOT_RUNNING = '%s: Experiment %s is not running.'; +export const FEATURE_ENABLED_FOR_USER = '%s: Feature %s is enabled for user %s.'; +export const FEATURE_NOT_ENABLED_FOR_USER = '%s: Feature %s is not enabled for user %s.'; +export const FEATURE_HAS_NO_EXPERIMENTS = '%s: Feature %s is not attached to any experiments.'; +export const FAILED_TO_PARSE_VALUE = '%s: Failed to parse event value "%s" from event tags.'; +export const FAILED_TO_PARSE_REVENUE = '%s: Failed to parse revenue value "%s" from event tags.'; +export const FORCED_BUCKETING_FAILED = '%s: Variation key %s is not in datafile. Not activating user %s.'; +export const INVALID_OBJECT = '%s: Optimizely object is not valid. Failing %s.'; +export const INVALID_CLIENT_ENGINE = '%s: Invalid client engine passed: %s. Defaulting to node-sdk.'; +export const INVALID_DEFAULT_DECIDE_OPTIONS = '%s: Provided default decide options is not an array.'; +export const INVALID_DECIDE_OPTIONS = '%s: Provided decide options is not an array. Using default decide options.'; +export const NOTIFICATION_LISTENER_EXCEPTION = '%s: Notification listener for (%s) threw exception: %s'; +export const NO_ROLLOUT_EXISTS = '%s: There is no rollout of feature %s.'; +export const NOT_ACTIVATING_USER = '%s: Not activating user %s for experiment %s.'; +export const NOT_TRACKING_USER = '% s: Not tracking user %s.'; +export const ODP_DISABLED = 'ODP Disabled.'; +export const ODP_IDENTIFY_FAILED_ODP_DISABLED = '%s: ODP identify event for user %s is not dispatched (ODP disabled).'; +export const ODP_IDENTIFY_FAILED_ODP_NOT_INTEGRATED = + '%s: ODP identify event %s is not dispatched (ODP not integrated).'; +export const ODP_SEND_EVENT_IDENTIFIER_CONVERSION_FAILED = + '%s: sendOdpEvent failed to parse through and convert fs_user_id aliases'; +export const PARSED_REVENUE_VALUE = '%s: Parsed revenue value "%s" from event tags.'; +export const PARSED_NUMERIC_VALUE = '%s: Parsed event value "%s" from event tags.'; +export const RETURNING_STORED_VARIATION = + '%s: Returning previously activated variation "%s" of experiment "%s" for user "%s" from user profile.'; +export const ROLLOUT_HAS_NO_EXPERIMENTS = '%s: Rollout of feature %s has no experiments'; +export const SAVED_USER_VARIATION = '%s: Saved user profile for user "%s".'; +export const UPDATED_USER_VARIATION = '%s: Updated variation "%s" of experiment "%s" for user "%s".'; +export const SAVED_VARIATION_NOT_FOUND = + '%s: User %s was previously bucketed into variation with ID %s for experiment %s, but no matching variation was found.'; +export const SHOULD_NOT_DISPATCH_ACTIVATE = '%s: Experiment %s is not in "Running" state. Not activating user.'; +export const SKIPPING_JSON_VALIDATION = '%s: Skipping JSON schema validation.'; +export const TRACK_EVENT = '%s: Tracking event %s for user %s.'; +export const UNRECOGNIZED_DECIDE_OPTION = '%s: Unrecognized decide option %s provided.'; +export const USER_BUCKETED_INTO_TARGETING_RULE = '%s: User %s bucketed into targeting rule %s.'; +export const USER_IN_FEATURE_EXPERIMENT = '%s: User %s is in variation %s of experiment %s on the feature %s.'; +export const USER_IN_ROLLOUT = '%s: User %s is in rollout of feature %s.'; +export const USER_NOT_BUCKETED_INTO_EVERYONE_TARGETING_RULE = + '%s: User %s not bucketed into everyone targeting rule due to traffic allocation.'; +export const USER_NOT_BUCKETED_INTO_ANY_EXPERIMENT_IN_GROUP = '%s: User %s is not in any experiment of group %s.'; +export const USER_NOT_BUCKETED_INTO_TARGETING_RULE = + '%s User %s not bucketed into targeting rule %s due to traffic allocation. Trying everyone rule.'; +export const USER_FORCED_IN_VARIATION = '%s: User %s is forced in variation %s.'; +export const USER_MAPPED_TO_FORCED_VARIATION = + '%s: Set variation %s for experiment %s and user %s in the forced variation map.'; +export const USER_DOESNT_MEET_CONDITIONS_FOR_TARGETING_RULE = + '%s: User %s does not meet conditions for targeting rule %s.'; +export const USER_MEETS_CONDITIONS_FOR_TARGETING_RULE = '%s: User %s meets conditions for targeting rule %s.'; +export const USER_HAS_VARIATION = '%s: User %s is in variation %s of experiment %s.'; +export const USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED = + 'Variation (%s) is mapped to flag (%s), rule (%s) and user (%s) in the forced decision map.'; +export const USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED = + 'Variation (%s) is mapped to flag (%s) and user (%s) in the forced decision map.'; +export const USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED_BUT_INVALID = + 'Invalid variation is mapped to flag (%s), rule (%s) and user (%s) in the forced decision map.'; +export const USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED_BUT_INVALID = + 'Invalid variation is mapped to flag (%s) and user (%s) in the forced decision map.'; +export const USER_HAS_FORCED_VARIATION = + '%s: Variation %s is mapped to experiment %s and user %s in the forced variation map.'; +export const USER_HAS_NO_VARIATION = '%s: User %s is in no variation of experiment %s.'; +export const USER_HAS_NO_FORCED_VARIATION = '%s: User %s is not in the forced variation map.'; +export const USER_HAS_NO_FORCED_VARIATION_FOR_EXPERIMENT = + '%s: No experiment %s mapped to user %s in the forced variation map.'; +export const USER_NOT_IN_EXPERIMENT = '%s: User %s does not meet conditions to be in experiment %s.'; +export const USER_NOT_IN_ROLLOUT = '%s: User %s is not in rollout of feature %s.'; +export const USER_RECEIVED_DEFAULT_VARIABLE_VALUE = + '%s: User "%s" is not in any variation or rollout rule. Returning default value for variable "%s" of feature flag "%s".'; +export const FEATURE_NOT_ENABLED_RETURN_DEFAULT_VARIABLE_VALUE = + '%s: Feature "%s" is not enabled for user %s. Returning the default variable value "%s".'; +export const VARIABLE_NOT_USED_RETURN_DEFAULT_VARIABLE_VALUE = + '%s: Variable "%s" is not used in variation "%s". Returning default value.'; +export const USER_RECEIVED_VARIABLE_VALUE = '%s: Got variable value "%s" for variable "%s" of feature flag "%s"'; +export const VALID_DATAFILE = '%s: Datafile is valid.'; +export const VALID_USER_PROFILE_SERVICE = '%s: Valid user profile service provided.'; +export const VARIATION_REMOVED_FOR_USER = '%s: Variation mapped to experiment %s has been removed for user %s.'; +export const VARIABLE_REQUESTED_WITH_WRONG_TYPE = + '%s: Requested variable type "%s", but variable is of type "%s". Use correct API to retrieve value. Returning None.'; +export const VALID_BUCKETING_ID = '%s: BucketingId is valid: "%s"'; +export const BUCKETING_ID_NOT_STRING = '%s: BucketingID attribute is not a string. Defaulted to userId'; +export const EVALUATING_AUDIENCE = '%s: Starting to evaluate audience "%s" with conditions: %s.'; +export const EVALUATING_AUDIENCES_COMBINED = '%s: Evaluating audiences for %s "%s": %s.'; +export const AUDIENCE_EVALUATION_RESULT = '%s: Audience "%s" evaluated to %s.'; +export const AUDIENCE_EVALUATION_RESULT_COMBINED = '%s: Audiences for %s %s collectively evaluated to %s.'; +export const MISSING_ATTRIBUTE_VALUE = + '%s: Audience condition %s evaluated to UNKNOWN because no value was passed for user attribute "%s".'; +export const UNEXPECTED_CONDITION_VALUE = + '%s: Audience condition %s evaluated to UNKNOWN because the condition value is not supported.'; +export const UNEXPECTED_TYPE = + '%s: Audience condition %s evaluated to UNKNOWN because a value of type "%s" was passed for user attribute "%s".'; +export const UNEXPECTED_TYPE_NULL = + '%s: Audience condition %s evaluated to UNKNOWN because a null value was passed for user attribute "%s".'; +export const UPDATED_OPTIMIZELY_CONFIG = '%s: Updated Optimizely config to revision %s (project id %s)'; +export const OUT_OF_BOUNDS = + '%s: Audience condition %s evaluated to UNKNOWN because the number value for user attribute "%s" is not in the range [-2^53, +2^53].'; +export const UNABLE_TO_ATTACH_UNLOAD = '%s: unable to bind optimizely.close() to page unload event: "%s"'; +export const UNABLE_TO_PARSE_AND_SKIPPED_HEADER = 'Unable to parse & skipped header item'; +export const ADDING_AUTHORIZATION_HEADER_WITH_BEARER_TOKEN = 'Adding Authorization header with Bearer Token'; +export const MAKING_DATAFILE_REQ_TO_URL_WITH_HEADERS = 'Making datafile request to url %s with headers: %s'; +export const RESPONSE_STATUS_CODE = 'Response status code: %s'; +export const SAVED_LAST_MODIFIED_HEADER_VALUE_FROM_RESPONSE = 'Saved last modified header value from response: %s'; + diff --git a/lib/notification_center/index.ts b/lib/notification_center/index.ts index d33c3fa2e..4df708096 100644 --- a/lib/notification_center/index.ts +++ b/lib/notification_center/index.ts @@ -18,13 +18,13 @@ import { objectValues } from '../utils/fns'; import { LOG_LEVEL, - LOG_MESSAGES, } from '../utils/enums'; import { NOTIFICATION_TYPES } from './type'; import { NotificationType, NotificationPayload } from './type'; import { Consumer, Fn } from '../utils/type'; import { EventEmitter } from '../utils/event_emitter/event_emitter'; +import { NOTIFICATION_LISTENER_EXCEPTION } from '../log_messages'; const MODULE_NAME = 'NOTIFICATION_CENTER'; @@ -111,7 +111,7 @@ export class DefaultNotificationCenter implements NotificationCenter, Notificati } catch (ex: any) { this.logger.log( LOG_LEVEL.ERROR, - LOG_MESSAGES.NOTIFICATION_LISTENER_EXCEPTION, + NOTIFICATION_LISTENER_EXCEPTION, MODULE_NAME, notificationType, ex.message, diff --git a/lib/odp/event_manager/odp_event_api_manager.spec.ts b/lib/odp/event_manager/odp_event_api_manager.spec.ts index 8f6a07fd2..55ec009e1 100644 --- a/lib/odp/event_manager/odp_event_api_manager.spec.ts +++ b/lib/odp/event_manager/odp_event_api_manager.spec.ts @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - import { describe, it, expect, vi } from 'vitest'; import { DefaultOdpEventApiManager, eventApiRequestGenerator, pixelApiRequestGenerator } from './odp_event_api_manager'; @@ -42,6 +41,7 @@ const PIXEL_URL = 'https://odp.pixel.com'; const odpConfig = new OdpConfig(API_KEY, API_HOST, PIXEL_URL, []); import { getMockRequestHandler } from '../../tests/mock/mock_request_handler'; +import { REQUEST_FAILED } from '../../exception_messages'; describe('DefaultOdpEventApiManager', () => { it('should generate the event request using the correct odp config and event', async () => { @@ -101,7 +101,7 @@ describe('DefaultOdpEventApiManager', () => { it('should return a promise that fails if the requestHandler response promise fails', async () => { const mockRequestHandler = getMockRequestHandler(); mockRequestHandler.makeRequest.mockReturnValue({ - responsePromise: Promise.reject(new Error('Request failed')), + responsePromise: Promise.reject(new Error(REQUEST_FAILED)), }); const requestGenerator = vi.fn().mockReturnValue({ method: 'PATCH', diff --git a/lib/odp/event_manager/odp_event_manager.spec.ts b/lib/odp/event_manager/odp_event_manager.spec.ts index 12d061918..67b874509 100644 --- a/lib/odp/event_manager/odp_event_manager.spec.ts +++ b/lib/odp/event_manager/odp_event_manager.spec.ts @@ -23,6 +23,7 @@ import { OdpEvent } from './odp_event'; import { OdpConfig } from '../odp_config'; import { EventDispatchResponse } from './odp_event_api_manager'; import { advanceTimersByTime } from '../../tests/testUtils'; +import { FAILED_TO_DISPATCH_EVENTS } from '../../exception_messages'; const API_KEY = 'test-api-key'; const API_HOST = 'https://odp.example.com'; @@ -604,7 +605,7 @@ describe('DefaultOdpEventManager', () => { const repeater = getMockRepeater(); const apiManager = getMockApiManager(); - apiManager.sendEvents.mockReturnValue(Promise.reject(new Error('Failed to dispatch events'))); + apiManager.sendEvents.mockReturnValue(Promise.reject(new Error(FAILED_TO_DISPATCH_EVENTS))); const backoffController = { backoff: vi.fn().mockReturnValue(666), @@ -706,7 +707,7 @@ describe('DefaultOdpEventManager', () => { const repeater = getMockRepeater(); const apiManager = getMockApiManager(); - apiManager.sendEvents.mockReturnValue(Promise.reject(new Error('Failed to dispatch events'))); + apiManager.sendEvents.mockReturnValue(Promise.reject(new Error(FAILED_TO_DISPATCH_EVENTS))); const backoffController = { backoff: vi.fn().mockReturnValue(666), diff --git a/lib/odp/event_manager/odp_event_manager.ts b/lib/odp/event_manager/odp_event_manager.ts index 9db9086a4..6ebe5aaa0 100644 --- a/lib/odp/event_manager/odp_event_manager.ts +++ b/lib/odp/event_manager/odp_event_manager.ts @@ -22,8 +22,17 @@ import { BackoffController, Repeater } from '../../utils/repeater/repeater'; import { Producer } from '../../utils/type'; import { runWithRetry } from '../../utils/executor/backoff_retry_runner'; import { isSuccessStatusCode } from '../../utils/http_request_handler/http_util'; -import { ERROR_MESSAGES } from '../../utils/enums'; import { ODP_DEFAULT_EVENT_TYPE, ODP_USER_KEY } from '../constant'; +import { + EVENT_ACTION_INVALID, + EVENT_DATA_FOUND_TO_BE_INVALID, + FAILED_TO_SEND_ODP_EVENTS, + ODP_EVENT_MANAGER_IS_NOT_RUNNING, + ODP_EVENTS_SHOULD_HAVE_ATLEAST_ONE_KEY_VALUE, + ODP_NOT_INTEGRATED, +} from '../../error_messages'; +import { sprintf } from '../../utils/fns'; +import { FAILED_TO_DISPATCH_EVENTS_WITH_ARG, ODP_EVENT_MANAGER_STOPPED } from '../../exception_messages'; export interface OdpEventManager extends Service { updateConfig(odpIntegrationConfig: OdpIntegrationConfig): void; @@ -66,8 +75,7 @@ export class DefaultOdpEventManager extends BaseService implements OdpEventManag private async executeDispatch(odpConfig: OdpConfig, batch: OdpEvent[]): Promise { const res = await this.apiManager.sendEvents(odpConfig, batch); if (res.statusCode && !isSuccessStatusCode(res.statusCode)) { - // TODO: replace message with imported constants - return Promise.reject(new Error(`Failed to dispatch events: ${res.statusCode}`)); + return Promise.reject(new Error(sprintf(FAILED_TO_DISPATCH_EVENTS_WITH_ARG, res.statusCode))); } return await Promise.resolve(res); } @@ -89,8 +97,7 @@ export class DefaultOdpEventManager extends BaseService implements OdpEventManag return runWithRetry( () => this.executeDispatch(odpConfig, batch), this.retryConfig.backoffProvider(), this.retryConfig.maxRetries ).result.catch((err) => { - // TODO: replace with imported constants - this.logger?.error('failed to send odp events', err); + this.logger?.error(FAILED_TO_SEND_ODP_EVENTS, err); }); } @@ -139,7 +146,7 @@ export class DefaultOdpEventManager extends BaseService implements OdpEventManag } if (this.isNew()) { - this.startPromise.reject(new Error('odp event manager stopped before it could start')); + this.startPromise.reject(new Error(ODP_EVENT_MANAGER_STOPPED)); } this.flush(); @@ -149,27 +156,27 @@ export class DefaultOdpEventManager extends BaseService implements OdpEventManag sendEvent(event: OdpEvent): void { if (!this.isRunning()) { - this.logger?.error('ODP event manager is not running.'); + this.logger?.error(ODP_EVENT_MANAGER_IS_NOT_RUNNING); return; } if (!this.odpIntegrationConfig?.integrated) { - this.logger?.error(ERROR_MESSAGES.ODP_NOT_INTEGRATED); + this.logger?.error(ODP_NOT_INTEGRATED); return; } if (event.identifiers.size === 0) { - this.logger?.error('ODP events should have at least one key-value pair in identifiers.'); + this.logger?.error(ODP_EVENTS_SHOULD_HAVE_ATLEAST_ONE_KEY_VALUE); return; } if (!this.isDataValid(event.data)) { - this.logger?.error('Event data found to be invalid.'); + this.logger?.error(EVENT_DATA_FOUND_TO_BE_INVALID); return; } if (!event.action ) { - this.logger?.error('Event action invalid.'); + this.logger?.error(EVENT_ACTION_INVALID); return; } diff --git a/lib/odp/odp_manager.spec.ts b/lib/odp/odp_manager.spec.ts index 2464bc28b..dc6e2b96b 100644 --- a/lib/odp/odp_manager.spec.ts +++ b/lib/odp/odp_manager.spec.ts @@ -25,6 +25,7 @@ import { ODP_USER_KEY } from './constant'; import { OptimizelySegmentOption } from './segment_manager/optimizely_segment_option'; import { OdpEventManager } from './event_manager/odp_event_manager'; import { CLIENT_VERSION, JAVASCRIPT_CLIENT_ENGINE } from '../utils/enums'; +import { FAILED_TO_STOP } from '../exception_messages'; const keyA = 'key-a'; const hostA = 'host-a'; @@ -166,7 +167,7 @@ describe('DefaultOdpManager', () => { await exhaustMicrotasks(); expect(odpManager.getState()).toEqual(ServiceState.Starting); - eventManagerPromise.reject(new Error('Failed to start')); + eventManagerPromise.reject(new Error("Failed to start")); await expect(odpManager.onRunning()).rejects.toThrow(); await expect(odpManager.onTerminated()).rejects.toThrow(); @@ -186,7 +187,7 @@ describe('DefaultOdpManager', () => { odpManager.start(); expect(odpManager.getState()).toEqual(ServiceState.Starting); - eventManagerPromise.reject(new Error('Failed to start')); + eventManagerPromise.reject(new Error("Failed to start")); await expect(odpManager.onRunning()).rejects.toThrow(); await expect(odpManager.onTerminated()).rejects.toThrow(); @@ -692,7 +693,7 @@ describe('DefaultOdpManager', () => { await exhaustMicrotasks(); expect(odpManager.getState()).toEqual(ServiceState.Stopping); - eventManagerTerminatedPromise.reject(new Error('Failed to stop')); + eventManagerTerminatedPromise.reject(new Error(FAILED_TO_STOP)); await expect(odpManager.onTerminated()).rejects.toThrow(); }); }); diff --git a/lib/odp/odp_manager.ts b/lib/odp/odp_manager.ts index 560e445a4..05c476ff3 100644 --- a/lib/odp/odp_manager.ts +++ b/lib/odp/odp_manager.ts @@ -29,6 +29,7 @@ import { CLIENT_VERSION, JAVASCRIPT_CLIENT_ENGINE } from '../utils/enums'; import { ODP_DEFAULT_EVENT_TYPE, ODP_EVENT_ACTION, ODP_USER_KEY } from './constant'; import { isVuid } from '../vuid/vuid'; import { Maybe } from '../utils/type'; +import { ODP_MANAGER_STOPPED_BEFORE_RUNNING } from '../exception_messages'; export interface OdpManager extends Service { updateConfig(odpIntegrationConfig: OdpIntegrationConfig): boolean; @@ -131,7 +132,7 @@ export class DefaultOdpManager extends BaseService implements OdpManager { } if (!this.isRunning()) { - this.startPromise.reject(new Error('odp manager stopped before running')); + this.startPromise.reject(new Error(ODP_MANAGER_STOPPED_BEFORE_RUNNING)); } this.state = ServiceState.Stopping; diff --git a/lib/odp/segment_manager/odp_segment_api_manager.spec.ts b/lib/odp/segment_manager/odp_segment_api_manager.spec.ts index 52237add9..ad07894bd 100644 --- a/lib/odp/segment_manager/odp_segment_api_manager.spec.ts +++ b/lib/odp/segment_manager/odp_segment_api_manager.spec.ts @@ -46,7 +46,7 @@ describe('DefaultOdpSegmentApiManager', () => { const requestHandler = getMockRequestHandler(); requestHandler.makeRequest.mockReturnValue({ abort: () => {}, - responsePromise: Promise.reject(new Error('Request timed out')), + responsePromise: Promise.reject(new Error("Request timed out")), }); const logger = getMockLogger(); const manager = new DefaultOdpSegmentApiManager(requestHandler, logger); diff --git a/lib/odp/segment_manager/odp_segment_manager.ts b/lib/odp/segment_manager/odp_segment_manager.ts index dbf83a12f..1dc2eca42 100644 --- a/lib/odp/segment_manager/odp_segment_manager.ts +++ b/lib/odp/segment_manager/odp_segment_manager.ts @@ -14,13 +14,13 @@ * limitations under the License. */ -import { ERROR_MESSAGES } from '../../utils/enums'; import { Cache } from '../../utils/cache/cache'; import { OdpSegmentApiManager } from './odp_segment_api_manager'; import { OdpIntegrationConfig } from '../odp_config'; import { OptimizelySegmentOption } from './optimizely_segment_option'; import { ODP_USER_KEY } from '../constant'; import { LoggerFacade } from '../../modules/logging'; +import { ODP_CONFIG_NOT_AVAILABLE, ODP_NOT_INTEGRATED } from '../../error_messages'; export interface OdpSegmentManager { fetchQualifiedSegments( @@ -61,12 +61,12 @@ export class DefaultOdpSegmentManager implements OdpSegmentManager { options?: Array ): Promise { if (!this.odpIntegrationConfig) { - this.logger?.warn(ERROR_MESSAGES.ODP_CONFIG_NOT_AVAILABLE); + this.logger?.warn(ODP_CONFIG_NOT_AVAILABLE); return null; } if (!this.odpIntegrationConfig.integrated) { - this.logger?.warn(ERROR_MESSAGES.ODP_NOT_INTEGRATED); + this.logger?.warn(ODP_NOT_INTEGRATED); return null; } diff --git a/lib/optimizely/index.spec.ts b/lib/optimizely/index.spec.ts index 364c05658..5ced36a08 100644 --- a/lib/optimizely/index.spec.ts +++ b/lib/optimizely/index.spec.ts @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - import { describe, it, expect, vi } from 'vitest'; import Optimizely from '.'; import { getMockProjectConfigManager } from '../tests/mock/mock_project_config_manager'; diff --git a/lib/optimizely/index.tests.js b/lib/optimizely/index.tests.js index 187764625..4f121df29 100644 --- a/lib/optimizely/index.tests.js +++ b/lib/optimizely/index.tests.js @@ -18,7 +18,6 @@ import sinon from 'sinon'; import { sprintf } from '../utils/fns'; import { NOTIFICATION_TYPES } from '../notification_center/type'; import * as logging from '../modules/logging'; - import Optimizely from './'; import OptimizelyUserContext from '../optimizely_user_context'; import { OptimizelyDecideOption } from '../shared_types'; @@ -38,10 +37,44 @@ import { createNotificationCenter } from '../notification_center'; import { createProjectConfig } from '../project_config/project_config'; import { getMockProjectConfigManager } from '../tests/mock/mock_project_config_manager'; import { DECISION_NOTIFICATION_TYPES } from '../notification_center/type'; +import { + AUDIENCE_EVALUATION_RESULT_COMBINED, + EVENT_KEY_NOT_FOUND, + EXPERIMENT_NOT_RUNNING, + FEATURE_HAS_NO_EXPERIMENTS, + FORCED_BUCKETING_FAILED, + INVALID_CLIENT_ENGINE, + INVALID_DEFAULT_DECIDE_OPTIONS, + INVALID_OBJECT, + NOT_ACTIVATING_USER, + NOT_TRACKING_USER, + RETURNING_STORED_VARIATION, + USER_DOESNT_MEET_CONDITIONS_FOR_TARGETING_RULE, + USER_FORCED_IN_VARIATION, + USER_HAS_FORCED_VARIATION, + USER_HAS_NO_FORCED_VARIATION, + USER_HAS_NO_FORCED_VARIATION_FOR_EXPERIMENT, + USER_HAS_NO_VARIATION, + USER_HAS_VARIATION, + USER_IN_ROLLOUT, + USER_MAPPED_TO_FORCED_VARIATION, + USER_MEETS_CONDITIONS_FOR_TARGETING_RULE, + USER_NOT_BUCKETED_INTO_TARGETING_RULE, + USER_NOT_IN_EXPERIMENT, + VARIATION_REMOVED_FOR_USER, +} from '../log_messages'; +import { + EXPERIMENT_KEY_NOT_IN_DATAFILE, + INVALID_ATTRIBUTES, + INVALID_EXPERIMENT_KEY, + INVALID_INPUT_FORMAT, + NO_VARIATION_FOR_EXPERIMENT_KEY, + USER_NOT_IN_FORCED_VARIATION, +} from '../error_messages'; +import { FAILED_TO_STOP, ONREADY_TIMEOUT_EXPIRED, PROMISE_SHOULD_NOT_HAVE_RESOLVED } from '../exception_messages'; +import { USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP } from '../core/bucketer'; -var ERROR_MESSAGES = enums.ERROR_MESSAGES; var LOG_LEVEL = enums.LOG_LEVEL; -var LOG_MESSAGES = enums.LOG_MESSAGES; var DECISION_SOURCES = enums.DECISION_SOURCES; var DECISION_MESSAGES = enums.DECISION_MESSAGES; var FEATURE_VARIABLE_TYPES = enums.FEATURE_VARIABLE_TYPES; @@ -158,7 +191,7 @@ describe('lib/optimizely', function() { sinon.assert.called(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_CLIENT_ENGINE, 'OPTIMIZELY', 'undefined')); + assert.strictEqual(logMessage, sprintf(INVALID_CLIENT_ENGINE, 'OPTIMIZELY', 'undefined')); }); it('should log if the defaultDecideOptions passed in are invalid', function() { @@ -175,7 +208,7 @@ describe('lib/optimizely', function() { sinon.assert.called(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_DEFAULT_DECIDE_OPTIONS, 'OPTIMIZELY')); + assert.strictEqual(logMessage, sprintf(INVALID_DEFAULT_DECIDE_OPTIONS, 'OPTIMIZELY')); }); it('should allow passing `react-sdk` as the clientEngine', function() { @@ -759,7 +792,7 @@ describe('lib/optimizely', function() { sinon.assert.calledWithExactly( createdLogger.log, LOG_LEVEL.DEBUG, - LOG_MESSAGES.USER_HAS_NO_FORCED_VARIATION, + USER_HAS_NO_FORCED_VARIATION, 'DECISION_SERVICE', 'testUser' ); @@ -767,7 +800,7 @@ describe('lib/optimizely', function() { sinon.assert.calledWithExactly( createdLogger.log, LOG_LEVEL.INFO, - LOG_MESSAGES.NOT_ACTIVATING_USER, + NOT_ACTIVATING_USER, 'OPTIMIZELY', 'testUser', 'testExperiment' @@ -780,7 +813,7 @@ describe('lib/optimizely', function() { sinon.assert.calledWithExactly( createdLogger.log, LOG_LEVEL.DEBUG, - LOG_MESSAGES.USER_HAS_NO_FORCED_VARIATION, + USER_HAS_NO_FORCED_VARIATION, 'DECISION_SERVICE', 'testUser' ); @@ -788,7 +821,7 @@ describe('lib/optimizely', function() { sinon.assert.calledWithExactly( createdLogger.log, LOG_LEVEL.INFO, - LOG_MESSAGES.USER_NOT_IN_EXPERIMENT, + USER_NOT_IN_EXPERIMENT, 'DECISION_SERVICE', 'testUser', 'testExperimentWithAudiences' @@ -797,7 +830,7 @@ describe('lib/optimizely', function() { sinon.assert.calledWithExactly( createdLogger.log, LOG_LEVEL.INFO, - LOG_MESSAGES.NOT_ACTIVATING_USER, + NOT_ACTIVATING_USER, 'OPTIMIZELY', 'testUser', 'testExperimentWithAudiences' @@ -810,7 +843,7 @@ describe('lib/optimizely', function() { sinon.assert.calledWithExactly( createdLogger.log, LOG_LEVEL.DEBUG, - LOG_MESSAGES.USER_HAS_NO_FORCED_VARIATION, + USER_HAS_NO_FORCED_VARIATION, 'DECISION_SERVICE', 'testUser' ); @@ -818,7 +851,7 @@ describe('lib/optimizely', function() { sinon.assert.calledWithExactly( createdLogger.log, LOG_LEVEL.INFO, - LOG_MESSAGES.USER_NOT_IN_EXPERIMENT, + USER_NOT_IN_EXPERIMENT, 'DECISION_SERVICE', 'testUser', 'groupExperiment1' @@ -827,7 +860,7 @@ describe('lib/optimizely', function() { sinon.assert.calledWithExactly( createdLogger.log, LOG_LEVEL.INFO, - LOG_MESSAGES.NOT_ACTIVATING_USER, + NOT_ACTIVATING_USER, 'OPTIMIZELY', 'testUser', 'groupExperiment1' @@ -841,12 +874,12 @@ describe('lib/optimizely', function() { var logMessage1 = buildLogMessageFromArgs(createdLogger.log.args[0]); assert.strictEqual( logMessage1, - sprintf(LOG_MESSAGES.EXPERIMENT_NOT_RUNNING, 'DECISION_SERVICE', 'testExperimentNotRunning') + sprintf(EXPERIMENT_NOT_RUNNING, 'DECISION_SERVICE', 'testExperimentNotRunning') ); var logMessage2 = buildLogMessageFromArgs(createdLogger.log.args[1]); assert.strictEqual( logMessage2, - sprintf(LOG_MESSAGES.NOT_ACTIVATING_USER, 'OPTIMIZELY', 'testUser', 'testExperimentNotRunning') + sprintf(NOT_ACTIVATING_USER, 'OPTIMIZELY', 'testUser', 'testExperimentNotRunning') ); }); @@ -857,16 +890,16 @@ describe('lib/optimizely', function() { sinon.assert.calledOnce(errorHandler.handleError); var errorMessage = errorHandler.handleError.lastCall.args[0].message; - assert.strictEqual(errorMessage, sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); + assert.strictEqual(errorMessage, sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); sinon.assert.calledTwice(createdLogger.log); var logMessage1 = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage1, sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); + assert.strictEqual(logMessage1, sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); var logMessage2 = buildLogMessageFromArgs(createdLogger.log.args[1]); assert.strictEqual( logMessage2, - sprintf(LOG_MESSAGES.NOT_ACTIVATING_USER, 'OPTIMIZELY', 'null', 'testExperiment') + sprintf(NOT_ACTIVATING_USER, 'OPTIMIZELY', 'null', 'testExperiment') ); }); @@ -879,12 +912,12 @@ describe('lib/optimizely', function() { var logMessage1 = buildLogMessageFromArgs(createdLogger.log.args[0]); assert.strictEqual( logMessage1, - sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, 'OPTIMIZELY', 'invalidExperimentKey') + sprintf(INVALID_EXPERIMENT_KEY, 'OPTIMIZELY', 'invalidExperimentKey') ); var logMessage2 = buildLogMessageFromArgs(createdLogger.log.args[1]); assert.strictEqual( logMessage2, - sprintf(LOG_MESSAGES.NOT_ACTIVATING_USER, 'OPTIMIZELY', 'testUser', 'invalidExperimentKey') + sprintf(NOT_ACTIVATING_USER, 'OPTIMIZELY', 'testUser', 'invalidExperimentKey') ); }); @@ -894,15 +927,15 @@ describe('lib/optimizely', function() { sinon.assert.notCalled(eventDispatcher.dispatchEvent); sinon.assert.calledOnce(errorHandler.handleError); var errorMessage = errorHandler.handleError.lastCall.args[0].message; - assert.strictEqual(errorMessage, sprintf(ERROR_MESSAGES.INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); + assert.strictEqual(errorMessage, sprintf(INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); sinon.assert.calledTwice(createdLogger.log); var logMessage1 = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage1, sprintf(ERROR_MESSAGES.INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); + assert.strictEqual(logMessage1, sprintf(INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); var logMessage2 = buildLogMessageFromArgs(createdLogger.log.args[1]); assert.strictEqual( logMessage2, - sprintf(LOG_MESSAGES.NOT_ACTIVATING_USER, 'OPTIMIZELY', 'testUser', 'testExperimentWithAudiences') + sprintf(NOT_ACTIVATING_USER, 'OPTIMIZELY', 'testUser', 'testExperimentWithAudiences') ); }); @@ -955,12 +988,12 @@ describe('lib/optimizely', function() { var logMessage0 = buildLogMessageFromArgs(createdLogger.log.args[0]); assert.strictEqual( logMessage0, - sprintf(LOG_MESSAGES.USER_HAS_NO_FORCED_VARIATION, 'DECISION_SERVICE', 'user1') + sprintf(USER_HAS_NO_FORCED_VARIATION, 'DECISION_SERVICE', 'user1') ); var logMessage1 = buildLogMessageFromArgs(createdLogger.log.args[1]); assert.strictEqual( logMessage1, - sprintf(LOG_MESSAGES.USER_FORCED_IN_VARIATION, 'DECISION_SERVICE', 'user1', 'control') + sprintf(USER_FORCED_IN_VARIATION, 'DECISION_SERVICE', 'user1', 'control') ); var expectedObj = { @@ -1020,7 +1053,7 @@ describe('lib/optimizely', function() { sinon.assert.calledOnce(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'activate')); + assert.strictEqual(logMessage, sprintf(INVALID_OBJECT, 'OPTIMIZELY', 'activate')); sinon.assert.notCalled(eventDispatcher.dispatchEvent); }); @@ -1640,11 +1673,11 @@ describe('lib/optimizely', function() { sinon.assert.calledOnce(errorHandler.handleError); var errorMessage = errorHandler.handleError.lastCall.args[0].message; - assert.strictEqual(errorMessage, sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); + assert.strictEqual(errorMessage, sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); sinon.assert.calledOnce(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); + assert.strictEqual(logMessage, sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); }); it('should log a warning for an event key that is not in the datafile and a warning for not tracking user', function() { @@ -1656,7 +1689,7 @@ describe('lib/optimizely', function() { sinon.assert.calledWithExactly( logCall1, LOG_LEVEL.WARNING, - LOG_MESSAGES.EVENT_KEY_NOT_FOUND, + EVENT_KEY_NOT_FOUND, 'OPTIMIZELY', 'invalidEventKey' ); @@ -1665,7 +1698,7 @@ describe('lib/optimizely', function() { sinon.assert.calledWithExactly( logCall2, LOG_LEVEL.WARNING, - LOG_MESSAGES.NOT_TRACKING_USER, + NOT_TRACKING_USER, 'OPTIMIZELY', 'testUser' ); @@ -1680,11 +1713,11 @@ describe('lib/optimizely', function() { sinon.assert.calledOnce(errorHandler.handleError); var errorMessage = errorHandler.handleError.lastCall.args[0].message; - assert.strictEqual(errorMessage, sprintf(ERROR_MESSAGES.INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); + assert.strictEqual(errorMessage, sprintf(INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); sinon.assert.calledOnce(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(ERROR_MESSAGES.INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); + assert.strictEqual(logMessage, sprintf(INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); }); it('should not throw an error for an event key without associated experiment IDs', function() { @@ -1732,7 +1765,7 @@ describe('lib/optimizely', function() { sinon.assert.calledOnce(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'track')); + assert.strictEqual(logMessage, sprintf(INVALID_OBJECT, 'OPTIMIZELY', 'track')); sinon.assert.notCalled(eventDispatcher.dispatchEvent); }); @@ -1755,7 +1788,7 @@ describe('lib/optimizely', function() { sinon.assert.calledWithExactly( createdLogger.log, LOG_LEVEL.DEBUG, - LOG_MESSAGES.USER_HAS_NO_FORCED_VARIATION, + USER_HAS_NO_FORCED_VARIATION, 'DECISION_SERVICE', 'testUser' ); @@ -1790,7 +1823,7 @@ describe('lib/optimizely', function() { sinon.assert.calledWithExactly( createdLogger.log, LOG_LEVEL.DEBUG, - LOG_MESSAGES.USER_HAS_NO_FORCED_VARIATION, + USER_HAS_NO_FORCED_VARIATION, 'DECISION_SERVICE', 'testUser' ); @@ -1798,7 +1831,7 @@ describe('lib/optimizely', function() { sinon.assert.calledWithExactly( createdLogger.log, LOG_LEVEL.INFO, - LOG_MESSAGES.USER_NOT_IN_EXPERIMENT, + USER_NOT_IN_EXPERIMENT, 'DECISION_SERVICE', 'testUser', 'testExperimentWithAudiences' @@ -1807,7 +1840,7 @@ describe('lib/optimizely', function() { sinon.assert.calledWithExactly( createdLogger.log, LOG_LEVEL.INFO, - LOG_MESSAGES.EXPERIMENT_NOT_RUNNING, + EXPERIMENT_NOT_RUNNING, 'DECISION_SERVICE', 'testExperimentNotRunning' ); @@ -1820,11 +1853,11 @@ describe('lib/optimizely', function() { sinon.assert.calledOnce(errorHandler.handleError); var errorMessage = errorHandler.handleError.lastCall.args[0].message; - assert.strictEqual(errorMessage, sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); + assert.strictEqual(errorMessage, sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); sinon.assert.calledOnce(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); + assert.strictEqual(logMessage, sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); }); it('should log an error for invalid experiment key', function() { @@ -1835,7 +1868,7 @@ describe('lib/optimizely', function() { var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); assert.strictEqual( logMessage, - sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, 'OPTIMIZELY', 'invalidExperimentKey') + sprintf(INVALID_EXPERIMENT_KEY, 'OPTIMIZELY', 'invalidExperimentKey') ); }); @@ -1846,11 +1879,11 @@ describe('lib/optimizely', function() { sinon.assert.calledOnce(errorHandler.handleError); var errorMessage = errorHandler.handleError.lastCall.args[0].message; - assert.strictEqual(errorMessage, sprintf(ERROR_MESSAGES.INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); + assert.strictEqual(errorMessage, sprintf(INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); sinon.assert.calledOnce(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(ERROR_MESSAGES.INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); + assert.strictEqual(logMessage, sprintf(INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); }); describe('whitelisting', function() { @@ -1873,12 +1906,12 @@ describe('lib/optimizely', function() { var logMessage0 = buildLogMessageFromArgs(createdLogger.log.args[0]); assert.strictEqual( logMessage0, - sprintf(LOG_MESSAGES.USER_HAS_NO_FORCED_VARIATION, 'DECISION_SERVICE', 'user1') + sprintf(USER_HAS_NO_FORCED_VARIATION, 'DECISION_SERVICE', 'user1') ); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[1]); assert.strictEqual( logMessage, - sprintf(LOG_MESSAGES.USER_FORCED_IN_VARIATION, 'DECISION_SERVICE', 'user1', 'control') + sprintf(USER_FORCED_IN_VARIATION, 'DECISION_SERVICE', 'user1', 'control') ); }); }); @@ -1899,7 +1932,7 @@ describe('lib/optimizely', function() { sinon.assert.calledOnce(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getVariation')); + assert.strictEqual(logMessage, sprintf(INVALID_OBJECT, 'OPTIMIZELY', 'getVariation')); sinon.assert.notCalled(eventDispatcher.dispatchEvent); }); @@ -1951,7 +1984,7 @@ describe('lib/optimizely', function() { assert.strictEqual(forcedVariation, null); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.USER_HAS_NO_FORCED_VARIATION, 'DECISION_SERVICE', 'user1')); + assert.strictEqual(logMessage, sprintf(USER_HAS_NO_FORCED_VARIATION, 'DECISION_SERVICE', 'user1')); }); it('should return null with a null experimentKey', function() { @@ -1959,7 +1992,7 @@ describe('lib/optimizely', function() { assert.strictEqual(forcedVariation, null); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'experiment_key')); + assert.strictEqual(logMessage, sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'experiment_key')); }); it('should return null with an undefined experimentKey', function() { @@ -1967,7 +2000,7 @@ describe('lib/optimizely', function() { assert.strictEqual(forcedVariation, null); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'experiment_key')); + assert.strictEqual(logMessage, sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'experiment_key')); }); it('should return null with a null userId', function() { @@ -1975,7 +2008,7 @@ describe('lib/optimizely', function() { assert.strictEqual(forcedVariation, null); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); + assert.strictEqual(logMessage, sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); }); it('should return null with an undefined userId', function() { @@ -1983,7 +2016,7 @@ describe('lib/optimizely', function() { assert.strictEqual(forcedVariation, null); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); + assert.strictEqual(logMessage, sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); }); }); @@ -1995,7 +2028,7 @@ describe('lib/optimizely', function() { var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); assert.strictEqual( logMessage, - sprintf(LOG_MESSAGES.USER_MAPPED_TO_FORCED_VARIATION, 'DECISION_SERVICE', 111128, 111127, 'user1') + sprintf(USER_MAPPED_TO_FORCED_VARIATION, 'DECISION_SERVICE', 111128, 111127, 'user1') ); }); @@ -2034,17 +2067,17 @@ describe('lib/optimizely', function() { assert.strictEqual( setVariationLogMessage, - sprintf(LOG_MESSAGES.USER_MAPPED_TO_FORCED_VARIATION, 'DECISION_SERVICE', 111128, 111127, 'user1') + sprintf(USER_MAPPED_TO_FORCED_VARIATION, 'DECISION_SERVICE', 111128, 111127, 'user1') ); assert.strictEqual( variationIsMappedLogMessage, - sprintf(LOG_MESSAGES.USER_HAS_FORCED_VARIATION, 'DECISION_SERVICE', 'control', 'testExperiment', 'user1') + sprintf(USER_HAS_FORCED_VARIATION, 'DECISION_SERVICE', 'control', 'testExperiment', 'user1') ); assert.strictEqual( variationMappingRemovedLogMessage, - sprintf(LOG_MESSAGES.VARIATION_REMOVED_FOR_USER, 'DECISION_SERVICE', 'testExperiment', 'user1') + sprintf(VARIATION_REMOVED_FOR_USER, 'DECISION_SERVICE', 'testExperiment', 'user1') ); }); @@ -2074,7 +2107,7 @@ describe('lib/optimizely', function() { assert.strictEqual( logMessage, sprintf( - ERROR_MESSAGES.NO_VARIATION_FOR_EXPERIMENT_KEY, + NO_VARIATION_FOR_EXPERIMENT_KEY, 'DECISION_SERVICE', 'definitely_not_valid_variation_key', 'testExperiment' @@ -2089,7 +2122,7 @@ describe('lib/optimizely', function() { var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); assert.strictEqual( logMessage, - sprintf(ERROR_MESSAGES.EXPERIMENT_KEY_NOT_IN_DATAFILE, 'PROJECT_CONFIG', 'definitely_not_valid_exp_key') + sprintf(EXPERIMENT_KEY_NOT_IN_DATAFILE, 'PROJECT_CONFIG', 'definitely_not_valid_exp_key') ); }); @@ -2103,14 +2136,14 @@ describe('lib/optimizely', function() { var setVariationLogMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); assert.strictEqual( setVariationLogMessage, - sprintf(LOG_MESSAGES.USER_MAPPED_TO_FORCED_VARIATION, 'DECISION_SERVICE', 111128, 111127, 'user1') + sprintf(USER_MAPPED_TO_FORCED_VARIATION, 'DECISION_SERVICE', 111128, 111127, 'user1') ); var noVariationToGetLogMessage = buildLogMessageFromArgs(createdLogger.log.args[1]); assert.strictEqual( noVariationToGetLogMessage, sprintf( - LOG_MESSAGES.USER_HAS_NO_FORCED_VARIATION_FOR_EXPERIMENT, + USER_HAS_NO_FORCED_VARIATION_FOR_EXPERIMENT, 'DECISION_SERVICE', 'testExperimentLaunched', 'user1' @@ -2125,7 +2158,7 @@ describe('lib/optimizely', function() { var setVariationLogMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); assert.strictEqual( setVariationLogMessage, - sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'experiment_key') + sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'experiment_key') ); }); @@ -2136,7 +2169,7 @@ describe('lib/optimizely', function() { var setVariationLogMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); assert.strictEqual( setVariationLogMessage, - sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'experiment_key') + sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'experiment_key') ); }); @@ -2147,7 +2180,7 @@ describe('lib/optimizely', function() { var setVariationLogMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); assert.strictEqual( setVariationLogMessage, - sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'experiment_key') + sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'experiment_key') ); }); @@ -2158,7 +2191,7 @@ describe('lib/optimizely', function() { var setVariationLogMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); assert.strictEqual( setVariationLogMessage, - sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id') + sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id') ); }); @@ -2169,7 +2202,7 @@ describe('lib/optimizely', function() { var setVariationLogMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); assert.strictEqual( setVariationLogMessage, - sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id') + sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id') ); }); @@ -2185,7 +2218,7 @@ describe('lib/optimizely', function() { var setVariationLogMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); assert.strictEqual( setVariationLogMessage, - sprintf(ERROR_MESSAGES.USER_NOT_IN_FORCED_VARIATION, 'DECISION_SERVICE', 'user1') + sprintf(USER_NOT_IN_FORCED_VARIATION, 'DECISION_SERVICE', 'user1') ); }); @@ -2196,7 +2229,7 @@ describe('lib/optimizely', function() { var setVariationLogMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); assert.strictEqual( setVariationLogMessage, - sprintf(ERROR_MESSAGES.USER_NOT_IN_FORCED_VARIATION, 'DECISION_SERVICE', 'user1') + sprintf(USER_NOT_IN_FORCED_VARIATION, 'DECISION_SERVICE', 'user1') ); }); @@ -2214,13 +2247,13 @@ describe('lib/optimizely', function() { var logMessage0 = buildLogMessageFromArgs(createdLogger.log.args[0]); assert.strictEqual( logMessage0, - sprintf(LOG_MESSAGES.USER_MAPPED_TO_FORCED_VARIATION, 'DECISION_SERVICE', 133338, 133337, 'user1') + sprintf(USER_MAPPED_TO_FORCED_VARIATION, 'DECISION_SERVICE', 133338, 133337, 'user1') ); var logMessage1 = buildLogMessageFromArgs(createdLogger.log.args[1]); assert.strictEqual( logMessage1, - sprintf(LOG_MESSAGES.EXPERIMENT_NOT_RUNNING, 'DECISION_SERVICE', 'testExperimentNotRunning') + sprintf(EXPERIMENT_NOT_RUNNING, 'DECISION_SERVICE', 'testExperimentNotRunning') ); }); }); @@ -2245,11 +2278,11 @@ describe('lib/optimizely', function() { sinon.assert.calledThrice(errorHandler.handleError); var errorMessage = errorHandler.handleError.lastCall.args[0].message; - assert.strictEqual(errorMessage, sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); + assert.strictEqual(errorMessage, sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); sinon.assert.calledThrice(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); + assert.strictEqual(logMessage, sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); }); it('should return false and throw an error if attributes are invalid', function() { @@ -2258,11 +2291,11 @@ describe('lib/optimizely', function() { sinon.assert.calledOnce(errorHandler.handleError); var errorMessage = errorHandler.handleError.lastCall.args[0].message; - assert.strictEqual(errorMessage, sprintf(ERROR_MESSAGES.INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); + assert.strictEqual(errorMessage, sprintf(INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); sinon.assert.calledOnce(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(ERROR_MESSAGES.INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); + assert.strictEqual(logMessage, sprintf(INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); }); }); @@ -4589,20 +4622,20 @@ describe('lib/optimizely', function() { assert.isNull(optlyInstance.createUserContext(1)); sinon.assert.calledOnce(errorHandler.handleError); var errorMessage = errorHandler.handleError.lastCall.args[0].message; - assert.strictEqual(errorMessage, sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); + assert.strictEqual(errorMessage, sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); sinon.assert.calledOnce(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); + assert.strictEqual(logMessage, sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); }); it('should call the error handler for invalid attributes and return null', function() { assert.isNull(optlyInstance.createUserContext('user1', 'invalid_attributes')); sinon.assert.calledOnce(errorHandler.handleError); var errorMessage = errorHandler.handleError.lastCall.args[0].message; - assert.strictEqual(errorMessage, sprintf(ERROR_MESSAGES.INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); + assert.strictEqual(errorMessage, sprintf(INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); sinon.assert.calledOnce(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(ERROR_MESSAGES.INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); + assert.strictEqual(logMessage, sprintf(INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); }); }); @@ -5192,7 +5225,7 @@ describe('lib/optimizely', function() { }); var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( - sprintf(LOG_MESSAGES.EXPERIMENT_NOT_RUNNING, 'DECISION_SERVICE', 'exp_with_audience') + sprintf(EXPERIMENT_NOT_RUNNING, 'DECISION_SERVICE', 'exp_with_audience') ); }); @@ -5237,7 +5270,7 @@ describe('lib/optimizely', function() { }); var decision = optlyInstanceWithUserProfile.decide(user, flagKey); expect(decision.reasons).to.include( - sprintf(LOG_MESSAGES.RETURNING_STORED_VARIATION, 'DECISION_SERVICE', variationKey2, experimentKey, userId) + sprintf(RETURNING_STORED_VARIATION, 'DECISION_SERVICE', variationKey2, experimentKey, userId) ); }); @@ -5253,7 +5286,7 @@ describe('lib/optimizely', function() { }); var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( - sprintf(LOG_MESSAGES.USER_FORCED_IN_VARIATION, 'DECISION_SERVICE', userId, variationKey) + sprintf(USER_FORCED_IN_VARIATION, 'DECISION_SERVICE', userId, variationKey) ); }); @@ -5271,7 +5304,7 @@ describe('lib/optimizely', function() { }); var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( - sprintf(LOG_MESSAGES.USER_HAS_FORCED_VARIATION, 'DECISION_SERVICE', variationKey, experimentKey, userId) + sprintf(USER_HAS_FORCED_VARIATION, 'DECISION_SERVICE', variationKey, experimentKey, userId) ); }); @@ -5287,7 +5320,7 @@ describe('lib/optimizely', function() { }); var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( - sprintf(LOG_MESSAGES.FORCED_BUCKETING_FAILED, 'DECISION_SERVICE', variationKey, userId) + sprintf(FORCED_BUCKETING_FAILED, 'DECISION_SERVICE', variationKey, userId) ); }); @@ -5300,7 +5333,7 @@ describe('lib/optimizely', function() { user.setAttribute('country', 'US'); var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( - sprintf(LOG_MESSAGES.USER_MEETS_CONDITIONS_FOR_TARGETING_RULE, 'DECISION_SERVICE', userId, '1') + sprintf(USER_MEETS_CONDITIONS_FOR_TARGETING_RULE, 'DECISION_SERVICE', userId, '1') ); }); @@ -5313,7 +5346,7 @@ describe('lib/optimizely', function() { user.setAttribute('country', 'CA'); var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( - sprintf(LOG_MESSAGES.USER_DOESNT_MEET_CONDITIONS_FOR_TARGETING_RULE, 'DECISION_SERVICE', userId, '1') + sprintf(USER_DOESNT_MEET_CONDITIONS_FOR_TARGETING_RULE, 'DECISION_SERVICE', userId, '1') ); }); @@ -5326,7 +5359,7 @@ describe('lib/optimizely', function() { user.setAttribute('country', 'US'); var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( - sprintf(LOG_MESSAGES.USER_IN_ROLLOUT, 'DECISION_SERVICE', userId, flagKey) + sprintf(USER_IN_ROLLOUT, 'DECISION_SERVICE', userId, flagKey) ); }); @@ -5339,7 +5372,7 @@ describe('lib/optimizely', function() { user.setAttribute('country', 'KO'); var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( - sprintf(LOG_MESSAGES.USER_MEETS_CONDITIONS_FOR_TARGETING_RULE, 'DECISION_SERVICE', userId, 'Everyone Else') + sprintf(USER_MEETS_CONDITIONS_FOR_TARGETING_RULE, 'DECISION_SERVICE', userId, 'Everyone Else') ); }); @@ -5352,7 +5385,7 @@ describe('lib/optimizely', function() { user.setAttribute('browser', 'safari'); var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( - sprintf(LOG_MESSAGES.USER_NOT_BUCKETED_INTO_TARGETING_RULE, 'DECISION_SERVICE', userId, '2') + sprintf(USER_NOT_BUCKETED_INTO_TARGETING_RULE, 'DECISION_SERVICE', userId, '2') ); }); @@ -5366,7 +5399,7 @@ describe('lib/optimizely', function() { }); var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( - sprintf(LOG_MESSAGES.USER_HAS_VARIATION, 'DECISION_SERVICE', userId, variationKey, experimentKey) + sprintf(USER_HAS_VARIATION, 'DECISION_SERVICE', userId, variationKey, experimentKey) ); }); @@ -5384,7 +5417,7 @@ describe('lib/optimizely', function() { }); var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( - sprintf(LOG_MESSAGES.USER_HAS_NO_VARIATION, 'DECISION_SERVICE', userId, experimentKey) + sprintf(USER_HAS_NO_VARIATION, 'DECISION_SERVICE', userId, experimentKey) ); }); @@ -5402,7 +5435,7 @@ describe('lib/optimizely', function() { }); var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( - sprintf(LOG_MESSAGES.USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP, 'BUCKETER', userId, experimentKey, groupId) + sprintf(USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP, 'BUCKETER', userId, experimentKey, groupId) ); }); @@ -5417,7 +5450,7 @@ describe('lib/optimizely', function() { }); var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( - sprintf(LOG_MESSAGES.FEATURE_HAS_NO_EXPERIMENTS, 'DECISION_SERVICE', flagKey) + sprintf(FEATURE_HAS_NO_EXPERIMENTS, 'DECISION_SERVICE', flagKey) ); }); @@ -5430,7 +5463,7 @@ describe('lib/optimizely', function() { }); var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( - sprintf(LOG_MESSAGES.USER_NOT_IN_EXPERIMENT, 'DECISION_SERVICE', userId, experimentKey) + sprintf(USER_NOT_IN_EXPERIMENT, 'DECISION_SERVICE', userId, experimentKey) ); }); @@ -5449,7 +5482,7 @@ describe('lib/optimizely', function() { var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( sprintf( - LOG_MESSAGES.AUDIENCE_EVALUATION_RESULT_COMBINED, + AUDIENCE_EVALUATION_RESULT_COMBINED, 'DECISION_SERVICE', 'experiment', experimentKey, @@ -5474,7 +5507,7 @@ describe('lib/optimizely', function() { var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( sprintf( - LOG_MESSAGES.AUDIENCE_EVALUATION_RESULT_COMBINED, + AUDIENCE_EVALUATION_RESULT_COMBINED, 'DECISION_SERVICE', 'experiment', experimentKey, @@ -5499,7 +5532,7 @@ describe('lib/optimizely', function() { var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( sprintf( - LOG_MESSAGES.AUDIENCE_EVALUATION_RESULT_COMBINED, + AUDIENCE_EVALUATION_RESULT_COMBINED, 'DECISION_SERVICE', 'experiment', experimentKey, @@ -5524,7 +5557,7 @@ describe('lib/optimizely', function() { var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( sprintf( - LOG_MESSAGES.AUDIENCE_EVALUATION_RESULT_COMBINED, + AUDIENCE_EVALUATION_RESULT_COMBINED, 'DECISION_SERVICE', 'experiment', experimentKey, @@ -5549,7 +5582,7 @@ describe('lib/optimizely', function() { var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( sprintf( - LOG_MESSAGES.AUDIENCE_EVALUATION_RESULT_COMBINED, + AUDIENCE_EVALUATION_RESULT_COMBINED, 'DECISION_SERVICE', 'experiment', experimentKey, @@ -5574,7 +5607,7 @@ describe('lib/optimizely', function() { var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( sprintf( - LOG_MESSAGES.AUDIENCE_EVALUATION_RESULT_COMBINED, + AUDIENCE_EVALUATION_RESULT_COMBINED, 'DECISION_SERVICE', 'experiment', experimentKey, @@ -5599,7 +5632,7 @@ describe('lib/optimizely', function() { var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( sprintf( - LOG_MESSAGES.AUDIENCE_EVALUATION_RESULT_COMBINED, + AUDIENCE_EVALUATION_RESULT_COMBINED, 'DECISION_SERVICE', 'experiment', experimentKey, @@ -5623,7 +5656,7 @@ describe('lib/optimizely', function() { var decision = optlyInstance.decide(user, flagKey); expect(decision.reasons).to.include( sprintf( - LOG_MESSAGES.AUDIENCE_EVALUATION_RESULT_COMBINED, + AUDIENCE_EVALUATION_RESULT_COMBINED, 'DECISION_SERVICE', 'experiment', experimentKey, @@ -8988,7 +9021,7 @@ describe('lib/optimizely', function() { sinon.assert.calledOnce(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariable')); + assert.strictEqual(logMessage, sprintf(INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariable')); }); it('returns null from getFeatureVariableBoolean when optimizely object is not a valid instance', function() { @@ -9007,7 +9040,7 @@ describe('lib/optimizely', function() { sinon.assert.calledOnce(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariableBoolean')); + assert.strictEqual(logMessage, sprintf(INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariableBoolean')); }); it('returns null from getFeatureVariableDouble when optimizely object is not a valid instance', function() { @@ -9026,7 +9059,7 @@ describe('lib/optimizely', function() { sinon.assert.calledOnce(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariableDouble')); + assert.strictEqual(logMessage, sprintf(INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariableDouble')); }); it('returns null from getFeatureVariableInteger when optimizely object is not a valid instance', function() { @@ -9045,7 +9078,7 @@ describe('lib/optimizely', function() { sinon.assert.calledOnce(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariableInteger')); + assert.strictEqual(logMessage, sprintf(INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariableInteger')); }); it('returns null from getFeatureVariableString when optimizely object is not a valid instance', function() { @@ -9064,7 +9097,7 @@ describe('lib/optimizely', function() { sinon.assert.calledOnce(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariableString')); + assert.strictEqual(logMessage, sprintf(INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariableString')); }); it('returns null from getFeatureVariableJSON when optimizely object is not a valid instance', function() { @@ -9083,7 +9116,7 @@ describe('lib/optimizely', function() { sinon.assert.calledOnce(createdLogger.log); var logMessage = buildLogMessageFromArgs(createdLogger.log.args[0]); - assert.strictEqual(logMessage, sprintf(LOG_MESSAGES.INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariableJSON')); + assert.strictEqual(logMessage, sprintf(INVALID_OBJECT, 'OPTIMIZELY', 'getFeatureVariableJSON')); }); }); }); @@ -9804,7 +9837,7 @@ describe('lib/optimizely', function() { describe('when the event processor onTerminated() method returns a promise that rejects', function() { beforeEach(function() { - eventProcessorStopPromise = Promise.reject(new Error('Failed to stop')); + eventProcessorStopPromise = Promise.reject(new Error(FAILED_TO_STOP)); eventProcessorStopPromise.catch(() => {}); mockEventProcessor.onTerminated.returns(eventProcessorStopPromise); const mockConfigManager = getMockProjectConfigManager({ @@ -9979,9 +10012,9 @@ describe('lib/optimizely', function() { var readyPromise = optlyInstance.onReady({ timeout: 500 }); clock.tick(501); return readyPromise.then(() => { - return Promise.reject(new Error('Promise should not have resolved')); + return Promise.reject(new Error(PROMISE_SHOULD_NOT_HAVE_RESOLVED)); }, (err) => { - assert.equal(err.message, 'onReady timeout expired after 500 ms') + assert.equal(err.message, sprintf(ONREADY_TIMEOUT_EXPIRED, 500)); }); }); @@ -10003,7 +10036,7 @@ describe('lib/optimizely', function() { var readyPromise = optlyInstance.onReady(); clock.tick(300001); return readyPromise.then(() => { - return Promise.reject(new Error('Promise should not have resolved')); + return Promise.reject(new Error(PROMISE_SHOULD_NOT_HAVE_RESOLVED)); }, (err) => { assert.equal(err.message, 'onReady timeout expired after 30000 ms') }); @@ -10027,7 +10060,7 @@ describe('lib/optimizely', function() { var readyPromise = optlyInstance.onReady({ timeout: 100 }); optlyInstance.close(); return readyPromise.then(() => { - return Promise.reject(new Error('Promise should not have resolved')); + return Promise.reject(new Error(PROMISE_SHOULD_NOT_HAVE_RESOLVED)); }, (err) => { assert.equal(err.message, 'Instance closed') }); diff --git a/lib/optimizely/index.ts b/lib/optimizely/index.ts index 4c4898c91..34fa116f6 100644 --- a/lib/optimizely/index.ts +++ b/lib/optimizely/index.ts @@ -53,9 +53,7 @@ import * as stringValidator from '../utils/string_value_validator'; import * as decision from '../core/decision'; import { - ERROR_MESSAGES, LOG_LEVEL, - LOG_MESSAGES, DECISION_SOURCES, DECISION_MESSAGES, FEATURE_VARIABLE_TYPES, @@ -68,6 +66,37 @@ import { Fn } from '../utils/type'; import { resolvablePromise } from '../utils/promise/resolvablePromise'; import { NOTIFICATION_TYPES, DecisionNotificationType, DECISION_NOTIFICATION_TYPES } from '../notification_center/type'; +import { + FEATURE_NOT_IN_DATAFILE, + INVALID_EXPERIMENT_KEY, + INVALID_INPUT_FORMAT, + NO_EVENT_PROCESSOR, + ODP_EVENT_FAILED, + ODP_EVENT_FAILED_ODP_MANAGER_MISSING, + UNABLE_TO_GET_VUID_VUID_MANAGER_NOT_AVAILABLE, +} from '../error_messages'; +import { + EVENT_KEY_NOT_FOUND, + FEATURE_ENABLED_FOR_USER, + FEATURE_NOT_ENABLED_FOR_USER, + FEATURE_NOT_ENABLED_RETURN_DEFAULT_VARIABLE_VALUE, + INVALID_CLIENT_ENGINE, + INVALID_DECIDE_OPTIONS, + INVALID_DEFAULT_DECIDE_OPTIONS, + INVALID_OBJECT, + NOT_ACTIVATING_USER, + NOT_TRACKING_USER, + SHOULD_NOT_DISPATCH_ACTIVATE, + TRACK_EVENT, + UNRECOGNIZED_DECIDE_OPTION, + UPDATED_OPTIMIZELY_CONFIG, + USER_RECEIVED_DEFAULT_VARIABLE_VALUE, + USER_RECEIVED_VARIABLE_VALUE, + VALID_USER_PROFILE_SERVICE, + VARIABLE_NOT_USED_RETURN_DEFAULT_VARIABLE_VALUE, + VARIABLE_REQUESTED_WITH_WRONG_TYPE, +} from '../log_messages'; +import { INSTANCE_CLOSED } from '../exception_messages'; const MODULE_NAME = 'OPTIMIZELY'; @@ -103,7 +132,7 @@ export default class Optimizely implements Client { constructor(config: OptimizelyOptions) { let clientEngine = config.clientEngine; if (!clientEngine) { - config.logger.log(LOG_LEVEL.INFO, LOG_MESSAGES.INVALID_CLIENT_ENGINE, MODULE_NAME, clientEngine); + config.logger.log(LOG_LEVEL.INFO, INVALID_CLIENT_ENGINE, MODULE_NAME, clientEngine); clientEngine = NODE_CLIENT_ENGINE; } @@ -117,7 +146,7 @@ export default class Optimizely implements Client { let decideOptionsArray = config.defaultDecideOptions ?? []; if (!Array.isArray(decideOptionsArray)) { - this.logger.log(LOG_LEVEL.DEBUG, LOG_MESSAGES.INVALID_DEFAULT_DECIDE_OPTIONS, MODULE_NAME); + this.logger.log(LOG_LEVEL.DEBUG, INVALID_DEFAULT_DECIDE_OPTIONS, MODULE_NAME); decideOptionsArray = []; } @@ -127,7 +156,7 @@ export default class Optimizely implements Client { if (OptimizelyDecideOption[option]) { defaultDecideOptions[option] = true; } else { - this.logger.log(LOG_LEVEL.WARNING, LOG_MESSAGES.UNRECOGNIZED_DECIDE_OPTION, MODULE_NAME, option); + this.logger.log(LOG_LEVEL.WARNING, UNRECOGNIZED_DECIDE_OPTION, MODULE_NAME, option); } }); this.defaultDecideOptions = defaultDecideOptions; @@ -136,7 +165,7 @@ export default class Optimizely implements Client { this.disposeOnUpdate = this.projectConfigManager.onUpdate((configObj: projectConfig.ProjectConfig) => { this.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.UPDATED_OPTIMIZELY_CONFIG, + UPDATED_OPTIMIZELY_CONFIG, MODULE_NAME, configObj.revision, configObj.projectId @@ -156,7 +185,7 @@ export default class Optimizely implements Client { try { if (userProfileServiceValidator.validate(config.userProfileService)) { userProfileService = config.userProfileService; - this.logger.log(LOG_LEVEL.INFO, LOG_MESSAGES.VALID_USER_PROFILE_SERVICE, MODULE_NAME); + this.logger.log(LOG_LEVEL.INFO, VALID_USER_PROFILE_SERVICE, MODULE_NAME); } } catch (ex) { this.logger.log(LOG_LEVEL.WARNING, ex.message); @@ -227,7 +256,7 @@ export default class Optimizely implements Client { activate(experimentKey: string, userId: string, attributes?: UserAttributes): string | null { try { if (!this.isValidInstance()) { - this.logger.log(LOG_LEVEL.ERROR, LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'activate'); + this.logger.log(LOG_LEVEL.ERROR, INVALID_OBJECT, MODULE_NAME, 'activate'); return null; } @@ -248,7 +277,7 @@ export default class Optimizely implements Client { // If experiment is not set to 'Running' status, log accordingly and return variation key if (!projectConfig.isRunning(configObj, experimentKey)) { - this.logger.log(LOG_LEVEL.DEBUG, LOG_MESSAGES.SHOULD_NOT_DISPATCH_ACTIVATE, MODULE_NAME, experimentKey); + this.logger.log(LOG_LEVEL.DEBUG, SHOULD_NOT_DISPATCH_ACTIVATE, MODULE_NAME, experimentKey); return variationKey; } @@ -264,7 +293,7 @@ export default class Optimizely implements Client { return variationKey; } catch (ex) { this.logger.log(LOG_LEVEL.ERROR, ex.message); - this.logger.log(LOG_LEVEL.INFO, LOG_MESSAGES.NOT_ACTIVATING_USER, MODULE_NAME, userId, experimentKey); + this.logger.log(LOG_LEVEL.INFO, NOT_ACTIVATING_USER, MODULE_NAME, userId, experimentKey); this.errorHandler.handleError(ex); return null; } @@ -293,7 +322,7 @@ export default class Optimizely implements Client { attributes?: UserAttributes ): void { if (!this.eventProcessor) { - this.logger.error(ERROR_MESSAGES.NO_EVENT_PROCESSOR); + this.logger.error(NO_EVENT_PROCESSOR); return; } @@ -334,12 +363,12 @@ export default class Optimizely implements Client { track(eventKey: string, userId: string, attributes?: UserAttributes, eventTags?: EventTags): void { try { if (!this.eventProcessor) { - this.logger.error(ERROR_MESSAGES.NO_EVENT_PROCESSOR); + this.logger.error(NO_EVENT_PROCESSOR); return; } if (!this.isValidInstance()) { - this.logger.log(LOG_LEVEL.ERROR, LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'track'); + this.logger.log(LOG_LEVEL.ERROR, INVALID_OBJECT, MODULE_NAME, 'track'); return; } @@ -353,8 +382,8 @@ export default class Optimizely implements Client { } if (!projectConfig.eventWithKeyExists(configObj, eventKey)) { - this.logger.log(LOG_LEVEL.WARNING, LOG_MESSAGES.EVENT_KEY_NOT_FOUND, MODULE_NAME, eventKey); - this.logger.log(LOG_LEVEL.WARNING, LOG_MESSAGES.NOT_TRACKING_USER, MODULE_NAME, userId); + this.logger.log(LOG_LEVEL.WARNING, EVENT_KEY_NOT_FOUND, MODULE_NAME, eventKey); + this.logger.log(LOG_LEVEL.WARNING, NOT_TRACKING_USER, MODULE_NAME, userId); return; } @@ -369,7 +398,7 @@ export default class Optimizely implements Client { clientVersion: this.clientVersion, configObj: configObj, }); - this.logger.log(LOG_LEVEL.INFO, LOG_MESSAGES.TRACK_EVENT, MODULE_NAME, eventKey, userId); + this.logger.log(LOG_LEVEL.INFO, TRACK_EVENT, MODULE_NAME, eventKey, userId); // TODO is it okay to not pass a projectConfig as second argument this.eventProcessor.process(conversionEvent); @@ -384,7 +413,7 @@ export default class Optimizely implements Client { } catch (e) { this.logger.log(LOG_LEVEL.ERROR, e.message); this.errorHandler.handleError(e); - this.logger.log(LOG_LEVEL.ERROR, LOG_MESSAGES.NOT_TRACKING_USER, MODULE_NAME, userId); + this.logger.log(LOG_LEVEL.ERROR, NOT_TRACKING_USER, MODULE_NAME, userId); } } @@ -398,7 +427,7 @@ export default class Optimizely implements Client { getVariation(experimentKey: string, userId: string, attributes?: UserAttributes): string | null { try { if (!this.isValidInstance()) { - this.logger.log(LOG_LEVEL.ERROR, LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'getVariation'); + this.logger.log(LOG_LEVEL.ERROR, INVALID_OBJECT, MODULE_NAME, 'getVariation'); return null; } @@ -414,7 +443,7 @@ export default class Optimizely implements Client { const experiment = configObj.experimentKeyMap[experimentKey]; if (!experiment || experiment.isRollout) { - this.logger.log(LOG_LEVEL.DEBUG, ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey); + this.logger.log(LOG_LEVEL.DEBUG, INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey); return null; } @@ -515,14 +544,14 @@ export default class Optimizely implements Client { if (stringInputs.hasOwnProperty('user_id')) { const userId = stringInputs['user_id']; if (typeof userId !== 'string' || userId === null || userId === 'undefined') { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, MODULE_NAME, 'user_id')); + throw new Error(sprintf(INVALID_INPUT_FORMAT, MODULE_NAME, 'user_id')); } delete stringInputs['user_id']; } Object.keys(stringInputs).forEach(key => { if (!stringValidator.validate(stringInputs[key as InputKey])) { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, MODULE_NAME, key)); + throw new Error(sprintf(INVALID_INPUT_FORMAT, MODULE_NAME, key)); } }); if (userAttributes) { @@ -546,7 +575,7 @@ export default class Optimizely implements Client { * @return {null} */ private notActivatingExperiment(experimentKey: string, userId: string): null { - this.logger.log(LOG_LEVEL.INFO, LOG_MESSAGES.NOT_ACTIVATING_USER, MODULE_NAME, userId, experimentKey); + this.logger.log(LOG_LEVEL.INFO, NOT_ACTIVATING_USER, MODULE_NAME, userId, experimentKey); return null; } @@ -574,7 +603,7 @@ export default class Optimizely implements Client { isFeatureEnabled(featureKey: string, userId: string, attributes?: UserAttributes): boolean { try { if (!this.isValidInstance()) { - this.logger.log(LOG_LEVEL.ERROR, LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'isFeatureEnabled'); + this.logger.log(LOG_LEVEL.ERROR, INVALID_OBJECT, MODULE_NAME, 'isFeatureEnabled'); return false; } @@ -616,9 +645,9 @@ export default class Optimizely implements Client { } if (featureEnabled === true) { - this.logger.log(LOG_LEVEL.INFO, LOG_MESSAGES.FEATURE_ENABLED_FOR_USER, MODULE_NAME, featureKey, userId); + this.logger.log(LOG_LEVEL.INFO, FEATURE_ENABLED_FOR_USER, MODULE_NAME, featureKey, userId); } else { - this.logger.log(LOG_LEVEL.INFO, LOG_MESSAGES.FEATURE_NOT_ENABLED_FOR_USER, MODULE_NAME, featureKey, userId); + this.logger.log(LOG_LEVEL.INFO, FEATURE_NOT_ENABLED_FOR_USER, MODULE_NAME, featureKey, userId); featureEnabled = false; } @@ -655,7 +684,7 @@ export default class Optimizely implements Client { try { const enabledFeatures: string[] = []; if (!this.isValidInstance()) { - this.logger.log(LOG_LEVEL.ERROR, LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'getEnabledFeatures'); + this.logger.log(LOG_LEVEL.ERROR, INVALID_OBJECT, MODULE_NAME, 'getEnabledFeatures'); return enabledFeatures; } @@ -704,7 +733,7 @@ export default class Optimizely implements Client { ): FeatureVariableValue { try { if (!this.isValidInstance()) { - this.logger.log(LOG_LEVEL.ERROR, LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'getFeatureVariable'); + this.logger.log(LOG_LEVEL.ERROR, INVALID_OBJECT, MODULE_NAME, 'getFeatureVariable'); return null; } return this.getFeatureVariableForType(featureKey, variableKey, null, userId, attributes); @@ -766,7 +795,7 @@ export default class Optimizely implements Client { if (variableType && variable.type !== variableType) { this.logger.log( LOG_LEVEL.WARNING, - LOG_MESSAGES.VARIABLE_REQUESTED_WITH_WRONG_TYPE, + VARIABLE_REQUESTED_WITH_WRONG_TYPE, MODULE_NAME, variableType, variable.type @@ -849,7 +878,7 @@ export default class Optimizely implements Client { variableValue = value; this.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.USER_RECEIVED_VARIABLE_VALUE, + USER_RECEIVED_VARIABLE_VALUE, MODULE_NAME, variableValue, variable.key, @@ -858,7 +887,7 @@ export default class Optimizely implements Client { } else { this.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.FEATURE_NOT_ENABLED_RETURN_DEFAULT_VARIABLE_VALUE, + FEATURE_NOT_ENABLED_RETURN_DEFAULT_VARIABLE_VALUE, MODULE_NAME, featureKey, userId, @@ -868,7 +897,7 @@ export default class Optimizely implements Client { } else { this.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.VARIABLE_NOT_USED_RETURN_DEFAULT_VARIABLE_VALUE, + VARIABLE_NOT_USED_RETURN_DEFAULT_VARIABLE_VALUE, MODULE_NAME, variable.key, variation.key @@ -877,7 +906,7 @@ export default class Optimizely implements Client { } else { this.logger.log( LOG_LEVEL.INFO, - LOG_MESSAGES.USER_RECEIVED_DEFAULT_VARIABLE_VALUE, + USER_RECEIVED_DEFAULT_VARIABLE_VALUE, MODULE_NAME, userId, variable.key, @@ -909,7 +938,7 @@ export default class Optimizely implements Client { ): boolean | null { try { if (!this.isValidInstance()) { - this.logger.log(LOG_LEVEL.ERROR, LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'getFeatureVariableBoolean'); + this.logger.log(LOG_LEVEL.ERROR, INVALID_OBJECT, MODULE_NAME, 'getFeatureVariableBoolean'); return null; } return this.getFeatureVariableForType( @@ -948,7 +977,7 @@ export default class Optimizely implements Client { ): number | null { try { if (!this.isValidInstance()) { - this.logger.log(LOG_LEVEL.ERROR, LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'getFeatureVariableDouble'); + this.logger.log(LOG_LEVEL.ERROR, INVALID_OBJECT, MODULE_NAME, 'getFeatureVariableDouble'); return null; } return this.getFeatureVariableForType( @@ -987,7 +1016,7 @@ export default class Optimizely implements Client { ): number | null { try { if (!this.isValidInstance()) { - this.logger.log(LOG_LEVEL.ERROR, LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'getFeatureVariableInteger'); + this.logger.log(LOG_LEVEL.ERROR, INVALID_OBJECT, MODULE_NAME, 'getFeatureVariableInteger'); return null; } return this.getFeatureVariableForType( @@ -1026,7 +1055,7 @@ export default class Optimizely implements Client { ): string | null { try { if (!this.isValidInstance()) { - this.logger.log(LOG_LEVEL.ERROR, LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'getFeatureVariableString'); + this.logger.log(LOG_LEVEL.ERROR, INVALID_OBJECT, MODULE_NAME, 'getFeatureVariableString'); return null; } return this.getFeatureVariableForType( @@ -1060,7 +1089,7 @@ export default class Optimizely implements Client { getFeatureVariableJSON(featureKey: string, variableKey: string, userId: string, attributes: UserAttributes): unknown { try { if (!this.isValidInstance()) { - this.logger.log(LOG_LEVEL.ERROR, LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'getFeatureVariableJSON'); + this.logger.log(LOG_LEVEL.ERROR, INVALID_OBJECT, MODULE_NAME, 'getFeatureVariableJSON'); return null; } return this.getFeatureVariableForType(featureKey, variableKey, FEATURE_VARIABLE_TYPES.JSON, userId, attributes); @@ -1088,7 +1117,7 @@ export default class Optimizely implements Client { ): { [variableKey: string]: unknown } | null { try { if (!this.isValidInstance()) { - this.logger.log(LOG_LEVEL.ERROR, LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'getAllFeatureVariables'); + this.logger.log(LOG_LEVEL.ERROR, INVALID_OBJECT, MODULE_NAME, 'getAllFeatureVariables'); return null; } @@ -1330,7 +1359,7 @@ export default class Optimizely implements Client { const readyTimeout = setTimeout(onReadyTimeout, timeoutValue); const onClose = function() { - timeoutPromise.reject(new Error('Instance closed')); + timeoutPromise.reject(new Error(INSTANCE_CLOSED)); }; this.readyTimeouts[timeoutId] = { @@ -1398,7 +1427,7 @@ export default class Optimizely implements Client { const configObj = this.projectConfigManager.getConfig(); if (!this.isValidInstance() || !configObj) { - this.logger.log(LOG_LEVEL.INFO, LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'decide'); + this.logger.log(LOG_LEVEL.INFO, INVALID_OBJECT, MODULE_NAME, 'decide'); return newErrorDecision(key, user, [DECISION_MESSAGES.SDK_NOT_READY]); } @@ -1413,14 +1442,14 @@ export default class Optimizely implements Client { private getAllDecideOptions(options: OptimizelyDecideOption[]): { [key: string]: boolean } { const allDecideOptions = { ...this.defaultDecideOptions }; if (!Array.isArray(options)) { - this.logger.log(LOG_LEVEL.DEBUG, LOG_MESSAGES.INVALID_DECIDE_OPTIONS, MODULE_NAME); + this.logger.log(LOG_LEVEL.DEBUG, INVALID_DECIDE_OPTIONS, MODULE_NAME); } else { options.forEach(option => { // Filter out all provided decide options that are not in OptimizelyDecideOption[] if (OptimizelyDecideOption[option]) { allDecideOptions[option] = true; } else { - this.logger.log(LOG_LEVEL.WARNING, LOG_MESSAGES.UNRECOGNIZED_DECIDE_OPTION, MODULE_NAME, option); + this.logger.log(LOG_LEVEL.WARNING, UNRECOGNIZED_DECIDE_OPTION, MODULE_NAME, option); } }); } @@ -1458,9 +1487,9 @@ export default class Optimizely implements Client { let decisionEventDispatched = false; if (flagEnabled) { - this.logger.log(LOG_LEVEL.INFO, LOG_MESSAGES.FEATURE_ENABLED_FOR_USER, MODULE_NAME, key, userId); + this.logger.log(LOG_LEVEL.INFO, FEATURE_ENABLED_FOR_USER, MODULE_NAME, key, userId); } else { - this.logger.log(LOG_LEVEL.INFO, LOG_MESSAGES.FEATURE_NOT_ENABLED_FOR_USER, MODULE_NAME, key, userId); + this.logger.log(LOG_LEVEL.INFO, FEATURE_NOT_ENABLED_FOR_USER, MODULE_NAME, key, userId); } @@ -1544,7 +1573,7 @@ export default class Optimizely implements Client { const configObj = this.projectConfigManager.getConfig() if (!this.isValidInstance() || !configObj) { - this.logger.log(LOG_LEVEL.ERROR, LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'decideForKeys'); + this.logger.log(LOG_LEVEL.ERROR, INVALID_OBJECT, MODULE_NAME, 'decideForKeys'); return decisionMap; } if (keys.length === 0) { @@ -1560,7 +1589,7 @@ export default class Optimizely implements Client { for(const key of keys) { const feature = configObj.featureKeyMap[key]; if (!feature) { - this.logger.log(LOG_LEVEL.ERROR, ERROR_MESSAGES.FEATURE_NOT_IN_DATAFILE, MODULE_NAME, key); + this.logger.log(LOG_LEVEL.ERROR, FEATURE_NOT_IN_DATAFILE, MODULE_NAME, key); decisionMap[key] = newErrorDecision(key, user, [sprintf(DECISION_MESSAGES.FLAG_KEY_INVALID, key)]); continue } @@ -1614,7 +1643,7 @@ export default class Optimizely implements Client { const configObj = this.projectConfigManager.getConfig(); const decisionMap: { [key: string]: OptimizelyDecision } = {}; if (!this.isValidInstance() || !configObj) { - this.logger.log(LOG_LEVEL.ERROR, LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'decideAll'); + this.logger.log(LOG_LEVEL.ERROR, INVALID_OBJECT, MODULE_NAME, 'decideAll'); return decisionMap; } @@ -1653,7 +1682,7 @@ export default class Optimizely implements Client { data?: Map ): void { if (!this.odpManager) { - this.logger.error(ERROR_MESSAGES.ODP_EVENT_FAILED_ODP_MANAGER_MISSING); + this.logger.error(ODP_EVENT_FAILED_ODP_MANAGER_MISSING); return; } @@ -1661,7 +1690,7 @@ export default class Optimizely implements Client { const odpEvent = new OdpEvent(type || '', action, identifiers, data); this.odpManager.sendEvent(odpEvent); } catch (e) { - this.logger.error(ERROR_MESSAGES.ODP_EVENT_FAILED, e); + this.logger.error(ODP_EVENT_FAILED, e); } } /** @@ -1706,7 +1735,7 @@ export default class Optimizely implements Client { */ public getVuid(): string | undefined { if (!this.vuidManager) { - this.logger?.error('Unable to get VUID - VuidManager is not available'); + this.logger?.error(UNABLE_TO_GET_VUID_VUID_MANAGER_NOT_AVAILABLE); return undefined; } diff --git a/lib/optimizely_user_context/index.tests.js b/lib/optimizely_user_context/index.tests.js index fc72ffe0e..fbc9eb29b 100644 --- a/lib/optimizely_user_context/index.tests.js +++ b/lib/optimizely_user_context/index.tests.js @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - import { assert } from 'chai'; import sinon from 'sinon'; @@ -26,13 +25,19 @@ import { createLogger } from '../plugins/logger'; import { createNotificationCenter } from '../notification_center'; import Optimizely from '../optimizely'; import errorHandler from '../plugins/error_handler'; -import { CONTROL_ATTRIBUTES, LOG_LEVEL, LOG_MESSAGES } from '../utils/enums'; +import { CONTROL_ATTRIBUTES, LOG_LEVEL } from '../utils/enums'; import testData from '../tests/test_data'; import { OptimizelyDecideOption } from '../shared_types'; import { getMockProjectConfigManager } from '../tests/mock/mock_project_config_manager'; import { createProjectConfig } from '../project_config/project_config'; import { getForwardingEventProcessor } from '../event_processor/forwarding_event_processor'; import * as logger from '../plugins/logger'; +import { + USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED, + USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED_BUT_INVALID, + USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED, + USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED_BUT_INVALID, +} from '../log_messages'; const getMockEventDispatcher = () => { const dispatcher = { @@ -461,7 +466,7 @@ describe('lib/optimizely_user_context', function() { assert.equal( true, decision.reasons.includes( - sprintf(LOG_MESSAGES.USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED, variationKey, featureKey, userId) + sprintf(USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED, variationKey, featureKey, userId) ) ); @@ -487,7 +492,7 @@ describe('lib/optimizely_user_context', function() { assert.equal( true, decision.reasons.includes( - sprintf(LOG_MESSAGES.USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED, variationKey, featureKey, userId) + sprintf(USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED, variationKey, featureKey, userId) ) ); @@ -518,7 +523,7 @@ describe('lib/optimizely_user_context', function() { assert.equal( true, decision.reasons.includes( - sprintf(LOG_MESSAGES.USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED, variationKey, featureKey, userId) + sprintf(USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED, variationKey, featureKey, userId) ) ); @@ -561,7 +566,7 @@ describe('lib/optimizely_user_context', function() { decisionEventDispatched: true, reasons: [ sprintf( - LOG_MESSAGES.USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED, + USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED, variationKey, featureKey, userId @@ -597,7 +602,7 @@ describe('lib/optimizely_user_context', function() { true, decision.reasons.includes( sprintf( - LOG_MESSAGES.USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED, + USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED, variationKey, featureKey, ruleKey, @@ -645,7 +650,7 @@ describe('lib/optimizely_user_context', function() { decisionEventDispatched: true, reasons: [ sprintf( - LOG_MESSAGES.USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED, + USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED, variationKey, featureKey, ruleKey, @@ -778,7 +783,7 @@ describe('lib/optimizely_user_context', function() { assert.equal( true, decision.reasons.includes( - sprintf(LOG_MESSAGES.USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED_BUT_INVALID, featureKey, userId) + sprintf(USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED_BUT_INVALID, featureKey, userId) ) ); }); @@ -801,7 +806,7 @@ describe('lib/optimizely_user_context', function() { true, decision.reasons.includes( sprintf( - LOG_MESSAGES.USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED_BUT_INVALID, + USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED_BUT_INVALID, featureKey, ruleKey, userId @@ -828,7 +833,7 @@ describe('lib/optimizely_user_context', function() { true, decision.reasons.includes( sprintf( - LOG_MESSAGES.USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED_BUT_INVALID, + USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED_BUT_INVALID, featureKey, ruleKey, userId diff --git a/lib/project_config/config_manager_factory.react_native.spec.ts b/lib/project_config/config_manager_factory.react_native.spec.ts index e688c588a..6550fa0c6 100644 --- a/lib/project_config/config_manager_factory.react_native.spec.ts +++ b/lib/project_config/config_manager_factory.react_native.spec.ts @@ -30,7 +30,7 @@ async function mockRequireAsyncStorage() { M._load = (uri: string, parent: string) => { if (uri === '@react-native-async-storage/async-storage') { if (isAsyncStorageAvailable) return { default: {} }; - throw new Error('Module not found: @react-native-async-storage/async-storage'); + throw new Error("Module not found: @react-native-async-storage/async-storage"); } return M._load_original(uri, parent); }; @@ -157,7 +157,7 @@ describe('createPollingConfigManager', () => { }; expect(() => createPollingProjectConfigManager(config)).toThrowError( - 'Module not found: @react-native-async-storage/async-storage' + "Module not found: @react-native-async-storage/async-storage" ); isAsyncStorageAvailable = true; }); diff --git a/lib/project_config/polling_datafile_manager.ts b/lib/project_config/polling_datafile_manager.ts index f7223fc00..bde704029 100644 --- a/lib/project_config/polling_datafile_manager.ts +++ b/lib/project_config/polling_datafile_manager.ts @@ -23,6 +23,14 @@ import { RequestHandler, AbortableRequest, Headers, Response } from '../utils/ht import { Repeater } from '../utils/repeater/repeater'; import { Consumer, Fn } from '../utils/type'; import { isSuccessStatusCode } from '../utils/http_request_handler/http_util'; +import { DATAFILE_MANAGER_STOPPED, FAILED_TO_FETCH_DATAFILE } from '../exception_messages'; +import { DATAFILE_FETCH_REQUEST_FAILED, ERROR_FETCHING_DATAFILE } from '../error_messages'; +import { + ADDING_AUTHORIZATION_HEADER_WITH_BEARER_TOKEN, + MAKING_DATAFILE_REQ_TO_URL_WITH_HEADERS, + RESPONSE_STATUS_CODE, + SAVED_LAST_MODIFIED_HEADER_VALUE_FROM_RESPONSE, +} from '../log_messages'; export class PollingDatafileManager extends BaseService implements DatafileManager { private requestHandler: RequestHandler; @@ -94,11 +102,10 @@ export class PollingDatafileManager extends BaseService implements DatafileManag } if (this.isNew() || this.isStarting()) { - // TOOD: replace message with imported constants - this.startPromise.reject(new Error('Datafile manager stopped before it could be started')); + this.startPromise.reject(new Error(DATAFILE_MANAGER_STOPPED)); } - - this.logger?.debug('Datafile manager stopped'); + + this.logger?.debug(DATAFILE_MANAGER_STOPPED); this.state = ServiceState.Terminated; this.repeater.stop(); this.currentRequest?.abort(); @@ -109,8 +116,7 @@ export class PollingDatafileManager extends BaseService implements DatafileManag private handleInitFailure(): void { this.state = ServiceState.Failed; this.repeater.stop(); - // TODO: replace message with imported constants - const error = new Error('Failed to fetch datafile'); + const error = new Error(FAILED_TO_FETCH_DATAFILE); this.startPromise.reject(error); this.stopPromise.reject(error); } @@ -120,11 +126,10 @@ export class PollingDatafileManager extends BaseService implements DatafileManag return; } - // TODO: replace message with imported constants if (errorOrStatus instanceof Error) { - this.logger?.error('Error fetching datafile: %s', errorOrStatus.message, errorOrStatus); + this.logger?.error(ERROR_FETCHING_DATAFILE, errorOrStatus.message, errorOrStatus); } else { - this.logger?.error(`Datafile fetch request failed with status: ${errorOrStatus}`); + this.logger?.error(DATAFILE_FETCH_REQUEST_FAILED, errorOrStatus); } if(this.isStarting() && this.initRetryRemaining !== undefined) { @@ -170,11 +175,11 @@ export class PollingDatafileManager extends BaseService implements DatafileManag } if (this.datafileAccessToken) { - this.logger?.debug('Adding Authorization header with Bearer Token'); + this.logger?.debug(ADDING_AUTHORIZATION_HEADER_WITH_BEARER_TOKEN); headers['Authorization'] = `Bearer ${this.datafileAccessToken}`; } - this.logger?.debug('Making datafile request to url %s with headers: %s', this.datafileUrl, () => JSON.stringify(headers)); + this.logger?.debug(MAKING_DATAFILE_REQ_TO_URL_WITH_HEADERS, this.datafileUrl, () => JSON.stringify(headers)); return this.requestHandler.makeRequest(this.datafileUrl, headers, 'GET'); } @@ -201,7 +206,7 @@ export class PollingDatafileManager extends BaseService implements DatafileManag } private getDatafileFromResponse(response: Response): string | undefined{ - this.logger?.debug('Response status code: %s', response.statusCode); + this.logger?.debug(RESPONSE_STATUS_CODE, response.statusCode); if (response.statusCode === 304) { return undefined; } @@ -212,7 +217,7 @@ export class PollingDatafileManager extends BaseService implements DatafileManag const lastModifiedHeader = headers['last-modified'] || headers['Last-Modified']; if (lastModifiedHeader !== undefined) { this.lastResponseLastModified = lastModifiedHeader; - this.logger?.debug('Saved last modified header value from response: %s', this.lastResponseLastModified); + this.logger?.debug(SAVED_LAST_MODIFIED_HEADER_VALUE_FROM_RESPONSE, this.lastResponseLastModified); } } diff --git a/lib/project_config/project_config.tests.js b/lib/project_config/project_config.tests.js index c49a75dad..6bfc34d67 100644 --- a/lib/project_config/project_config.tests.js +++ b/lib/project_config/project_config.tests.js @@ -21,10 +21,11 @@ import { getLogger } from '../modules/logging'; import fns from '../utils/fns'; import projectConfig from './project_config'; -import { ERROR_MESSAGES, FEATURE_VARIABLE_TYPES, LOG_LEVEL } from '../utils/enums'; +import { FEATURE_VARIABLE_TYPES, LOG_LEVEL } from '../utils/enums'; import * as loggerPlugin from '../plugins/logger'; import testDatafile from '../tests/test_data'; import configValidator from '../utils/config_validator'; +import { INVALID_EXPERIMENT_ID, INVALID_EXPERIMENT_KEY } from '../error_messages'; var buildLogMessageFromArgs = args => sprintf(args[1], ...args.splice(2)); var logger = getLogger(); @@ -300,7 +301,7 @@ describe('lib/core/project_config', function() { it('should throw error for invalid experiment key in getExperimentId', function() { assert.throws(function() { projectConfig.getExperimentId(configObj, 'invalidExperimentKey'); - }, sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, 'PROJECT_CONFIG', 'invalidExperimentKey')); + }, sprintf(INVALID_EXPERIMENT_KEY, 'PROJECT_CONFIG', 'invalidExperimentKey')); }); it('should retrieve layer ID for valid experiment key in getLayerId', function() { @@ -310,7 +311,7 @@ describe('lib/core/project_config', function() { it('should throw error for invalid experiment key in getLayerId', function() { assert.throws(function() { projectConfig.getLayerId(configObj, 'invalidExperimentKey'); - }, sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_ID, 'PROJECT_CONFIG', 'invalidExperimentKey')); + }, sprintf(INVALID_EXPERIMENT_ID, 'PROJECT_CONFIG', 'invalidExperimentKey')); }); it('should retrieve attribute ID for valid attribute key in getAttributeId', function() { @@ -360,7 +361,7 @@ describe('lib/core/project_config', function() { it('should throw error for invalid experiment key in getExperimentStatus', function() { assert.throws(function() { projectConfig.getExperimentStatus(configObj, 'invalidExperimentKey'); - }, sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, 'PROJECT_CONFIG', 'invalidExperimentKey')); + }, sprintf(INVALID_EXPERIMENT_KEY, 'PROJECT_CONFIG', 'invalidExperimentKey')); }); it('should return true if experiment status is set to Running in isActive', function() { @@ -396,7 +397,7 @@ describe('lib/core/project_config', function() { it('should throw error for invalid experient key in getTrafficAllocation', function() { assert.throws(function() { projectConfig.getTrafficAllocation(configObj, 'invalidExperimentId'); - }, sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_ID, 'PROJECT_CONFIG', 'invalidExperimentId')); + }, sprintf(INVALID_EXPERIMENT_ID, 'PROJECT_CONFIG', 'invalidExperimentId')); }); describe('#getVariationIdFromExperimentAndVariationKey', function() { @@ -684,7 +685,7 @@ describe('lib/core/project_config', function() { configObj = projectConfig.createProjectConfig(cloneDeep(testData)); assert.throws(function() { projectConfig.getExperimentAudienceConditions(configObj, 'invalidExperimentId'); - }, sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_ID, 'PROJECT_CONFIG', 'invalidExperimentId')); + }, sprintf(INVALID_EXPERIMENT_ID, 'PROJECT_CONFIG', 'invalidExperimentId')); }); it('should return experiment audienceIds if experiment has no audienceConditions', function() { diff --git a/lib/project_config/project_config.ts b/lib/project_config/project_config.ts index a9b618894..781470ab2 100644 --- a/lib/project_config/project_config.ts +++ b/lib/project_config/project_config.ts @@ -15,7 +15,7 @@ */ import { find, objectEntries, objectValues, sprintf, keyBy } from '../utils/fns'; -import { ERROR_MESSAGES, LOG_LEVEL, LOG_MESSAGES, FEATURE_VARIABLE_TYPES } from '../utils/enums'; +import { LOG_LEVEL, FEATURE_VARIABLE_TYPES } from '../utils/enums'; import configValidator from '../utils/config_validator'; import { LogHandler } from '../modules/logging'; @@ -36,6 +36,18 @@ import { } from '../shared_types'; import { OdpConfig, OdpIntegrationConfig } from '../odp/odp_config'; import { Transformer } from '../utils/type'; +import { + EXPERIMENT_KEY_NOT_IN_DATAFILE, + FEATURE_NOT_IN_DATAFILE, + INVALID_EXPERIMENT_ID, + INVALID_EXPERIMENT_KEY, + MISSING_INTEGRATION_KEY, + UNABLE_TO_CAST_VALUE, + UNRECOGNIZED_ATTRIBUTE, + VARIABLE_KEY_NOT_IN_DATAFILE, + VARIATION_ID_NOT_IN_DATAFILE_NO_EXPERIMENT, +} from '../error_messages'; +import { SKIPPING_JSON_VALIDATION, VALID_DATAFILE } from '../log_messages'; interface TryCreatingProjectConfigConfig { // TODO[OASIS-6649]: Don't use object type @@ -199,7 +211,7 @@ export const createProjectConfig = function(datafileObj?: JSON, datafileStr: str projectConfig.integrations.forEach(integration => { if (!('key' in integration)) { - throw new Error(sprintf(ERROR_MESSAGES.MISSING_INTEGRATION_KEY, MODULE_NAME)); + throw new Error(sprintf(MISSING_INTEGRATION_KEY, MODULE_NAME)); } if (integration.key === 'odp') { @@ -347,7 +359,7 @@ function isLogicalOperator(condition: string): boolean { export const getExperimentId = function(projectConfig: ProjectConfig, experimentKey: string): string { const experiment = projectConfig.experimentKeyMap[experimentKey]; if (!experiment) { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); + throw new Error(sprintf(INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); } return experiment.id; }; @@ -362,7 +374,7 @@ export const getExperimentId = function(projectConfig: ProjectConfig, experiment export const getLayerId = function(projectConfig: ProjectConfig, experimentId: string): string { const experiment = projectConfig.experimentIdMap[experimentId]; if (!experiment) { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_ID, MODULE_NAME, experimentId)); + throw new Error(sprintf(INVALID_EXPERIMENT_ID, MODULE_NAME, experimentId)); } return experiment.layerId; }; @@ -395,7 +407,7 @@ export const getAttributeId = function( return attributeKey; } - logger.log(LOG_LEVEL.DEBUG, ERROR_MESSAGES.UNRECOGNIZED_ATTRIBUTE, MODULE_NAME, attributeKey); + logger.log(LOG_LEVEL.DEBUG, UNRECOGNIZED_ATTRIBUTE, MODULE_NAME, attributeKey); return null; }; @@ -423,7 +435,7 @@ export const getEventId = function(projectConfig: ProjectConfig, eventKey: strin export const getExperimentStatus = function(projectConfig: ProjectConfig, experimentKey: string): string { const experiment = projectConfig.experimentKeyMap[experimentKey]; if (!experiment) { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); + throw new Error(sprintf(INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); } return experiment.status; }; @@ -465,7 +477,7 @@ export const getExperimentAudienceConditions = function( ): Array { const experiment = projectConfig.experimentIdMap[experimentId]; if (!experiment) { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_ID, MODULE_NAME, experimentId)); + throw new Error(sprintf(INVALID_EXPERIMENT_ID, MODULE_NAME, experimentId)); } return experiment.audienceConditions || experiment.audienceIds; @@ -534,7 +546,7 @@ export const getExperimentFromKey = function(projectConfig: ProjectConfig, exper } } - throw new Error(sprintf(ERROR_MESSAGES.EXPERIMENT_KEY_NOT_IN_DATAFILE, MODULE_NAME, experimentKey)); + throw new Error(sprintf(EXPERIMENT_KEY_NOT_IN_DATAFILE, MODULE_NAME, experimentKey)); }; /** @@ -547,7 +559,7 @@ export const getExperimentFromKey = function(projectConfig: ProjectConfig, exper export const getTrafficAllocation = function(projectConfig: ProjectConfig, experimentId: string): TrafficAllocation[] { const experiment = projectConfig.experimentIdMap[experimentId]; if (!experiment) { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_ID, MODULE_NAME, experimentId)); + throw new Error(sprintf(INVALID_EXPERIMENT_ID, MODULE_NAME, experimentId)); } return experiment.trafficAllocation; }; @@ -572,7 +584,7 @@ export const getExperimentFromId = function( } } - logger.log(LOG_LEVEL.ERROR, ERROR_MESSAGES.INVALID_EXPERIMENT_ID, MODULE_NAME, experimentId); + logger.log(LOG_LEVEL.ERROR, INVALID_EXPERIMENT_ID, MODULE_NAME, experimentId); return null; }; @@ -621,7 +633,7 @@ export const getFeatureFromKey = function( } } - logger.log(LOG_LEVEL.ERROR, ERROR_MESSAGES.FEATURE_NOT_IN_DATAFILE, MODULE_NAME, featureKey); + logger.log(LOG_LEVEL.ERROR, FEATURE_NOT_IN_DATAFILE, MODULE_NAME, featureKey); return null; }; @@ -644,13 +656,13 @@ export const getVariableForFeature = function( ): FeatureVariable | null { const feature = projectConfig.featureKeyMap[featureKey]; if (!feature) { - logger.log(LOG_LEVEL.ERROR, ERROR_MESSAGES.FEATURE_NOT_IN_DATAFILE, MODULE_NAME, featureKey); + logger.log(LOG_LEVEL.ERROR, FEATURE_NOT_IN_DATAFILE, MODULE_NAME, featureKey); return null; } const variable = feature.variableKeyMap[variableKey]; if (!variable) { - logger.log(LOG_LEVEL.ERROR, ERROR_MESSAGES.VARIABLE_KEY_NOT_IN_DATAFILE, MODULE_NAME, variableKey, featureKey); + logger.log(LOG_LEVEL.ERROR, VARIABLE_KEY_NOT_IN_DATAFILE, MODULE_NAME, variableKey, featureKey); return null; } @@ -680,7 +692,7 @@ export const getVariableValueForVariation = function( } if (!projectConfig.variationVariableUsageMap.hasOwnProperty(variation.id)) { - logger.log(LOG_LEVEL.ERROR, ERROR_MESSAGES.VARIATION_ID_NOT_IN_DATAFILE_NO_EXPERIMENT, MODULE_NAME, variation.id); + logger.log(LOG_LEVEL.ERROR, VARIATION_ID_NOT_IN_DATAFILE_NO_EXPERIMENT, MODULE_NAME, variation.id); return null; } @@ -716,7 +728,7 @@ export const getTypeCastValue = function( switch (variableType) { case FEATURE_VARIABLE_TYPES.BOOLEAN: if (variableValue !== 'true' && variableValue !== 'false') { - logger.log(LOG_LEVEL.ERROR, ERROR_MESSAGES.UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType); + logger.log(LOG_LEVEL.ERROR, UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType); castValue = null; } else { castValue = variableValue === 'true'; @@ -726,7 +738,7 @@ export const getTypeCastValue = function( case FEATURE_VARIABLE_TYPES.INTEGER: castValue = parseInt(variableValue, 10); if (isNaN(castValue)) { - logger.log(LOG_LEVEL.ERROR, ERROR_MESSAGES.UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType); + logger.log(LOG_LEVEL.ERROR, UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType); castValue = null; } break; @@ -734,7 +746,7 @@ export const getTypeCastValue = function( case FEATURE_VARIABLE_TYPES.DOUBLE: castValue = parseFloat(variableValue); if (isNaN(castValue)) { - logger.log(LOG_LEVEL.ERROR, ERROR_MESSAGES.UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType); + logger.log(LOG_LEVEL.ERROR, UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType); castValue = null; } break; @@ -743,7 +755,7 @@ export const getTypeCastValue = function( try { castValue = JSON.parse(variableValue); } catch (e) { - logger.log(LOG_LEVEL.ERROR, ERROR_MESSAGES.UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType); + logger.log(LOG_LEVEL.ERROR, UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType); castValue = null; } break; @@ -821,9 +833,9 @@ export const tryCreatingProjectConfig = function( if (config.jsonSchemaValidator) { config.jsonSchemaValidator(newDatafileObj); - config.logger?.log(LOG_LEVEL.INFO, LOG_MESSAGES.VALID_DATAFILE, MODULE_NAME); + config.logger?.log(LOG_LEVEL.INFO, VALID_DATAFILE, MODULE_NAME); } else { - config.logger?.log(LOG_LEVEL.INFO, LOG_MESSAGES.SKIPPING_JSON_VALIDATION, MODULE_NAME); + config.logger?.log(LOG_LEVEL.INFO, SKIPPING_JSON_VALIDATION, MODULE_NAME); } const createProjectConfigArgs = [newDatafileObj]; diff --git a/lib/project_config/project_config_manager.spec.ts b/lib/project_config/project_config_manager.spec.ts index 682c2bede..7bed978ef 100644 --- a/lib/project_config/project_config_manager.spec.ts +++ b/lib/project_config/project_config_manager.spec.ts @@ -127,7 +127,7 @@ describe('ProjectConfigManagerImpl', () => { }); it('should resolve onRunning() even if datafileManger.onRunning() rejects', async () => { - const onRunning = Promise.reject(new Error('onRunning error')); + const onRunning = Promise.reject(new Error("onRunning error")); const datafileManager = getMockDatafileManager({ onRunning, }); diff --git a/lib/project_config/project_config_manager.ts b/lib/project_config/project_config_manager.ts index b71ef1f39..81ee87b78 100644 --- a/lib/project_config/project_config_manager.ts +++ b/lib/project_config/project_config_manager.ts @@ -22,6 +22,12 @@ import { scheduleMicrotask } from '../utils/microtask'; import { Service, ServiceState, BaseService } from '../service'; import { Consumer, Fn, Transformer } from '../utils/type'; import { EventEmitter } from '../utils/event_emitter/event_emitter'; +import { + DATAFILE_MANAGER_FAILED_TO_START, + DATAFILE_MANAGER_STOPPED, + YOU_MUST_PROVIDE_AT_LEAST_ONE_OF_SDKKEY_OR_DATAFILE, + YOU_MUST_PROVIDE_DATAFILE_IN_SSR, +} from '../exception_messages'; interface ProjectConfigManagerConfig { // TODO: Don't use object type @@ -78,9 +84,9 @@ export class ProjectConfigManagerImpl extends BaseService implements ProjectConf if (!this.datafile && !this.datafileManager) { const errorMessage = this.isSsr - ? 'You must provide datafile in SSR' - : 'You must provide at least one of sdkKey or datafile'; - // TODO: replace message with imported constants + ? YOU_MUST_PROVIDE_DATAFILE_IN_SSR + : YOU_MUST_PROVIDE_AT_LEAST_ONE_OF_SDKKEY_OR_DATAFILE; + this.handleInitError(new Error(errorMessage)); return; } @@ -113,8 +119,7 @@ export class ProjectConfigManagerImpl extends BaseService implements ProjectConf } private handleDatafileManagerError(err: Error): void { - // TODO: replace message with imported constants - this.logger?.error('datafile manager failed to start', err); + this.logger?.error(DATAFILE_MANAGER_FAILED_TO_START, err); // If datafile manager onRunning() promise is rejected, and the project config manager // is still in starting state, that means a datafile was not provided in cofig or was invalid, @@ -202,7 +207,7 @@ export class ProjectConfigManagerImpl extends BaseService implements ProjectConf if (this.isNew() || this.isStarting()) { // TOOD: replace message with imported constants - this.startPromise.reject(new Error('Datafile manager stopped before it could be started')); + this.startPromise.reject(new Error(DATAFILE_MANAGER_STOPPED)); } this.state = ServiceState.Stopping; diff --git a/lib/utils/attributes_validator/index.tests.js b/lib/utils/attributes_validator/index.tests.js index d98e8fdb0..ed79d9470 100644 --- a/lib/utils/attributes_validator/index.tests.js +++ b/lib/utils/attributes_validator/index.tests.js @@ -17,7 +17,7 @@ import { assert } from 'chai'; import { sprintf } from '../../utils/fns'; import * as attributesValidator from './'; -import { ERROR_MESSAGES } from '../enums'; +import { INVALID_ATTRIBUTES, UNDEFINED_ATTRIBUTE } from '../../error_messages'; describe('lib/utils/attributes_validator', function() { describe('APIs', function() { @@ -30,13 +30,13 @@ describe('lib/utils/attributes_validator', function() { var attributesArray = ['notGonnaWork']; assert.throws(function() { attributesValidator.validate(attributesArray); - }, sprintf(ERROR_MESSAGES.INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); + }, sprintf(INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); }); it('should throw an error if attributes is null', function() { assert.throws(function() { attributesValidator.validate(null); - }, sprintf(ERROR_MESSAGES.INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); + }, sprintf(INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); }); it('should throw an error if attributes is a function', function() { @@ -45,7 +45,7 @@ describe('lib/utils/attributes_validator', function() { } assert.throws(function() { attributesValidator.validate(invalidInput); - }, sprintf(ERROR_MESSAGES.INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); + }, sprintf(INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); }); it('should throw an error if attributes contains a key with an undefined value', function() { @@ -55,7 +55,7 @@ describe('lib/utils/attributes_validator', function() { assert.throws(function() { attributesValidator.validate(attributes); - }, sprintf(ERROR_MESSAGES.UNDEFINED_ATTRIBUTE, 'ATTRIBUTES_VALIDATOR', attributeKey)); + }, sprintf(UNDEFINED_ATTRIBUTE, 'ATTRIBUTES_VALIDATOR', attributeKey)); }); }); diff --git a/lib/utils/attributes_validator/index.ts b/lib/utils/attributes_validator/index.ts index 5f33e85d4..255b99419 100644 --- a/lib/utils/attributes_validator/index.ts +++ b/lib/utils/attributes_validator/index.ts @@ -17,7 +17,7 @@ import { sprintf } from '../../utils/fns'; import { ObjectWithUnknownProperties } from '../../shared_types'; import fns from '../../utils/fns'; -import { ERROR_MESSAGES } from '../enums'; +import { INVALID_ATTRIBUTES, UNDEFINED_ATTRIBUTE } from '../../error_messages'; const MODULE_NAME = 'ATTRIBUTES_VALIDATOR'; @@ -32,12 +32,12 @@ export function validate(attributes: unknown): boolean { if (typeof attributes === 'object' && !Array.isArray(attributes) && attributes !== null) { Object.keys(attributes).forEach(function(key) { if (typeof (attributes as ObjectWithUnknownProperties)[key] === 'undefined') { - throw new Error(sprintf(ERROR_MESSAGES.UNDEFINED_ATTRIBUTE, MODULE_NAME, key)); + throw new Error(sprintf(UNDEFINED_ATTRIBUTE, MODULE_NAME, key)); } }); return true; } else { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_ATTRIBUTES, MODULE_NAME)); + throw new Error(sprintf(INVALID_ATTRIBUTES, MODULE_NAME)); } } diff --git a/lib/utils/config_validator/index.tests.js b/lib/utils/config_validator/index.tests.js index 9ff0a32c5..b7a8711c7 100644 --- a/lib/utils/config_validator/index.tests.js +++ b/lib/utils/config_validator/index.tests.js @@ -17,8 +17,15 @@ import { assert } from 'chai'; import { sprintf } from '../../utils/fns'; import configValidator from './'; -import { ERROR_MESSAGES } from '../enums'; import testData from '../../tests/test_data'; +import { + INVALID_DATAFILE_MALFORMED, + INVALID_DATAFILE_VERSION, + INVALID_ERROR_HANDLER, + INVALID_EVENT_DISPATCHER, + INVALID_LOGGER, + NO_DATAFILE_SPECIFIED, +} from '../../error_messages'; describe('lib/utils/config_validator', function() { describe('APIs', function() { @@ -28,7 +35,7 @@ describe('lib/utils/config_validator', function() { configValidator.validate({ errorHandler: {}, }); - }, sprintf(ERROR_MESSAGES.INVALID_ERROR_HANDLER, 'CONFIG_VALIDATOR')); + }, sprintf(INVALID_ERROR_HANDLER, 'CONFIG_VALIDATOR')); }); it('should complain if the provided event dispatcher is invalid', function() { @@ -36,7 +43,7 @@ describe('lib/utils/config_validator', function() { configValidator.validate({ eventDispatcher: {}, }); - }, sprintf(ERROR_MESSAGES.INVALID_EVENT_DISPATCHER, 'CONFIG_VALIDATOR')); + }, sprintf(INVALID_EVENT_DISPATCHER, 'CONFIG_VALIDATOR')); }); it('should complain if the provided logger is invalid', function() { @@ -44,25 +51,25 @@ describe('lib/utils/config_validator', function() { configValidator.validate({ logger: {}, }); - }, sprintf(ERROR_MESSAGES.INVALID_LOGGER, 'CONFIG_VALIDATOR')); + }, sprintf(INVALID_LOGGER, 'CONFIG_VALIDATOR')); }); it('should complain if datafile is not provided', function() { assert.throws(function() { configValidator.validateDatafile(); - }, sprintf(ERROR_MESSAGES.NO_DATAFILE_SPECIFIED, 'CONFIG_VALIDATOR')); + }, sprintf(NO_DATAFILE_SPECIFIED, 'CONFIG_VALIDATOR')); }); it('should complain if datafile is malformed', function() { assert.throws(function() { configValidator.validateDatafile('abc'); - }, sprintf(ERROR_MESSAGES.INVALID_DATAFILE_MALFORMED, 'CONFIG_VALIDATOR')); + }, sprintf(INVALID_DATAFILE_MALFORMED, 'CONFIG_VALIDATOR')); }); it('should complain if datafile version is not supported', function() { assert.throws(function() { configValidator.validateDatafile(JSON.stringify(testData.getUnsupportedVersionConfig())); - }, sprintf(ERROR_MESSAGES.INVALID_DATAFILE_VERSION, 'CONFIG_VALIDATOR', '5')); + }, sprintf(INVALID_DATAFILE_VERSION, 'CONFIG_VALIDATOR', '5')); }); it('should not complain if datafile is valid', function() { diff --git a/lib/utils/config_validator/index.ts b/lib/utils/config_validator/index.ts index a273121cc..12e0ca0d9 100644 --- a/lib/utils/config_validator/index.ts +++ b/lib/utils/config_validator/index.ts @@ -17,9 +17,17 @@ import { sprintf } from '../../utils/fns'; import { ObjectWithUnknownProperties } from '../../shared_types'; import { - ERROR_MESSAGES, DATAFILE_VERSIONS, } from '../enums'; +import { + INVALID_CONFIG, + INVALID_DATAFILE_MALFORMED, + INVALID_DATAFILE_VERSION, + INVALID_ERROR_HANDLER, + INVALID_EVENT_DISPATCHER, + INVALID_LOGGER, + NO_DATAFILE_SPECIFIED, +} from '../../error_messages'; const MODULE_NAME = 'CONFIG_VALIDATOR'; const SUPPORTED_VERSIONS = [DATAFILE_VERSIONS.V2, DATAFILE_VERSIONS.V3, DATAFILE_VERSIONS.V4]; @@ -40,17 +48,17 @@ export const validate = function(config: unknown): boolean { const eventDispatcher = configObj['eventDispatcher']; const logger = configObj['logger']; if (errorHandler && typeof (errorHandler as ObjectWithUnknownProperties)['handleError'] !== 'function') { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_ERROR_HANDLER, MODULE_NAME)); + throw new Error(sprintf(INVALID_ERROR_HANDLER, MODULE_NAME)); } if (eventDispatcher && typeof (eventDispatcher as ObjectWithUnknownProperties)['dispatchEvent'] !== 'function') { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_EVENT_DISPATCHER, MODULE_NAME)); + throw new Error(sprintf(INVALID_EVENT_DISPATCHER, MODULE_NAME)); } if (logger && typeof (logger as ObjectWithUnknownProperties)['log'] !== 'function') { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_LOGGER, MODULE_NAME)); + throw new Error(sprintf(INVALID_LOGGER, MODULE_NAME)); } return true; } - throw new Error(sprintf(ERROR_MESSAGES.INVALID_CONFIG, MODULE_NAME)); + throw new Error(sprintf(INVALID_CONFIG, MODULE_NAME)); } /** @@ -65,19 +73,19 @@ export const validate = function(config: unknown): boolean { // eslint-disable-next-line export const validateDatafile = function(datafile: unknown): any { if (!datafile) { - throw new Error(sprintf(ERROR_MESSAGES.NO_DATAFILE_SPECIFIED, MODULE_NAME)); + throw new Error(sprintf(NO_DATAFILE_SPECIFIED, MODULE_NAME)); } if (typeof datafile === 'string') { // Attempt to parse the datafile string try { datafile = JSON.parse(datafile); } catch (ex) { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_DATAFILE_MALFORMED, MODULE_NAME)); + throw new Error(sprintf(INVALID_DATAFILE_MALFORMED, MODULE_NAME)); } } if (typeof datafile === 'object' && !Array.isArray(datafile) && datafile !== null) { if (SUPPORTED_VERSIONS.indexOf(datafile['version' as keyof unknown]) === -1) { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_DATAFILE_VERSION, MODULE_NAME, datafile['version' as keyof unknown])); + throw new Error(sprintf(INVALID_DATAFILE_VERSION, MODULE_NAME, datafile['version' as keyof unknown])); } } diff --git a/lib/utils/enums/index.ts b/lib/utils/enums/index.ts index 551fa6b98..1c867fbbf 100644 --- a/lib/utils/enums/index.ts +++ b/lib/utils/enums/index.ts @@ -25,185 +25,6 @@ export const LOG_LEVEL = { ERROR: 4, }; -export const ERROR_MESSAGES = { - BROWSER_ODP_MANAGER_INITIALIZATION_FAILED: '%s: Error initializing Browser ODP Manager.', - CONDITION_EVALUATOR_ERROR: '%s: Error evaluating audience condition of type %s: %s', - DATAFILE_AND_SDK_KEY_MISSING: '%s: You must provide at least one of sdkKey or datafile. Cannot start Optimizely', - EXPERIMENT_KEY_NOT_IN_DATAFILE: '%s: Experiment key %s is not in datafile.', - FEATURE_NOT_IN_DATAFILE: '%s: Feature key %s is not in datafile.', - FETCH_SEGMENTS_FAILED_NETWORK_ERROR: '%s: Audience segments fetch failed. (network error)', - FETCH_SEGMENTS_FAILED_DECODE_ERROR: '%s: Audience segments fetch failed. (decode error)', - IMPROPERLY_FORMATTED_EXPERIMENT: '%s: Experiment key %s is improperly formatted.', - INVALID_ATTRIBUTES: '%s: Provided attributes are in an invalid format.', - INVALID_BUCKETING_ID: '%s: Unable to generate hash for bucketing ID %s: %s', - INVALID_DATAFILE: '%s: Datafile is invalid - property %s: %s', - INVALID_DATAFILE_MALFORMED: '%s: Datafile is invalid because it is malformed.', - INVALID_CONFIG: '%s: Provided Optimizely config is in an invalid format.', - INVALID_JSON: '%s: JSON object is not valid.', - INVALID_ERROR_HANDLER: '%s: Provided "errorHandler" is in an invalid format.', - INVALID_EVENT_DISPATCHER: '%s: Provided "eventDispatcher" is in an invalid format.', - INVALID_EVENT_TAGS: '%s: Provided event tags are in an invalid format.', - INVALID_EXPERIMENT_KEY: '%s: Experiment key %s is not in datafile. It is either invalid, paused, or archived.', - INVALID_EXPERIMENT_ID: '%s: Experiment ID %s is not in datafile.', - INVALID_GROUP_ID: '%s: Group ID %s is not in datafile.', - INVALID_LOGGER: '%s: Provided "logger" is in an invalid format.', - INVALID_ROLLOUT_ID: '%s: Invalid rollout ID %s attached to feature %s', - INVALID_USER_ID: '%s: Provided user ID is in an invalid format.', - INVALID_USER_PROFILE_SERVICE: '%s: Provided user profile service instance is in an invalid format: %s.', - LOCAL_STORAGE_DOES_NOT_EXIST: 'Error accessing window localStorage.', - MISSING_INTEGRATION_KEY: '%s: Integration key missing from datafile. All integrations should include a key.', - NO_DATAFILE_SPECIFIED: '%s: No datafile specified. Cannot start optimizely.', - NO_JSON_PROVIDED: '%s: No JSON object to validate against schema.', - NO_EVENT_PROCESSOR: 'No event processor is provided', - NO_VARIATION_FOR_EXPERIMENT_KEY: '%s: No variation key %s defined in datafile for experiment %s.', - ODP_CONFIG_NOT_AVAILABLE: '%s: ODP is not integrated to the project.', - ODP_EVENT_FAILED: 'ODP event send failed.', - ODP_FETCH_QUALIFIED_SEGMENTS_SEGMENTS_MANAGER_MISSING: - '%s: ODP unable to fetch qualified segments (Segments Manager not initialized).', - ODP_IDENTIFY_FAILED_EVENT_MANAGER_MISSING: - '%s: ODP identify event %s is not dispatched (Event Manager not instantiated).', - ODP_INITIALIZATION_FAILED: '%s: ODP failed to initialize.', - ODP_INVALID_DATA: '%s: ODP data is not valid', - ODP_EVENT_FAILED_ODP_MANAGER_MISSING: '%s: ODP Event failed to send. (ODP Manager not initialized).', - ODP_FETCH_QUALIFIED_SEGMENTS_FAILED_ODP_MANAGER_MISSING: - '%s: ODP failed to Fetch Qualified Segments. (ODP Manager not initialized).', - ODP_IDENTIFY_USER_FAILED_ODP_MANAGER_MISSING: '%s: ODP failed to Identify User. (ODP Manager not initialized).', - ODP_IDENTIFY_USER_FAILED_USER_CONTEXT_INITIALIZATION: - '%s: ODP failed to Identify User. (Failed during User Context Initialization).', - ODP_MANAGER_UPDATE_SETTINGS_FAILED_EVENT_MANAGER_MISSING: - '%s: ODP Manager failed to update OdpConfig settings for internal event manager. (Event Manager not initialized).', - ODP_MANAGER_UPDATE_SETTINGS_FAILED_SEGMENTS_MANAGER_MISSING: - '%s: ODP Manager failed to update OdpConfig settings for internal segments manager. (Segments Manager not initialized).', - ODP_NOT_ENABLED: 'ODP is not enabled', - ODP_NOT_INTEGRATED: '%s: ODP is not integrated', - ODP_SEND_EVENT_FAILED_EVENT_MANAGER_MISSING: - '%s: ODP send event %s was not dispatched (Event Manager not instantiated).', - ODP_SEND_EVENT_FAILED_UID_MISSING: '%s: ODP send event %s was not dispatched (No valid user identifier provided).', - ODP_SEND_EVENT_FAILED_VUID_MISSING: '%s: ODP send event %s was not dispatched (Unable to fetch VUID).', - ODP_VUID_INITIALIZATION_FAILED: '%s: ODP VUID initialization failed.', - ODP_VUID_REGISTRATION_FAILED: '%s: ODP VUID failed to be registered.', - ODP_VUID_REGISTRATION_FAILED_EVENT_MANAGER_MISSING: '%s: ODP register vuid failed. (Event Manager not instantiated).', - UNDEFINED_ATTRIBUTE: '%s: Provided attribute: %s has an undefined value.', - UNRECOGNIZED_ATTRIBUTE: '%s: Unrecognized attribute %s provided. Pruning before sending event to Optimizely.', - UNABLE_TO_CAST_VALUE: '%s: Unable to cast value %s to type %s, returning null.', - USER_NOT_IN_FORCED_VARIATION: '%s: User %s is not in the forced variation map. Cannot remove their forced variation.', - USER_PROFILE_LOOKUP_ERROR: '%s: Error while looking up user profile for user ID "%s": %s.', - USER_PROFILE_SAVE_ERROR: '%s: Error while saving user profile for user ID "%s": %s.', - VARIABLE_KEY_NOT_IN_DATAFILE: '%s: Variable with key "%s" associated with feature with key "%s" is not in datafile.', - VARIATION_ID_NOT_IN_DATAFILE: '%s: No variation ID %s defined in datafile for experiment %s.', - VARIATION_ID_NOT_IN_DATAFILE_NO_EXPERIMENT: '%s: Variation ID %s is not in the datafile.', - INVALID_INPUT_FORMAT: '%s: Provided %s is in an invalid format.', - INVALID_DATAFILE_VERSION: '%s: This version of the JavaScript SDK does not support the given datafile version: %s', - INVALID_VARIATION_KEY: '%s: Provided variation key is in an invalid format.', -}; - -export const LOG_MESSAGES = { - ACTIVATE_USER: '%s: Activating user %s in experiment %s.', - DISPATCH_CONVERSION_EVENT: '%s: Dispatching conversion event to URL %s with params %s.', - DISPATCH_IMPRESSION_EVENT: '%s: Dispatching impression event to URL %s with params %s.', - DEPRECATED_EVENT_VALUE: '%s: Event value is deprecated in %s call.', - EVENT_KEY_NOT_FOUND: '%s: Event key %s is not in datafile.', - EXPERIMENT_NOT_RUNNING: '%s: Experiment %s is not running.', - FEATURE_ENABLED_FOR_USER: '%s: Feature %s is enabled for user %s.', - FEATURE_NOT_ENABLED_FOR_USER: '%s: Feature %s is not enabled for user %s.', - FEATURE_HAS_NO_EXPERIMENTS: '%s: Feature %s is not attached to any experiments.', - FAILED_TO_PARSE_VALUE: '%s: Failed to parse event value "%s" from event tags.', - FAILED_TO_PARSE_REVENUE: '%s: Failed to parse revenue value "%s" from event tags.', - FORCED_BUCKETING_FAILED: '%s: Variation key %s is not in datafile. Not activating user %s.', - INVALID_OBJECT: '%s: Optimizely object is not valid. Failing %s.', - INVALID_CLIENT_ENGINE: '%s: Invalid client engine passed: %s. Defaulting to node-sdk.', - INVALID_DEFAULT_DECIDE_OPTIONS: '%s: Provided default decide options is not an array.', - INVALID_DECIDE_OPTIONS: '%s: Provided decide options is not an array. Using default decide options.', - INVALID_VARIATION_ID: '%s: Bucketed into an invalid variation ID. Returning null.', - NOTIFICATION_LISTENER_EXCEPTION: '%s: Notification listener for (%s) threw exception: %s', - NO_ROLLOUT_EXISTS: '%s: There is no rollout of feature %s.', - NOT_ACTIVATING_USER: '%s: Not activating user %s for experiment %s.', - NOT_TRACKING_USER: '%s: Not tracking user %s.', - ODP_DISABLED: 'ODP Disabled.', - ODP_IDENTIFY_FAILED_ODP_DISABLED: '%s: ODP identify event for user %s is not dispatched (ODP disabled).', - ODP_IDENTIFY_FAILED_ODP_NOT_INTEGRATED: '%s: ODP identify event %s is not dispatched (ODP not integrated).', - ODP_SEND_EVENT_IDENTIFIER_CONVERSION_FAILED: - '%s: sendOdpEvent failed to parse through and convert fs_user_id aliases', - PARSED_REVENUE_VALUE: '%s: Parsed revenue value "%s" from event tags.', - PARSED_NUMERIC_VALUE: '%s: Parsed event value "%s" from event tags.', - RETURNING_STORED_VARIATION: - '%s: Returning previously activated variation "%s" of experiment "%s" for user "%s" from user profile.', - ROLLOUT_HAS_NO_EXPERIMENTS: '%s: Rollout of feature %s has no experiments', - SAVED_USER_VARIATION: '%s: Saved user profile for user "%s".', - UPDATED_USER_VARIATION: '%s: Updated variation "%s" of experiment "%s" for user "%s".', - SAVED_VARIATION_NOT_FOUND: - '%s: User %s was previously bucketed into variation with ID %s for experiment %s, but no matching variation was found.', - SHOULD_NOT_DISPATCH_ACTIVATE: '%s: Experiment %s is not in "Running" state. Not activating user.', - SKIPPING_JSON_VALIDATION: '%s: Skipping JSON schema validation.', - TRACK_EVENT: '%s: Tracking event %s for user %s.', - UNRECOGNIZED_DECIDE_OPTION: '%s: Unrecognized decide option %s provided.', - USER_ASSIGNED_TO_EXPERIMENT_BUCKET: '%s: Assigned bucket %s to user with bucketing ID %s.', - USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP: '%s: User %s is in experiment %s of group %s.', - USER_BUCKETED_INTO_TARGETING_RULE: '%s: User %s bucketed into targeting rule %s.', - USER_IN_FEATURE_EXPERIMENT: '%s: User %s is in variation %s of experiment %s on the feature %s.', - USER_IN_ROLLOUT: '%s: User %s is in rollout of feature %s.', - USER_NOT_BUCKETED_INTO_EVERYONE_TARGETING_RULE: - '%s: User %s not bucketed into everyone targeting rule due to traffic allocation.', - USER_NOT_BUCKETED_INTO_EXPERIMENT_IN_GROUP: '%s: User %s is not in experiment %s of group %s.', - USER_NOT_BUCKETED_INTO_ANY_EXPERIMENT_IN_GROUP: '%s: User %s is not in any experiment of group %s.', - USER_NOT_BUCKETED_INTO_TARGETING_RULE: - '%s User %s not bucketed into targeting rule %s due to traffic allocation. Trying everyone rule.', - USER_NOT_IN_FEATURE_EXPERIMENT: '%s: User %s is not in any experiment on the feature %s.', - USER_NOT_IN_ROLLOUT: '%s: User %s is not in rollout of feature %s.', - USER_FORCED_IN_VARIATION: '%s: User %s is forced in variation %s.', - USER_MAPPED_TO_FORCED_VARIATION: '%s: Set variation %s for experiment %s and user %s in the forced variation map.', - USER_DOESNT_MEET_CONDITIONS_FOR_TARGETING_RULE: '%s: User %s does not meet conditions for targeting rule %s.', - USER_MEETS_CONDITIONS_FOR_TARGETING_RULE: '%s: User %s meets conditions for targeting rule %s.', - USER_HAS_VARIATION: '%s: User %s is in variation %s of experiment %s.', - USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED: - 'Variation (%s) is mapped to flag (%s), rule (%s) and user (%s) in the forced decision map.', - USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED: - 'Variation (%s) is mapped to flag (%s) and user (%s) in the forced decision map.', - USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED_BUT_INVALID: - 'Invalid variation is mapped to flag (%s), rule (%s) and user (%s) in the forced decision map.', - USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED_BUT_INVALID: - 'Invalid variation is mapped to flag (%s) and user (%s) in the forced decision map.', - USER_HAS_FORCED_VARIATION: '%s: Variation %s is mapped to experiment %s and user %s in the forced variation map.', - USER_HAS_NO_VARIATION: '%s: User %s is in no variation of experiment %s.', - USER_HAS_NO_FORCED_VARIATION: '%s: User %s is not in the forced variation map.', - USER_HAS_NO_FORCED_VARIATION_FOR_EXPERIMENT: '%s: No experiment %s mapped to user %s in the forced variation map.', - USER_NOT_IN_ANY_EXPERIMENT: '%s: User %s is not in any experiment of group %s.', - USER_NOT_IN_EXPERIMENT: '%s: User %s does not meet conditions to be in experiment %s.', - USER_RECEIVED_DEFAULT_VARIABLE_VALUE: - '%s: User "%s" is not in any variation or rollout rule. Returning default value for variable "%s" of feature flag "%s".', - FEATURE_NOT_ENABLED_RETURN_DEFAULT_VARIABLE_VALUE: - '%s: Feature "%s" is not enabled for user %s. Returning the default variable value "%s".', - VARIABLE_NOT_USED_RETURN_DEFAULT_VARIABLE_VALUE: - '%s: Variable "%s" is not used in variation "%s". Returning default value.', - USER_RECEIVED_VARIABLE_VALUE: '%s: Got variable value "%s" for variable "%s" of feature flag "%s"', - VALID_DATAFILE: '%s: Datafile is valid.', - VALID_USER_PROFILE_SERVICE: '%s: Valid user profile service provided.', - VARIATION_REMOVED_FOR_USER: '%s: Variation mapped to experiment %s has been removed for user %s.', - VARIABLE_REQUESTED_WITH_WRONG_TYPE: - '%s: Requested variable type "%s", but variable is of type "%s". Use correct API to retrieve value. Returning None.', - VALID_BUCKETING_ID: '%s: BucketingId is valid: "%s"', - BUCKETING_ID_NOT_STRING: '%s: BucketingID attribute is not a string. Defaulted to userId', - EVALUATING_AUDIENCE: '%s: Starting to evaluate audience "%s" with conditions: %s.', - EVALUATING_AUDIENCES_COMBINED: '%s: Evaluating audiences for %s "%s": %s.', - AUDIENCE_EVALUATION_RESULT: '%s: Audience "%s" evaluated to %s.', - AUDIENCE_EVALUATION_RESULT_COMBINED: '%s: Audiences for %s %s collectively evaluated to %s.', - MISSING_ATTRIBUTE_VALUE: - '%s: Audience condition %s evaluated to UNKNOWN because no value was passed for user attribute "%s".', - UNEXPECTED_CONDITION_VALUE: - '%s: Audience condition %s evaluated to UNKNOWN because the condition value is not supported.', - UNEXPECTED_TYPE: - '%s: Audience condition %s evaluated to UNKNOWN because a value of type "%s" was passed for user attribute "%s".', - UNEXPECTED_TYPE_NULL: - '%s: Audience condition %s evaluated to UNKNOWN because a null value was passed for user attribute "%s".', - UNKNOWN_CONDITION_TYPE: - '%s: Audience condition %s has an unknown condition type. You may need to upgrade to a newer release of the Optimizely SDK.', - UNKNOWN_MATCH_TYPE: - '%s: Audience condition %s uses an unknown match type. You may need to upgrade to a newer release of the Optimizely SDK.', - UPDATED_OPTIMIZELY_CONFIG: '%s: Updated Optimizely config to revision %s (project id %s)', - OUT_OF_BOUNDS: - '%s: Audience condition %s evaluated to UNKNOWN because the number value for user attribute "%s" is not in the range [-2^53, +2^53].', - UNABLE_TO_ATTACH_UNLOAD: '%s: unable to bind optimizely.close() to page unload event: "%s"', -}; export const enum RESERVED_EVENT_KEYWORDS { REVENUE = 'revenue', @@ -223,7 +44,7 @@ export const NODE_CLIENT_ENGINE = 'node-sdk'; export const REACT_CLIENT_ENGINE = 'react-sdk'; export const REACT_NATIVE_CLIENT_ENGINE = 'react-native-sdk'; export const REACT_NATIVE_JS_CLIENT_ENGINE = 'react-native-js-sdk'; -export const CLIENT_VERSION ='5.3.4' +export const CLIENT_VERSION = '5.3.4'; export const DECISION_NOTIFICATION_TYPES = { AB_TEST: 'ab-test', diff --git a/lib/utils/event_tag_utils/index.ts b/lib/utils/event_tag_utils/index.ts index 9836afa14..fab537adb 100644 --- a/lib/utils/event_tag_utils/index.ts +++ b/lib/utils/event_tag_utils/index.ts @@ -13,12 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { + FAILED_TO_PARSE_REVENUE, + FAILED_TO_PARSE_VALUE, + PARSED_NUMERIC_VALUE, + PARSED_REVENUE_VALUE, +} from '../../log_messages'; import { EventTags } from '../../event_processor/event_builder/user_event'; import { LoggerFacade } from '../../modules/logging'; import { LOG_LEVEL, - LOG_MESSAGES, RESERVED_EVENT_KEYWORDS, } from '../enums'; @@ -45,10 +50,10 @@ export function getRevenueValue(eventTags: EventTags, logger: LoggerFacade): num const parsedRevenueValue = typeof rawValue === 'string' ? parseInt(rawValue) : rawValue; if (isFinite(parsedRevenueValue)) { - logger.log(LOG_LEVEL.INFO, LOG_MESSAGES.PARSED_REVENUE_VALUE, MODULE_NAME, parsedRevenueValue); + logger.log(LOG_LEVEL.INFO, PARSED_REVENUE_VALUE, MODULE_NAME, parsedRevenueValue); return parsedRevenueValue; } else { // NaN, +/- infinity values - logger.log(LOG_LEVEL.INFO, LOG_MESSAGES.FAILED_TO_PARSE_REVENUE, MODULE_NAME, rawValue); + logger.log(LOG_LEVEL.INFO, FAILED_TO_PARSE_REVENUE, MODULE_NAME, rawValue); return null; } } @@ -69,10 +74,10 @@ export function getEventValue(eventTags: EventTags, logger: LoggerFacade): numbe const parsedEventValue = typeof rawValue === 'string' ? parseFloat(rawValue) : rawValue; if (isFinite(parsedEventValue)) { - logger.log(LOG_LEVEL.INFO, LOG_MESSAGES.PARSED_NUMERIC_VALUE, MODULE_NAME, parsedEventValue); + logger.log(LOG_LEVEL.INFO, PARSED_NUMERIC_VALUE, MODULE_NAME, parsedEventValue); return parsedEventValue; } else { // NaN, +/- infinity values - logger.log(LOG_LEVEL.INFO, LOG_MESSAGES.FAILED_TO_PARSE_VALUE, MODULE_NAME, rawValue); + logger.log(LOG_LEVEL.INFO, FAILED_TO_PARSE_VALUE, MODULE_NAME, rawValue); return null; } -} \ No newline at end of file +} diff --git a/lib/utils/event_tags_validator/index.tests.js b/lib/utils/event_tags_validator/index.tests.js index 45dc75123..fcf8d4bd3 100644 --- a/lib/utils/event_tags_validator/index.tests.js +++ b/lib/utils/event_tags_validator/index.tests.js @@ -17,7 +17,7 @@ import { assert } from 'chai'; import { sprintf } from '../../utils/fns'; import { validate } from './'; -import { ERROR_MESSAGES } from'../enums'; +import { INVALID_EVENT_TAGS } from '../../error_messages'; describe('lib/utils/event_tags_validator', function() { describe('APIs', function() { @@ -30,13 +30,13 @@ describe('lib/utils/event_tags_validator', function() { var eventTagsArray = ['notGonnaWork']; assert.throws(function() { validate(eventTagsArray); - }, sprintf(ERROR_MESSAGES.INVALID_EVENT_TAGS, 'EVENT_TAGS_VALIDATOR')); + }, sprintf(INVALID_EVENT_TAGS, 'EVENT_TAGS_VALIDATOR')); }); it('should throw an error if event tags is null', function() { assert.throws(function() { validate(null); - }, sprintf(ERROR_MESSAGES.INVALID_EVENT_TAGS, 'EVENT_TAGS_VALIDATOR')); + }, sprintf(INVALID_EVENT_TAGS, 'EVENT_TAGS_VALIDATOR')); }); it('should throw an error if event tags is a function', function() { @@ -45,7 +45,7 @@ describe('lib/utils/event_tags_validator', function() { } assert.throws(function() { validate(invalidInput); - }, sprintf(ERROR_MESSAGES.INVALID_EVENT_TAGS, 'EVENT_TAGS_VALIDATOR')); + }, sprintf(INVALID_EVENT_TAGS, 'EVENT_TAGS_VALIDATOR')); }); }); }); diff --git a/lib/utils/event_tags_validator/index.ts b/lib/utils/event_tags_validator/index.ts index f2294dda0..d898cc202 100644 --- a/lib/utils/event_tags_validator/index.ts +++ b/lib/utils/event_tags_validator/index.ts @@ -17,10 +17,9 @@ /** * Provides utility method for validating that event tags user has provided are valid */ +import { INVALID_EVENT_TAGS } from '../../error_messages'; import { sprintf } from '../../utils/fns'; -import { ERROR_MESSAGES } from '../enums'; - const MODULE_NAME = 'EVENT_TAGS_VALIDATOR'; /** @@ -33,6 +32,6 @@ export function validate(eventTags: unknown): boolean { if (typeof eventTags === 'object' && !Array.isArray(eventTags) && eventTags !== null) { return true; } else { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_EVENT_TAGS, MODULE_NAME)); + throw new Error(sprintf(INVALID_EVENT_TAGS, MODULE_NAME)); } } diff --git a/lib/utils/executor/backoff_retry_runner.ts b/lib/utils/executor/backoff_retry_runner.ts index 504412c24..f939f9cc6 100644 --- a/lib/utils/executor/backoff_retry_runner.ts +++ b/lib/utils/executor/backoff_retry_runner.ts @@ -1,3 +1,4 @@ +import { RETRY_CANCELLED } from "../../exception_messages"; import { resolvablePromise, ResolvablePromise } from "../promise/resolvablePromise"; import { BackoffController } from "../repeater/repeater"; import { AsyncProducer, Fn } from "../type"; @@ -26,7 +27,7 @@ const runTask = ( return; } if (cancelSignal.cancelled) { - returnPromise.reject(new Error('Retry cancelled')); + returnPromise.reject(new Error(RETRY_CANCELLED)); return; } const delay = backoff?.backoff() ?? 0; diff --git a/lib/utils/http_request_handler/request_handler.browser.ts b/lib/utils/http_request_handler/request_handler.browser.ts index a2756e318..26e22425d 100644 --- a/lib/utils/http_request_handler/request_handler.browser.ts +++ b/lib/utils/http_request_handler/request_handler.browser.ts @@ -17,6 +17,8 @@ import { AbortableRequest, Headers, RequestHandler, Response } from './http'; import { LogHandler, LogLevel } from '../../modules/logging'; import { REQUEST_TIMEOUT_MS } from '../enums'; +import { REQUEST_ERROR, REQUEST_TIMEOUT } from '../../exception_messages'; +import { UNABLE_TO_PARSE_AND_SKIPPED_HEADER } from '../../log_messages'; /** * Handles sending requests and receiving responses over HTTP via XMLHttpRequest @@ -50,7 +52,7 @@ export class BrowserRequestHandler implements RequestHandler { if (request.readyState === XMLHttpRequest.DONE) { const statusCode = request.status; if (statusCode === 0) { - reject(new Error('Request error')); + reject(new Error(REQUEST_ERROR)); return; } @@ -67,7 +69,7 @@ export class BrowserRequestHandler implements RequestHandler { request.timeout = this.timeout; request.ontimeout = (): void => { - this.logger?.log(LogLevel.WARNING, 'Request timed out'); + this.logger?.log(LogLevel.WARNING, REQUEST_TIMEOUT); }; request.send(data); @@ -122,7 +124,7 @@ export class BrowserRequestHandler implements RequestHandler { } } } catch { - this.logger?.log(LogLevel.WARNING, `Unable to parse & skipped header item '${headerLine}'`); + this.logger?.log(LogLevel.WARNING, UNABLE_TO_PARSE_AND_SKIPPED_HEADER, headerLine); } }); return headers; diff --git a/lib/utils/http_request_handler/request_handler.node.ts b/lib/utils/http_request_handler/request_handler.node.ts index 26bc6cbda..0530553b4 100644 --- a/lib/utils/http_request_handler/request_handler.node.ts +++ b/lib/utils/http_request_handler/request_handler.node.ts @@ -20,6 +20,8 @@ import { AbortableRequest, Headers, RequestHandler, Response } from './http'; import decompressResponse from 'decompress-response'; import { LogHandler } from '../../modules/logging'; import { REQUEST_TIMEOUT_MS } from '../enums'; +import { sprintf } from '../fns'; +import { NO_STATUS_CODE_IN_RESPONSE, REQUEST_ERROR, REQUEST_TIMEOUT, UNSUPPORTED_PROTOCOL } from '../../exception_messages'; /** * Handles sending requests and receiving responses over HTTP via NodeJS http module @@ -28,7 +30,7 @@ export class NodeRequestHandler implements RequestHandler { private readonly logger?: LogHandler; private readonly timeout: number; - constructor(opt: { logger?: LogHandler, timeout?: number } = {}) { + constructor(opt: { logger?: LogHandler; timeout?: number } = {}) { this.logger = opt.logger; this.timeout = opt.timeout ?? REQUEST_TIMEOUT_MS; } @@ -46,7 +48,7 @@ export class NodeRequestHandler implements RequestHandler { if (parsedUrl.protocol !== 'https:') { return { - responsePromise: Promise.reject(new Error(`Unsupported protocol: ${parsedUrl.protocol}`)), + responsePromise: Promise.reject(new Error(sprintf(UNSUPPORTED_PROTOCOL, parsedUrl.protocol))), abort: () => {}, }; } @@ -128,7 +130,7 @@ export class NodeRequestHandler implements RequestHandler { request.on('timeout', () => { aborted = true; request.destroy(); - reject(new Error('Request timed out')); + reject(new Error(REQUEST_TIMEOUT)); }); // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -138,7 +140,7 @@ export class NodeRequestHandler implements RequestHandler { } else if (typeof err === 'string') { reject(new Error(err)); } else { - reject(new Error('Request error')); + reject(new Error(REQUEST_ERROR)); } }); @@ -164,7 +166,7 @@ export class NodeRequestHandler implements RequestHandler { } if (!incomingMessage.statusCode) { - reject(new Error('No status code in response')); + reject(new Error(NO_STATUS_CODE_IN_RESPONSE)); return; } diff --git a/lib/utils/import.react_native/@react-native-async-storage/async-storage.ts b/lib/utils/import.react_native/@react-native-async-storage/async-storage.ts index 78deb7f2d..4a2fb77ed 100644 --- a/lib/utils/import.react_native/@react-native-async-storage/async-storage.ts +++ b/lib/utils/import.react_native/@react-native-async-storage/async-storage.ts @@ -16,11 +16,13 @@ import type { AsyncStorageStatic } from '@react-native-async-storage/async-storage' +export const MODULE_NOT_FOUND_REACT_NATIVE_ASYNC_STORAGE = 'Module not found: @react-native-async-storage/async-storage'; + export const getDefaultAsyncStorage = (): AsyncStorageStatic => { try { // eslint-disable-next-line @typescript-eslint/no-var-requires return require('@react-native-async-storage/async-storage').default; } catch (e) { - throw new Error('Module not found: @react-native-async-storage/async-storage'); + throw new Error(MODULE_NOT_FOUND_REACT_NATIVE_ASYNC_STORAGE); } }; diff --git a/lib/utils/json_schema_validator/index.tests.js b/lib/utils/json_schema_validator/index.tests.js index 61df2abaa..d54bc39a4 100644 --- a/lib/utils/json_schema_validator/index.tests.js +++ b/lib/utils/json_schema_validator/index.tests.js @@ -17,8 +17,8 @@ import { sprintf } from '../fns'; import { assert } from 'chai'; import { validate } from './'; -import { ERROR_MESSAGES } from '../enums'; import testData from '../../tests/test_data'; +import { NO_JSON_PROVIDED } from '../../error_messages'; describe('lib/utils/json_schema_validator', function() { @@ -33,7 +33,7 @@ describe('lib/utils/json_schema_validator', function() { it('should throw an error if no json object is passed in', function() { assert.throws(function() { validate(); - }, sprintf(ERROR_MESSAGES.NO_JSON_PROVIDED, 'JSON_SCHEMA_VALIDATOR (Project Config JSON Schema)')); + }, sprintf(NO_JSON_PROVIDED, 'JSON_SCHEMA_VALIDATOR (Project Config JSON Schema)')); }); it('should validate specified Optimizely datafile', function() { diff --git a/lib/utils/json_schema_validator/index.ts b/lib/utils/json_schema_validator/index.ts index 7ad8708c9..a4bac5674 100644 --- a/lib/utils/json_schema_validator/index.ts +++ b/lib/utils/json_schema_validator/index.ts @@ -16,8 +16,8 @@ import { sprintf } from '../fns'; import { JSONSchema4, validate as jsonSchemaValidator } from 'json-schema'; -import { ERROR_MESSAGES } from '../enums'; import schema from '../../project_config/project_config_schema'; +import { INVALID_DATAFILE, INVALID_JSON, NO_JSON_PROVIDED } from '../../error_messages'; const MODULE_NAME = 'JSON_SCHEMA_VALIDATOR'; @@ -36,7 +36,7 @@ export function validate( const moduleTitle = `${MODULE_NAME} (${validationSchema.title})`; if (typeof jsonObject !== 'object' || jsonObject === null) { - throw new Error(sprintf(ERROR_MESSAGES.NO_JSON_PROVIDED, moduleTitle)); + throw new Error(sprintf(NO_JSON_PROVIDED, moduleTitle)); } const result = jsonSchemaValidator(jsonObject, validationSchema); @@ -50,9 +50,9 @@ export function validate( if (Array.isArray(result.errors)) { throw new Error( - sprintf(ERROR_MESSAGES.INVALID_DATAFILE, moduleTitle, result.errors[0].property, result.errors[0].message) + sprintf(INVALID_DATAFILE, moduleTitle, result.errors[0].property, result.errors[0].message) ); } - throw new Error(sprintf(ERROR_MESSAGES.INVALID_JSON, moduleTitle)); + throw new Error(sprintf(INVALID_JSON, moduleTitle)); } diff --git a/lib/utils/semantic_version/index.ts b/lib/utils/semantic_version/index.ts index e8ef11c7f..cdc479bf0 100644 --- a/lib/utils/semantic_version/index.ts +++ b/lib/utils/semantic_version/index.ts @@ -13,8 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { UNKNOWN_MATCH_TYPE } from '../../error_messages'; import { getLogger } from '../../modules/logging'; -import { VERSION_TYPE, LOG_MESSAGES } from '../enums'; +import { VERSION_TYPE } from '../enums'; const MODULE_NAME = 'SEMANTIC VERSION'; const logger = getLogger(); @@ -93,7 +94,7 @@ function splitVersion(version: string): string[] | null { // check that version shouldn't have white space if (hasWhiteSpaces(version)) { - logger.warn(LOG_MESSAGES.UNKNOWN_MATCH_TYPE, MODULE_NAME, version); + logger.warn(UNKNOWN_MATCH_TYPE, MODULE_NAME, version); return null; } //check for pre release e.g. 1.0.0-alpha where 'alpha' is a pre release @@ -113,18 +114,18 @@ function splitVersion(version: string): string[] | null { const dotCount = targetPrefix.split('.').length - 1; if (dotCount > 2) { - logger.warn(LOG_MESSAGES.UNKNOWN_MATCH_TYPE, MODULE_NAME, version); + logger.warn(UNKNOWN_MATCH_TYPE, MODULE_NAME, version); return null; } const targetVersionParts = targetPrefix.split('.'); if (targetVersionParts.length != dotCount + 1) { - logger.warn(LOG_MESSAGES.UNKNOWN_MATCH_TYPE, MODULE_NAME, version); + logger.warn(UNKNOWN_MATCH_TYPE, MODULE_NAME, version); return null; } for (const part of targetVersionParts) { if (!isNumber(part)) { - logger.warn(LOG_MESSAGES.UNKNOWN_MATCH_TYPE, MODULE_NAME, version); + logger.warn(UNKNOWN_MATCH_TYPE, MODULE_NAME, version); return null; } } diff --git a/lib/utils/user_profile_service_validator/index.tests.js b/lib/utils/user_profile_service_validator/index.tests.js index 1237a0894..f12f790ea 100644 --- a/lib/utils/user_profile_service_validator/index.tests.js +++ b/lib/utils/user_profile_service_validator/index.tests.js @@ -13,12 +13,11 @@ * See the License for the specific language governing permissions and * * limitations under the License. * ***************************************************************************/ - import { assert } from 'chai'; import { sprintf } from '../../utils/fns'; import { validate } from './'; -import { ERROR_MESSAGES } from '../enums'; +import { INVALID_USER_PROFILE_SERVICE } from '../../error_messages'; describe('lib/utils/user_profile_service_validator', function() { describe('APIs', function() { @@ -30,7 +29,7 @@ describe('lib/utils/user_profile_service_validator', function() { assert.throws(function() { validate(missingLookupFunction); }, sprintf( - ERROR_MESSAGES.INVALID_USER_PROFILE_SERVICE, + INVALID_USER_PROFILE_SERVICE, 'USER_PROFILE_SERVICE_VALIDATOR', "Missing function 'lookup'" )); @@ -44,7 +43,7 @@ describe('lib/utils/user_profile_service_validator', function() { assert.throws(function() { validate(lookupNotFunction); }, sprintf( - ERROR_MESSAGES.INVALID_USER_PROFILE_SERVICE, + INVALID_USER_PROFILE_SERVICE, 'USER_PROFILE_SERVICE_VALIDATOR', "Missing function 'lookup'" )); @@ -57,7 +56,7 @@ describe('lib/utils/user_profile_service_validator', function() { assert.throws(function() { validate(missingSaveFunction); }, sprintf( - ERROR_MESSAGES.INVALID_USER_PROFILE_SERVICE, + INVALID_USER_PROFILE_SERVICE, 'USER_PROFILE_SERVICE_VALIDATOR', "Missing function 'save'" )); @@ -71,7 +70,7 @@ describe('lib/utils/user_profile_service_validator', function() { assert.throws(function() { validate(saveNotFunction); }, sprintf( - ERROR_MESSAGES.INVALID_USER_PROFILE_SERVICE, + INVALID_USER_PROFILE_SERVICE, 'USER_PROFILE_SERVICE_VALIDATOR', "Missing function 'save'" )); diff --git a/lib/utils/user_profile_service_validator/index.ts b/lib/utils/user_profile_service_validator/index.ts index 57df0c891..8f51fc137 100644 --- a/lib/utils/user_profile_service_validator/index.ts +++ b/lib/utils/user_profile_service_validator/index.ts @@ -20,8 +20,7 @@ import { sprintf } from '../../utils/fns'; import { ObjectWithUnknownProperties } from '../../shared_types'; - -import { ERROR_MESSAGES } from '../enums'; +import { INVALID_USER_PROFILE_SERVICE } from '../../error_messages'; const MODULE_NAME = 'USER_PROFILE_SERVICE_VALIDATOR'; @@ -35,11 +34,11 @@ const MODULE_NAME = 'USER_PROFILE_SERVICE_VALIDATOR'; export function validate(userProfileServiceInstance: unknown): boolean { if (typeof userProfileServiceInstance === 'object' && userProfileServiceInstance !== null) { if (typeof (userProfileServiceInstance as ObjectWithUnknownProperties)['lookup'] !== 'function') { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_USER_PROFILE_SERVICE, MODULE_NAME, "Missing function 'lookup'")); + throw new Error(sprintf(INVALID_USER_PROFILE_SERVICE, MODULE_NAME, "Missing function 'lookup'")); } else if (typeof (userProfileServiceInstance as ObjectWithUnknownProperties)['save'] !== 'function') { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_USER_PROFILE_SERVICE, MODULE_NAME, "Missing function 'save'")); + throw new Error(sprintf(INVALID_USER_PROFILE_SERVICE, MODULE_NAME, "Missing function 'save'")); } return true; } - throw new Error(sprintf(ERROR_MESSAGES.INVALID_USER_PROFILE_SERVICE, MODULE_NAME)); + throw new Error(sprintf(INVALID_USER_PROFILE_SERVICE, MODULE_NAME)); } diff --git a/lib/vuid/vuid_manager_factory.node.spec.ts b/lib/vuid/vuid_manager_factory.node.spec.ts index 2a81f9a8a..048704794 100644 --- a/lib/vuid/vuid_manager_factory.node.spec.ts +++ b/lib/vuid/vuid_manager_factory.node.spec.ts @@ -17,10 +17,11 @@ import { vi, describe, expect, it } from 'vitest'; import { createVuidManager } from './vuid_manager_factory.node'; +import { VUID_IS_NOT_SUPPORTED_IN_NODEJS } from '../exception_messages'; describe('createVuidManager', () => { it('should throw an error', () => { expect(() => createVuidManager({ enableVuid: true })) - .toThrowError('VUID is not supported in Node.js environment'); + .toThrowError(VUID_IS_NOT_SUPPORTED_IN_NODEJS); }); }); diff --git a/lib/vuid/vuid_manager_factory.node.ts b/lib/vuid/vuid_manager_factory.node.ts index 993fbb60a..6d194ce0b 100644 --- a/lib/vuid/vuid_manager_factory.node.ts +++ b/lib/vuid/vuid_manager_factory.node.ts @@ -13,10 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { VUID_IS_NOT_SUPPORTED_IN_NODEJS } from '../exception_messages'; import { VuidManager } from './vuid_manager'; import { VuidManagerOptions } from './vuid_manager_factory'; export const createVuidManager = (options: VuidManagerOptions): VuidManager => { - throw new Error('VUID is not supported in Node.js environment'); + throw new Error(VUID_IS_NOT_SUPPORTED_IN_NODEJS); }; diff --git a/message_generator.ts b/message_generator.ts index 2c7cd53b1..d4b03fb04 100644 --- a/message_generator.ts +++ b/message_generator.ts @@ -25,7 +25,7 @@ const generate = async () => { genOut += `export const messages = ${JSON.stringify(messages, null, 2)};` await writeFile(genFilePath, genOut, 'utf-8'); - }; + } } generate().then(() => { diff --git a/package.json b/package.json index dbb2bf109..b4f553c4b 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "prepare": "npm run build", "prepublishOnly": "npm test && npm run test-ci", "postbuild:win": "@powershell copy \"dist/index.lite.d.ts\" \"dist/optimizely.lite.es.d.ts\" && @powershell copy \"dist/index.lite.d.ts\" \"dist/optimizely.lite.es.min.d.ts\" && @powershell copy \"dist/index.lite.d.ts\" \"dist/optimizely.lite.min.d.ts\"", - "genmsg": "jiti message_generator ./lib/error_messages.ts" + "genmsg": "jiti message_generator ./lib/error_messages.ts ./lib/log_messages.ts ./lib/exception_messages.ts" }, "repository": { "type": "git",