diff --git a/packages/optimizely-sdk/lib/core/event_builder/event_helpers.js b/packages/optimizely-sdk/lib/core/event_builder/event_helpers.js index aeeb958b2..778efa662 100644 --- a/packages/optimizely-sdk/lib/core/event_builder/event_helpers.js +++ b/packages/optimizely-sdk/lib/core/event_builder/event_helpers.js @@ -1,5 +1,5 @@ /** - * Copyright 2019, Optimizely + * Copyright 2019-2020, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -var logging = require('@optimizely/js-sdk-logging'); +import { getLogger } from '@optimizely/js-sdk-logging'; -var attributesValidator = require('../../utils/attributes_validator'); -var fns = require('../../utils/fns'); -var eventTagUtils = require('../../utils/event_tag_utils'); -var projectConfig = require('../project_config'); +import fns from '../../utils/fns'; +import projectConfig from '../project_config'; +import eventTagUtils from '../../utils/event_tag_utils'; +import attributesValidator from'../../utils/attributes_validator'; -var logger = logging.getLogger('EVENT_BUILDER'); +var logger = getLogger('EVENT_BUILDER'); /** * Creates an ImpressionEvent object from decision data @@ -34,7 +34,7 @@ var logger = logging.getLogger('EVENT_BUILDER'); * @param {String} config.clientVersion * @return {Object} an ImpressionEvent object */ -exports.buildImpressionEvent = function buildImpressionEvent(config) { +export var buildImpressionEvent = function(config) { var configObj = config.configObj; var experimentKey = config.experimentKey; var variationKey = config.variationKey; @@ -95,7 +95,7 @@ exports.buildImpressionEvent = function buildImpressionEvent(config) { * @param {String} config.clientVersion * @return {Object} a ConversionEvent object */ -exports.buildConversionEvent = function buildConversionEvent(config) { +export var buildConversionEvent = function(config) { var configObj = config.configObj; var userId = config.userId; var userAttributes = config.userAttributes; diff --git a/packages/optimizely-sdk/lib/core/event_builder/event_helpers.tests.js b/packages/optimizely-sdk/lib/core/event_builder/event_helpers.tests.js index 152fa9464..613118eeb 100644 --- a/packages/optimizely-sdk/lib/core/event_builder/event_helpers.tests.js +++ b/packages/optimizely-sdk/lib/core/event_builder/event_helpers.tests.js @@ -1,5 +1,5 @@ /** - * Copyright 2019, Optimizely + * Copyright 2019-2020, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,13 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -var projectConfig = require('../project_config'); -var eventHelpers = require('./event_helpers'); -var fns = require('../../utils/fns'); +import sinon from 'sinon'; +import { assert } from 'chai'; -var chai = require('chai'); -var assert = chai.assert; -var sinon = require('sinon'); +import fns from '../../utils/fns'; +import projectConfig from '../project_config'; +import { buildImpressionEvent, buildConversionEvent } from './event_helpers'; describe('lib/event_builder/event_helpers', function() { var configObj; @@ -65,7 +64,7 @@ describe('lib/event_builder/event_helpers', function() { projectConfig.getAttributeId.withArgs(configObj, 'plan_type').returns('plan_type_id'); - var result = eventHelpers.buildImpressionEvent({ + var result = buildImpressionEvent({ configObj: configObj, experimentKey: 'exp1', variationKey: 'var1', @@ -131,7 +130,7 @@ describe('lib/event_builder/event_helpers', function() { delete configObj['anonymizeIP']; delete configObj['botFiltering']; - var result = eventHelpers.buildImpressionEvent({ + var result = buildImpressionEvent({ configObj: configObj, experimentKey: 'exp1', variationKey: 'var1', @@ -191,7 +190,7 @@ describe('lib/event_builder/event_helpers', function() { projectConfig.getEventId.withArgs(configObj, 'event').returns('event-id'); projectConfig.getAttributeId.withArgs(configObj, 'plan_type').returns('plan_type_id'); - var result = eventHelpers.buildConversionEvent({ + var result = buildConversionEvent({ configObj: configObj, eventKey: 'event', eventTags: { @@ -257,7 +256,7 @@ describe('lib/event_builder/event_helpers', function() { delete configObj['anonymizeIP']; delete configObj['botFiltering']; - var result = eventHelpers.buildConversionEvent({ + var result = buildConversionEvent({ configObj: configObj, eventKey: 'event', eventTags: { diff --git a/packages/optimizely-sdk/lib/core/event_builder/index.js b/packages/optimizely-sdk/lib/core/event_builder/index.js index 575b86cea..08cb0225e 100644 --- a/packages/optimizely-sdk/lib/core/event_builder/index.js +++ b/packages/optimizely-sdk/lib/core/event_builder/index.js @@ -1,5 +1,5 @@ /** - * Copyright 2016-2019, Optimizely + * Copyright 2016-2020, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -var enums = require('../../utils/enums'); -var fns = require('../../utils/fns'); -var eventTagUtils = require('../../utils/event_tag_utils'); -var projectConfig = require('../project_config'); -var attributeValidator = require('../../utils/attributes_validator'); +import fns from '../../utils/fns'; +import enums from '../../utils/enums'; +import projectConfig from '../project_config'; +import eventTagUtils from '../../utils/event_tag_utils'; +import attributeValidator from '../../utils/attributes_validator'; var ACTIVATE_EVENT_KEY = 'campaign_activated'; var CUSTOM_ATTRIBUTE_FEATURE_TYPE = 'custom'; @@ -153,62 +153,65 @@ function getVisitorSnapshot(configObj, eventKey, eventTags, logger) { return snapshot; } -module.exports = { - /** - * Create impression event params to be sent to the logging endpoint - * @param {Object} options Object containing values needed to build impression event - * @param {Object} options.attributes Object representing user attributes and values which need to be recorded - * @param {string} options.clientEngine The client we are using: node or javascript - * @param {string} options.clientVersion The version of the client - * @param {Object} options.configObj Object representing project configuration, including datafile information and mappings for quick lookup - * @param {string} options.experimentId Experiment for which impression needs to be recorded - * @param {string} options.userId ID for user - * @param {string} options.variationId ID for variation which would be presented to user - * @return {Object} Params to be used in impression event logging endpoint call - */ - getImpressionEvent: function(options) { - var impressionEvent = { - httpVerb: HTTP_VERB, - }; - - var commonParams = getCommonEventParams(options); - impressionEvent.url = ENDPOINT; - - var impressionEventParams = getImpressionEventParams(options.configObj, options.experimentId, options.variationId); - // combine Event params into visitor obj - commonParams.visitors[0].snapshots.push(impressionEventParams); - - impressionEvent.params = commonParams; - - return impressionEvent; - }, - - /** - * Create conversion event params to be sent to the logging endpoint - * @param {Object} options Object containing values needed to build conversion event - * @param {Object} options.attributes Object representing user attributes and values which need to be recorded - * @param {string} options.clientEngine The client we are using: node or javascript - * @param {string} options.clientVersion The version of the client - * @param {Object} options.configObj Object representing project configuration, including datafile information and mappings for quick lookup - * @param {string} options.eventKey Event key representing the event which needs to be recorded - * @param {Object} options.eventTags Object with event-specific tags - * @param {Object} options.logger Logger object - * @param {string} options.userId ID for user - * @return {Object} Params to be used in conversion event logging endpoint call - */ - getConversionEvent: function(options) { - var conversionEvent = { - httpVerb: HTTP_VERB, - }; - - var commonParams = getCommonEventParams(options); - conversionEvent.url = ENDPOINT; - - var snapshot = getVisitorSnapshot(options.configObj, options.eventKey, options.eventTags, options.logger); - - commonParams.visitors[0].snapshots = [snapshot]; - conversionEvent.params = commonParams; - - return conversionEvent; - }, +/** + * Create impression event params to be sent to the logging endpoint + * @param {Object} options Object containing values needed to build impression event + * @param {Object} options.attributes Object representing user attributes and values which need to be recorded + * @param {string} options.clientEngine The client we are using: node or javascript + * @param {string} options.clientVersion The version of the client + * @param {Object} options.configObj Object representing project configuration, including datafile information and mappings for quick lookup + * @param {string} options.experimentId Experiment for which impression needs to be recorded + * @param {string} options.userId ID for user + * @param {string} options.variationId ID for variation which would be presented to user + * @return {Object} Params to be used in impression event logging endpoint call + */ +export var getImpressionEvent = function(options) { + var impressionEvent = { + httpVerb: HTTP_VERB, + }; + + var commonParams = getCommonEventParams(options); + impressionEvent.url = ENDPOINT; + + var impressionEventParams = getImpressionEventParams(options.configObj, options.experimentId, options.variationId); + // combine Event params into visitor obj + commonParams.visitors[0].snapshots.push(impressionEventParams); + + impressionEvent.params = commonParams; + + return impressionEvent; +}; + +/** + * Create conversion event params to be sent to the logging endpoint + * @param {Object} options Object containing values needed to build conversion event + * @param {Object} options.attributes Object representing user attributes and values which need to be recorded + * @param {string} options.clientEngine The client we are using: node or javascript + * @param {string} options.clientVersion The version of the client + * @param {Object} options.configObj Object representing project configuration, including datafile information and mappings for quick lookup + * @param {string} options.eventKey Event key representing the event which needs to be recorded + * @param {Object} options.eventTags Object with event-specific tags + * @param {Object} options.logger Logger object + * @param {string} options.userId ID for user + * @return {Object} Params to be used in conversion event logging endpoint call + */ +export var getConversionEvent = function(options) { + var conversionEvent = { + httpVerb: HTTP_VERB, + }; + + var commonParams = getCommonEventParams(options); + conversionEvent.url = ENDPOINT; + + var snapshot = getVisitorSnapshot(options.configObj, options.eventKey, options.eventTags, options.logger); + + commonParams.visitors[0].snapshots = [snapshot]; + conversionEvent.params = commonParams; + + return conversionEvent; +}; + +export default { + getConversionEvent: getConversionEvent, + getImpressionEvent: getImpressionEvent, }; diff --git a/packages/optimizely-sdk/lib/core/event_builder/index.tests.js b/packages/optimizely-sdk/lib/core/event_builder/index.tests.js index d223136e9..11f348ad8 100644 --- a/packages/optimizely-sdk/lib/core/event_builder/index.tests.js +++ b/packages/optimizely-sdk/lib/core/event_builder/index.tests.js @@ -1,5 +1,5 @@ /** - * Copyright 2016-2019, Optimizely + * Copyright 2016-2020, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,15 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -var eventBuilder = require('./index.js'); -var packageJSON = require('../../../package.json'); -var projectConfig = require('../project_config'); -var testData = require('../../tests/test_data'); +import uuid from 'uuid'; +import sinon from 'sinon'; +import { assert } from 'chai'; -var chai = require('chai'); -var assert = chai.assert; -var sinon = require('sinon'); -var uuid = require('uuid'); +import testData from '../../tests/test_data'; +import projectConfig from '../project_config'; +import packageJSON from '../../../package.json'; +import { getConversionEvent, getImpressionEvent} from './index.js'; describe('lib/core/event_builder', function() { describe('APIs', function() { @@ -93,7 +92,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getImpressionEvent(eventOptions); + var actualParams = getImpressionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -154,7 +153,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getImpressionEvent(eventOptions); + var actualParams = getImpressionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -216,7 +215,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getImpressionEvent(eventOptions); + var actualParams = getImpressionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -278,7 +277,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getImpressionEvent(eventOptions); + var actualParams = getImpressionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -334,7 +333,7 @@ describe('lib/core/event_builder', function() { logger: mockLogger, }; - var actualParams = eventBuilder.getImpressionEvent(eventOptions); + var actualParams = getImpressionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -403,7 +402,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getImpressionEvent(eventOptions); + var actualParams = getImpressionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -473,7 +472,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getImpressionEvent(eventOptions); + var actualParams = getImpressionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -558,7 +557,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getImpressionEvent(eventOptions); + var actualParams = getImpressionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -638,7 +637,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getImpressionEvent(eventOptions); + var actualParams = getImpressionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -687,7 +686,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getConversionEvent(eventOptions); + var actualParams = getConversionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -742,7 +741,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getConversionEvent(eventOptions); + var actualParams = getConversionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -796,7 +795,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getConversionEvent(eventOptions); + var actualParams = getConversionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -858,7 +857,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getConversionEvent(eventOptions); + var actualParams = getConversionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -906,7 +905,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getConversionEvent(eventOptions); + var actualParams = getConversionEvent(eventOptions); sinon.assert.calledOnce(mockLogger.log); assert.deepEqual(actualParams, expectedParams); }); @@ -968,7 +967,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getConversionEvent(eventOptions); + var actualParams = getConversionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -1031,7 +1030,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getConversionEvent(eventOptions); + var actualParams = getConversionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -1078,7 +1077,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getConversionEvent(eventOptions); + var actualParams = getConversionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -1151,7 +1150,7 @@ describe('lib/core/event_builder', function() { }, }; - var actualParams = eventBuilder.getConversionEvent(eventOptions); + var actualParams = getConversionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -1205,7 +1204,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getConversionEvent(eventOptions); + var actualParams = getConversionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -1262,7 +1261,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getConversionEvent(eventOptions); + var actualParams = getConversionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -1316,7 +1315,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getConversionEvent(eventOptions); + var actualParams = getConversionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -1372,7 +1371,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getConversionEvent(eventOptions); + var actualParams = getConversionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -1431,7 +1430,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getConversionEvent(eventOptions); + var actualParams = getConversionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -1485,7 +1484,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getConversionEvent(eventOptions); + var actualParams = getConversionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -1541,7 +1540,7 @@ describe('lib/core/event_builder', function() { userId: 'testUser', }; - var actualParams = eventBuilder.getConversionEvent(eventOptions); + var actualParams = getConversionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); @@ -1600,7 +1599,7 @@ describe('lib/core/event_builder', function() { attributes: { $opt_bucketing_id: 'variation' }, }; - var actualParams = eventBuilder.getConversionEvent(eventOptions); + var actualParams = getConversionEvent(eventOptions); assert.deepEqual(actualParams, expectedParams); }); diff --git a/packages/optimizely-sdk/lib/core/notification_center/index.js b/packages/optimizely-sdk/lib/core/notification_center/index.js index 6ae0748ea..2b2e65929 100644 --- a/packages/optimizely-sdk/lib/core/notification_center/index.js +++ b/packages/optimizely-sdk/lib/core/notification_center/index.js @@ -1,5 +1,5 @@ /** - * Copyright 2017, 2019 Optimizely + * Copyright 2017, 2019-2020, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,12 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { sprintf, objectValues } from '@optimizely/js-sdk-utils'; -var enums = require('../../utils/enums'); -var jsSdkUtils = require('@optimizely/js-sdk-utils'); +import { + LOG_LEVEL, + LOG_MESSAGES, + NOTIFICATION_TYPES, +} from '../../utils/enums'; -var LOG_LEVEL = enums.LOG_LEVEL; -var LOG_MESSAGES = enums.LOG_MESSAGES; var MODULE_NAME = 'NOTIFICATION_CENTER'; /** @@ -37,7 +39,7 @@ function NotificationCenter(options) { this.errorHandler = options.errorHandler; this.__notificationListeners = {}; - jsSdkUtils.objectValues(enums.NOTIFICATION_TYPES).forEach( + objectValues(NOTIFICATION_TYPES).forEach( function(notificationTypeEnum) { this.__notificationListeners[notificationTypeEnum] = []; }.bind(this) @@ -57,7 +59,7 @@ function NotificationCenter(options) { */ NotificationCenter.prototype.addNotificationListener = function(notificationType, callback) { try { - var isNotificationTypeValid = jsSdkUtils.objectValues(enums.NOTIFICATION_TYPES).indexOf(notificationType) > -1; + var isNotificationTypeValid = objectValues(NOTIFICATION_TYPES).indexOf(notificationType) > -1; if (!isNotificationTypeValid) { return -1; } @@ -136,7 +138,7 @@ NotificationCenter.prototype.removeNotificationListener = function(listenerId) { */ NotificationCenter.prototype.clearAllNotificationListeners = function() { try { - jsSdkUtils.objectValues(enums.NOTIFICATION_TYPES).forEach( + objectValues(NOTIFICATION_TYPES).forEach( function(notificationTypeEnum) { this.__notificationListeners[notificationTypeEnum] = []; }.bind(this) @@ -149,7 +151,7 @@ NotificationCenter.prototype.clearAllNotificationListeners = function() { /** * Remove all previously added notification listeners for the argument type - * @param {string} notificationType One of enums.NOTIFICATION_TYPES + * @param {string} notificationType One of NOTIFICATION_TYPES */ NotificationCenter.prototype.clearNotificationListeners = function(notificationType) { try { @@ -163,7 +165,7 @@ NotificationCenter.prototype.clearNotificationListeners = function(notificationT /** * Fires notifications for the argument type. All registered callbacks for this type will be * called. The notificationData object will be passed on to callbacks called. - * @param {string} notificationType One of enums.NOTIFICATION_TYPES + * @param {string} notificationType One of NOTIFICATION_TYPES * @param {Object} notificationData Will be passed to callbacks called */ NotificationCenter.prototype.sendNotifications = function(notificationType, notificationData) { @@ -176,7 +178,7 @@ NotificationCenter.prototype.sendNotifications = function(notificationType, noti } catch (ex) { this.logger.log( LOG_LEVEL.ERROR, - jsSdkUtils.sprintf(LOG_MESSAGES.NOTIFICATION_LISTENER_EXCEPTION, MODULE_NAME, notificationType, ex.message) + sprintf(LOG_MESSAGES.NOTIFICATION_LISTENER_EXCEPTION, MODULE_NAME, notificationType, ex.message) ); } }.bind(this) @@ -187,14 +189,16 @@ NotificationCenter.prototype.sendNotifications = function(notificationType, noti } }; -module.exports = { - /** - * Create an instance of NotificationCenter - * @param {Object} options - * @param {Object} options.logger An instance of a logger to log messages with - * @returns {Object} An instance of NotificationCenter - */ - createNotificationCenter: function(options) { - return new NotificationCenter(options); - }, +/** + * Create an instance of NotificationCenter + * @param {Object} options + * @param {Object} options.logger An instance of a logger to log messages with + * @returns {Object} An instance of NotificationCenter + */ +export var createNotificationCenter = function(options) { + return new NotificationCenter(options); +}; + +export default { + createNotificationCenter: createNotificationCenter, }; diff --git a/packages/optimizely-sdk/lib/core/notification_center/index.tests.js b/packages/optimizely-sdk/lib/core/notification_center/index.tests.js index 1a5f119f5..1a38beffd 100644 --- a/packages/optimizely-sdk/lib/core/notification_center/index.tests.js +++ b/packages/optimizely-sdk/lib/core/notification_center/index.tests.js @@ -13,15 +13,15 @@ * See the License for the specific language governing permissions and * * limitations under the License. * ***************************************************************************/ +import sinon from 'sinon'; +import { assert } from 'chai'; + +import NotificationCenter from './'; +import enums from '../../utils/enums'; +import logger from '../../plugins/logger'; +import errorHandler from '../../plugins/error_handler'; -var NotificationCenter = require('./'); -var errorHandler = require('../../plugins/error_handler'); -var logger = require('../../plugins/logger'); -var enums = require('../../utils/enums'); var LOG_LEVEL = enums.LOG_LEVEL; -var chai = require('chai'); -var sinon = require('sinon'); -var assert = chai.assert; describe('lib/core/notification_center', function() { describe('APIs', function() { diff --git a/packages/optimizely-sdk/lib/core/optimizely_config/index.js b/packages/optimizely-sdk/lib/core/optimizely_config/index.js index e30c3d183..43527fe1d 100644 --- a/packages/optimizely-sdk/lib/core/optimizely_config/index.js +++ b/packages/optimizely-sdk/lib/core/optimizely_config/index.js @@ -1,5 +1,5 @@ /** - * Copyright 2019, Optimizely + * Copyright 2019-2020, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -var projectConfig = require('../project_config'); +import { isFeatureExperiment } from '../project_config'; // Get Experiment Ids which are part of rollouts function getRolloutExperimentIds(rollouts) { @@ -44,7 +44,7 @@ function getExperimentsMap(configObj) { key: variation.key, variablesMap: getMergedVariablesMap(configObj, variation, experiment.id, featureVariablesMap), }; - if (projectConfig.isFeatureExperiment(configObj, experiment.id)) { + if (isFeatureExperiment(configObj, experiment.id)) { variations[variation.key].featureEnabled = variation.featureEnabled; } return variations; @@ -110,14 +110,12 @@ function getFeaturesMap(configObj, allExperiments) { }, {}); } -module.exports = { - getOptimizelyConfig: function(configObj) { - // Fetch all feature variables from feature flags to merge them with variation variables - var experimentsMap = getExperimentsMap(configObj); - return { - experimentsMap: experimentsMap, - featuresMap: getFeaturesMap(configObj, experimentsMap), - revision: configObj.revision, - }; - }, +export var getOptimizelyConfig = function(configObj) { + // Fetch all feature variables from feature flags to merge them with variation variables + var experimentsMap = getExperimentsMap(configObj); + return { + experimentsMap: experimentsMap, + featuresMap: getFeaturesMap(configObj, experimentsMap), + revision: configObj.revision, + }; }; diff --git a/packages/optimizely-sdk/lib/core/optimizely_config/index.tests.js b/packages/optimizely-sdk/lib/core/optimizely_config/index.tests.js index bcacbb233..d17a9bd62 100644 --- a/packages/optimizely-sdk/lib/core/optimizely_config/index.tests.js +++ b/packages/optimizely-sdk/lib/core/optimizely_config/index.tests.js @@ -1,5 +1,5 @@ /** - * Copyright 2019, Optimizely + * Copyright 2019-2020, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,11 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -var assert = require('chai').assert; -var cloneDeep = require('lodash/cloneDeep'); -var datafile = require('../../tests/test_data').getTestProjectConfigWithFeatures(); -var projectConfig = require('../project_config'); -var optimizelyConfig = require('./index'); +import { assert } from 'chai'; +import { cloneDeep } from 'lodash'; + +import { getOptimizelyConfig } from './index'; +import { createProjectConfig } from '../project_config'; +import { getTestProjectConfigWithFeatures } from '../../tests/test_data'; + +var datafile = getTestProjectConfigWithFeatures(); var getAllExperimentsFromDatafile = function(datafile) { var allExperiments = []; @@ -37,8 +40,8 @@ describe('lib/core/optimizely_config', function() { var optimizelyConfigObject; var projectConfigObject; beforeEach(function() { - projectConfigObject = projectConfig.createProjectConfig(cloneDeep(datafile)); - optimizelyConfigObject = optimizelyConfig.getOptimizelyConfig(projectConfigObject); + projectConfigObject = createProjectConfig(cloneDeep(datafile)); + optimizelyConfigObject = getOptimizelyConfig(projectConfigObject); }); it('should return all experiments except rollouts', function() { diff --git a/packages/optimizely-sdk/lib/core/project_config/index.js b/packages/optimizely-sdk/lib/core/project_config/index.js index c8b0ea337..7624a266b 100644 --- a/packages/optimizely-sdk/lib/core/project_config/index.js +++ b/packages/optimizely-sdk/lib/core/project_config/index.js @@ -1,5 +1,5 @@ /** - * Copyright 2016-2019, Optimizely + * Copyright 2016-2020, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,502 +13,526 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -var fns = require('../../utils/fns'); -var enums = require('../../utils/enums'); -var jsSdkUtils = require('@optimizely/js-sdk-utils'); -var configValidator = require('../../utils/config_validator'); +import { sprintf, objectValues } from '@optimizely/js-sdk-utils'; + +import fns from '../../utils/fns'; +import { + ERROR_MESSAGES, + LOG_MESSAGES, + LOG_LEVEL, + FEATURE_VARIABLE_TYPES, +} from '../../utils/enums'; +import configValidator from '../../utils/config_validator'; var EXPERIMENT_RUNNING_STATUS = 'Running'; var RESERVED_ATTRIBUTE_PREFIX = '$opt_'; var MODULE_NAME = 'PROJECT_CONFIG'; -var ERROR_MESSAGES = enums.ERROR_MESSAGES; -var LOG_MESSAGES = enums.LOG_MESSAGES; -var LOG_LEVEL = enums.LOG_LEVEL; -var FEATURE_VARIABLE_TYPES = enums.FEATURE_VARIABLE_TYPES; +/** + * Creates projectConfig object to be used for quick project property lookup + * @param {Object} datafile JSON datafile representing the project + * @return {Object} Object representing project configuration + */ +export var createProjectConfig = function(datafile) { + var projectConfig = fns.assign({}, datafile); -module.exports = { - /** - * Creates projectConfig object to be used for quick project property lookup - * @param {Object} datafile JSON datafile representing the project - * @return {Object} Object representing project configuration + /* + * Conditions of audiences in projectConfig.typedAudiences are not + * expected to be string-encoded as they are here in projectConfig.audiences. */ - createProjectConfig: function(datafile) { - var projectConfig = fns.assign({}, datafile); - - /* - * Conditions of audiences in projectConfig.typedAudiences are not - * expected to be string-encoded as they are here in projectConfig.audiences. - */ - (projectConfig.audiences || []).forEach(function(audience) { - audience.conditions = JSON.parse(audience.conditions); + (projectConfig.audiences || []).forEach(function(audience) { + audience.conditions = JSON.parse(audience.conditions); + }); + projectConfig.audiencesById = fns.keyBy(projectConfig.audiences, 'id'); + fns.assign(projectConfig.audiencesById, fns.keyBy(projectConfig.typedAudiences, 'id')); + + projectConfig.attributeKeyMap = fns.keyBy(projectConfig.attributes, 'key'); + projectConfig.eventKeyMap = fns.keyBy(projectConfig.events, 'key'); + projectConfig.groupIdMap = fns.keyBy(projectConfig.groups, 'id'); + + var experiments; + Object.keys(projectConfig.groupIdMap || {}).forEach(function(Id) { + experiments = projectConfig.groupIdMap[Id].experiments; + (experiments || []).forEach(function(experiment) { + projectConfig.experiments.push(fns.assign(experiment, { groupId: Id })); }); - projectConfig.audiencesById = fns.keyBy(projectConfig.audiences, 'id'); - fns.assign(projectConfig.audiencesById, fns.keyBy(projectConfig.typedAudiences, 'id')); - - projectConfig.attributeKeyMap = fns.keyBy(projectConfig.attributes, 'key'); - projectConfig.eventKeyMap = fns.keyBy(projectConfig.events, 'key'); - projectConfig.groupIdMap = fns.keyBy(projectConfig.groups, 'id'); - - var experiments; - Object.keys(projectConfig.groupIdMap || {}).forEach(function(Id) { - experiments = projectConfig.groupIdMap[Id].experiments; - (experiments || []).forEach(function(experiment) { - projectConfig.experiments.push(fns.assign(experiment, { groupId: Id })); - }); + }); + + projectConfig.rolloutIdMap = fns.keyBy(projectConfig.rollouts || [], 'id'); + objectValues(projectConfig.rolloutIdMap || {}).forEach(function (rollout) { + (rollout.experiments || []).forEach(function(experiment) { + projectConfig.experiments.push(experiment); + // Creates { : } map inside of the experiment + experiment.variationKeyMap = fns.keyBy(experiment.variations, 'key'); }); + }); + + projectConfig.experimentKeyMap = fns.keyBy(projectConfig.experiments, 'key'); + projectConfig.experimentIdMap = fns.keyBy(projectConfig.experiments, 'id'); + + projectConfig.variationIdMap = {}; + projectConfig.variationVariableUsageMap = {}; + (projectConfig.experiments || []).forEach(function(experiment) { + // Creates { : } map inside of the experiment + experiment.variationKeyMap = fns.keyBy(experiment.variations, 'key'); + + // Creates { : { key: , id: } } mapping for quick lookup + fns.assign(projectConfig.variationIdMap, fns.keyBy(experiment.variations, 'id')); + objectValues(experiment.variationKeyMap || {}).forEach(function(variation) { + if (variation.variables) { + projectConfig.variationVariableUsageMap[variation.id] = fns.keyBy(variation.variables, 'id'); + } + }); + }); + + // Object containing experiment Ids that exist in any feature + // for checking that experiment is a feature experiment or not. + projectConfig.experimentFeatureMap = {}; + + projectConfig.featureKeyMap = fns.keyBy(projectConfig.featureFlags || [], 'key'); + objectValues(projectConfig.featureKeyMap || {}).forEach(function(feature) { + feature.variableKeyMap = fns.keyBy(feature.variables, 'key'); + (feature.experimentIds || []).forEach(function(experimentId) { + // Add this experiment in experiment-feature map. + if (projectConfig.experimentFeatureMap[experimentId]) { + projectConfig.experimentFeatureMap[experimentId].push(feature.id); + } else { + projectConfig.experimentFeatureMap[experimentId] = [feature.id]; + } - projectConfig.rolloutIdMap = fns.keyBy(projectConfig.rollouts || [], 'id'); - jsSdkUtils.objectValues(projectConfig.rolloutIdMap || {}).forEach(function (rollout) { - (rollout.experiments || []).forEach(function(experiment) { - projectConfig.experiments.push(experiment); - // Creates { : } map inside of the experiment - experiment.variationKeyMap = fns.keyBy(experiment.variations, 'key'); - }); + var experimentInFeature = projectConfig.experimentIdMap[experimentId]; + // Experiments in feature can only belong to one mutex group. + if (experimentInFeature.groupId && !feature.groupId) { + feature.groupId = experimentInFeature.groupId; + } }); + }); - projectConfig.experimentKeyMap = fns.keyBy(projectConfig.experiments, 'key'); - projectConfig.experimentIdMap = fns.keyBy(projectConfig.experiments, 'id'); + return projectConfig; +}; - projectConfig.variationIdMap = {}; - projectConfig.variationVariableUsageMap = {}; - (projectConfig.experiments || []).forEach(function(experiment) { - // Creates { : } map inside of the experiment - experiment.variationKeyMap = fns.keyBy(experiment.variations, 'key'); +/** + * Get experiment ID for the provided experiment key + * @param {Object} projectConfig Object representing project configuration + * @param {string} experimentKey Experiment key for which ID is to be determined + * @return {string} Experiment ID corresponding to the provided experiment key + * @throws If experiment key is not in datafile + */ +export var getExperimentId = function(projectConfig, experimentKey) { + var experiment = projectConfig.experimentKeyMap[experimentKey]; + if (!experiment) { + throw new Error(sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); + } + return experiment.id; +}; - // Creates { : { key: , id: } } mapping for quick lookup - fns.assign(projectConfig.variationIdMap, fns.keyBy(experiment.variations, 'id')); - jsSdkUtils.objectValues(experiment.variationKeyMap || {}).forEach(function(variation) { - if (variation.variables) { - projectConfig.variationVariableUsageMap[variation.id] = fns.keyBy(variation.variables, 'id'); - } - }); - }); +/** + * Get layer ID for the provided experiment key + * @param {Object} projectConfig Object representing project configuration + * @param {string} experimentId Experiment ID for which layer ID is to be determined + * @return {string} Layer ID corresponding to the provided experiment key + * @throws If experiment key is not in datafile + */ +export var getLayerId = function(projectConfig, experimentId) { + var experiment = projectConfig.experimentIdMap[experimentId]; + if (!experiment) { + throw new Error(sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_ID, MODULE_NAME, experimentId)); + } + return experiment.layerId; +}; - // Object containing experiment Ids that exist in any feature - // for checking that experiment is a feature experiment or not. - projectConfig.experimentFeatureMap = {}; - - projectConfig.featureKeyMap = fns.keyBy(projectConfig.featureFlags || [], 'key'); - jsSdkUtils.objectValues(projectConfig.featureKeyMap || {}).forEach(function(feature) { - feature.variableKeyMap = fns.keyBy(feature.variables, 'key'); - (feature.experimentIds || []).forEach(function(experimentId) { - // Add this experiment in experiment-feature map. - if (projectConfig.experimentFeatureMap[experimentId]) { - projectConfig.experimentFeatureMap[experimentId].push(feature.id); - } else { - projectConfig.experimentFeatureMap[experimentId] = [feature.id]; - } - - var experimentInFeature = projectConfig.experimentIdMap[experimentId]; - // Experiments in feature can only belong to one mutex group. - if (experimentInFeature.groupId && !feature.groupId) { - feature.groupId = experimentInFeature.groupId; - } - }); - }); +/** + * Get attribute ID for the provided attribute key + * @param {Object} projectConfig Object representing project configuration + * @param {string} attributeKey Attribute key for which ID is to be determined + * @param {Object} logger + * @return {string|null} Attribute ID corresponding to the provided attribute key. Attribute key if it is a reserved attribute. + */ +export var getAttributeId = function(projectConfig, attributeKey, logger) { + var attribute = projectConfig.attributeKeyMap[attributeKey]; + var hasReservedPrefix = attributeKey.indexOf(RESERVED_ATTRIBUTE_PREFIX) === 0; + if (attribute) { + if (hasReservedPrefix) { + logger.log( + LOG_LEVEL.WARN, + sprintf( + 'Attribute %s unexpectedly has reserved prefix %s; using attribute ID instead of reserved attribute name.', + attributeKey, + RESERVED_ATTRIBUTE_PREFIX + ) + ); + } + return attribute.id; + } else if (hasReservedPrefix) { + return attributeKey; + } - return projectConfig; - }, + logger.log(LOG_LEVEL.DEBUG, sprintf(ERROR_MESSAGES.UNRECOGNIZED_ATTRIBUTE, MODULE_NAME, attributeKey)); + return null; +}; - /** - * Get experiment ID for the provided experiment key - * @param {Object} projectConfig Object representing project configuration - * @param {string} experimentKey Experiment key for which ID is to be determined - * @return {string} Experiment ID corresponding to the provided experiment key - * @throws If experiment key is not in datafile - */ - getExperimentId: function(projectConfig, experimentKey) { +/** + * Get event ID for the provided + * @param {Object} projectConfig Object representing project configuration + * @param {string} eventKey Event key for which ID is to be determined + * @return {string|null} Event ID corresponding to the provided event key + */ +export var getEventId = function(projectConfig, eventKey) { + var event = projectConfig.eventKeyMap[eventKey]; + if (event) { + return event.id; + } + return null; +}; + +/** + * Get experiment status for the provided experiment key + * @param {Object} projectConfig Object representing project configuration + * @param {string} experimentKey Experiment key for which status is to be determined + * @return {string} Experiment status corresponding to the provided experiment key + * @throws If experiment key is not in datafile + */ +export var getExperimentStatus = function(projectConfig, experimentKey) { + var experiment = projectConfig.experimentKeyMap[experimentKey]; + if (!experiment) { + throw new Error(sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); + } + return experiment.status; +}; + +/** + * Returns whether experiment has a status of 'Running' + * @param {Object} projectConfig Object representing project configuration + * @param {string} experimentKey Experiment key for which status is to be compared with 'Running' + * @return {Boolean} true if experiment status is set to 'Running', false otherwise + */ +export var isActive = function(projectConfig, experimentKey) { + return this.getExperimentStatus(projectConfig, experimentKey) === EXPERIMENT_RUNNING_STATUS; +}; + +/** + * Determine for given experiment if event is running, which determines whether should be dispatched or not + */ +export var isRunning = function(projectConfig, experimentKey) { + return this.getExperimentStatus(projectConfig, experimentKey) === EXPERIMENT_RUNNING_STATUS; +}; + +/** + * Get audience conditions for the experiment + * @param {Object} projectConfig Object representing project configuration + * @param {string} experimentKey Experiment key for which audience conditions are to be determined + * @return {Array} Audience conditions for the experiment - can be an array of audience IDs, or a + * nested array of conditions + * Examples: ["5", "6"], ["and", ["or", "1", "2"], "3"] + * @throws If experiment key is not in datafile + */ +export var getExperimentAudienceConditions = function(projectConfig, experimentKey) { + var experiment = projectConfig.experimentKeyMap[experimentKey]; + if (!experiment) { + throw new Error(sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); + } + + return experiment.audienceConditions || experiment.audienceIds; +}; + +/** + * Get variation key given experiment key and variation ID + * @param {Object} projectConfig Object representing project configuration + * @param {string} variationId ID of the variation + * @return {string} Variation key or null if the variation ID is not found + */ +export var getVariationKeyFromId = function(projectConfig, variationId) { + if (projectConfig.variationIdMap.hasOwnProperty(variationId)) { + return projectConfig.variationIdMap[variationId].key; + } + return null; +}; + +/** + * Get the variation ID given the experiment key and variation key + * @param {Object} projectConfig Object representing project configuration + * @param {string} experimentKey Key of the experiment the variation belongs to + * @param {string} variationKey The variation key + * @return {string} the variation ID + */ +export var getVariationIdFromExperimentAndVariationKey = function(projectConfig, experimentKey, variationKey) { + var experiment = projectConfig.experimentKeyMap[experimentKey]; + if (experiment.variationKeyMap.hasOwnProperty(variationKey)) { + return experiment.variationKeyMap[variationKey].id; + } + return null; +}; + +/** + * Get experiment from provided experiment key + * @param {Object} projectConfig Object representing project configuration + * @param {string} experimentKey Event key for which experiment IDs are to be retrieved + * @return {Object} experiment + * @throws If experiment key is not in datafile + */ +export var getExperimentFromKey = function(projectConfig, experimentKey) { + if (projectConfig.experimentKeyMap.hasOwnProperty(experimentKey)) { var experiment = projectConfig.experimentKeyMap[experimentKey]; - if (!experiment) { - throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); + if (experiment) { + return experiment; } - return experiment.id; - }, - - /** - * Get layer ID for the provided experiment key - * @param {Object} projectConfig Object representing project configuration - * @param {string} experimentId Experiment ID for which layer ID is to be determined - * @return {string} Layer ID corresponding to the provided experiment key - * @throws If experiment key is not in datafile - */ - getLayerId: function(projectConfig, experimentId) { + } + + throw new Error(sprintf(ERROR_MESSAGES.EXPERIMENT_KEY_NOT_IN_DATAFILE, MODULE_NAME, experimentKey)); +}; + +/** + * Given an experiment key, returns the traffic allocation within that experiment + * @param {Object} projectConfig Object representing project configuration + * @param {string} experimentKey Key representing the experiment + * @return {Array} Traffic allocation for the experiment + * @throws If experiment key is not in datafile + */ +export var getTrafficAllocation = function(projectConfig, experimentKey) { + var experiment = projectConfig.experimentKeyMap[experimentKey]; + if (!experiment) { + throw new Error(sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); + } + return experiment.trafficAllocation; +}; + +/** + * Get experiment from provided experiment id. Log an error if no experiment + * exists in the project config with the given ID. + * @param {Object} projectConfig Object representing project configuration + * @param {string} experimentId ID of desired experiment object + * @return {Object} Experiment object + */ +export var getExperimentFromId = function(projectConfig, experimentId, logger) { + if (projectConfig.experimentIdMap.hasOwnProperty(experimentId)) { var experiment = projectConfig.experimentIdMap[experimentId]; - if (!experiment) { - throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_ID, MODULE_NAME, experimentId)); - } - return experiment.layerId; - }, - - /** - * Get attribute ID for the provided attribute key - * @param {Object} projectConfig Object representing project configuration - * @param {string} attributeKey Attribute key for which ID is to be determined - * @param {Object} logger - * @return {string|null} Attribute ID corresponding to the provided attribute key. Attribute key if it is a reserved attribute. - */ - getAttributeId: function(projectConfig, attributeKey, logger) { - var attribute = projectConfig.attributeKeyMap[attributeKey]; - var hasReservedPrefix = attributeKey.indexOf(RESERVED_ATTRIBUTE_PREFIX) === 0; - if (attribute) { - if (hasReservedPrefix) { - logger.log( - LOG_LEVEL.WARN, - jsSdkUtils.sprintf( - 'Attribute %s unexpectedly has reserved prefix %s; using attribute ID instead of reserved attribute name.', - attributeKey, - RESERVED_ATTRIBUTE_PREFIX - ) - ); - } - return attribute.id; - } else if (hasReservedPrefix) { - return attributeKey; + if (experiment) { + return experiment; } + } - logger.log(LOG_LEVEL.DEBUG, jsSdkUtils.sprintf(ERROR_MESSAGES.UNRECOGNIZED_ATTRIBUTE, MODULE_NAME, attributeKey)); - return null; - }, + logger.log(LOG_LEVEL.ERROR, sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_ID, MODULE_NAME, experimentId)); + return null; +}; - /** - * Get event ID for the provided - * @param {Object} projectConfig Object representing project configuration - * @param {string} eventKey Event key for which ID is to be determined - * @return {string|null} Event ID corresponding to the provided event key - */ - getEventId: function(projectConfig, eventKey) { - var event = projectConfig.eventKeyMap[eventKey]; - if (event) { - return event.id; - } - return null; - }, - - /** - * Get experiment status for the provided experiment key - * @param {Object} projectConfig Object representing project configuration - * @param {string} experimentKey Experiment key for which status is to be determined - * @return {string} Experiment status corresponding to the provided experiment key - * @throws If experiment key is not in datafile - */ - getExperimentStatus: function(projectConfig, experimentKey) { - var experiment = projectConfig.experimentKeyMap[experimentKey]; - if (!experiment) { - throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); +/** + * Get feature from provided feature key. Log an error if no feature exists in + * the project config with the given key. + * @param {Object} projectConfig + * @param {string} featureKey + * @param {Object} logger + * @return {Object|null} Feature object, or null if no feature with the given + * key exists + */ +export var getFeatureFromKey = function(projectConfig, featureKey, logger) { + if (projectConfig.featureKeyMap.hasOwnProperty(featureKey)) { + var feature = projectConfig.featureKeyMap[featureKey]; + if (feature) { + return feature; } - return experiment.status; - }, - - /** - * Returns whether experiment has a status of 'Running' - * @param {Object} projectConfig Object representing project configuration - * @param {string} experimentKey Experiment key for which status is to be compared with 'Running' - * @return {Boolean} true if experiment status is set to 'Running', false otherwise - */ - isActive: function(projectConfig, experimentKey) { - return module.exports.getExperimentStatus(projectConfig, experimentKey) === EXPERIMENT_RUNNING_STATUS; - }, + } - /** - * Determine for given experiment if event is running, which determines whether should be dispatched or not - */ - isRunning: function(projectConfig, experimentKey) { - return module.exports.getExperimentStatus(projectConfig, experimentKey) === EXPERIMENT_RUNNING_STATUS; - }, - - /** - * Get audience conditions for the experiment - * @param {Object} projectConfig Object representing project configuration - * @param {string} experimentKey Experiment key for which audience conditions are to be determined - * @return {Array} Audience conditions for the experiment - can be an array of audience IDs, or a - * nested array of conditions - * Examples: ["5", "6"], ["and", ["or", "1", "2"], "3"] - * @throws If experiment key is not in datafile - */ - getExperimentAudienceConditions: function(projectConfig, experimentKey) { - var experiment = projectConfig.experimentKeyMap[experimentKey]; - if (!experiment) { - throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); - } + logger.log(LOG_LEVEL.ERROR, sprintf(ERROR_MESSAGES.FEATURE_NOT_IN_DATAFILE, MODULE_NAME, featureKey)); + return null; +}; + +/** + * Get the variable with the given key associated with the feature with the + * given key. If the feature key or the variable key are invalid, log an error + * message. + * @param {Object} projectConfig + * @param {string} featureKey + * @param {string} variableKey + * @param {Object} logger + * @return {Object|null} Variable object, or null one or both of the given + * feature and variable keys are invalid + */ +export var getVariableForFeature = function(projectConfig, featureKey, variableKey, logger) { + var feature = projectConfig.featureKeyMap[featureKey]; + if (!feature) { + logger.log(LOG_LEVEL.ERROR, sprintf(ERROR_MESSAGES.FEATURE_NOT_IN_DATAFILE, MODULE_NAME, featureKey)); + return null; + } + + var variable = feature.variableKeyMap[variableKey]; + if (!variable) { + logger.log( + LOG_LEVEL.ERROR, + sprintf(ERROR_MESSAGES.VARIABLE_KEY_NOT_IN_DATAFILE, MODULE_NAME, variableKey, featureKey) + ); + return null; + } - return experiment.audienceConditions || experiment.audienceIds; - }, + return variable; +}; - /** - * Get variation key given experiment key and variation ID - * @param {Object} projectConfig Object representing project configuration - * @param {string} variationId ID of the variation - * @return {string} Variation key or null if the variation ID is not found - */ - getVariationKeyFromId: function(projectConfig, variationId) { - if (projectConfig.variationIdMap.hasOwnProperty(variationId)) { - return projectConfig.variationIdMap[variationId].key; - } +/** + * Get the value of the given variable for the given variation. If the given + * variable has no value for the given variation, return null. Log an error message if the variation is invalid. If the + * variable or variation are invalid, return null. + * @param {Object} projectConfig + * @param {Object} variable + * @param {Object} variation + * @param {Object} logger + * @return {string|null} The value of the given variable for the given + * variation, or null if the given variable has no value + * for the given variation or if the variation or variable are invalid + */ +export var getVariableValueForVariation = function(projectConfig, variable, variation, logger) { + if (!variable || !variation) { return null; - }, - - /** - * Get the variation ID given the experiment key and variation key - * @param {Object} projectConfig Object representing project configuration - * @param {string} experimentKey Key of the experiment the variation belongs to - * @param {string} variationKey The variation key - * @return {string} the variation ID - */ - getVariationIdFromExperimentAndVariationKey: function(projectConfig, experimentKey, variationKey) { - var experiment = projectConfig.experimentKeyMap[experimentKey]; - if (experiment.variationKeyMap.hasOwnProperty(variationKey)) { - return experiment.variationKeyMap[variationKey].id; - } + } + + if (!projectConfig.variationVariableUsageMap.hasOwnProperty(variation.id)) { + logger.log( + LOG_LEVEL.ERROR, + sprintf(ERROR_MESSAGES.VARIATION_ID_NOT_IN_DATAFILE_NO_EXPERIMENT, MODULE_NAME, variation.id) + ); return null; - }, - - /** - * Get experiment from provided experiment key - * @param {Object} projectConfig Object representing project configuration - * @param {string} experimentKey Event key for which experiment IDs are to be retrieved - * @return {Object} experiment - * @throws If experiment key is not in datafile - */ - getExperimentFromKey: function(projectConfig, experimentKey) { - if (projectConfig.experimentKeyMap.hasOwnProperty(experimentKey)) { - var experiment = projectConfig.experimentKeyMap[experimentKey]; - if (experiment) { - return experiment; - } - } + } - throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.EXPERIMENT_KEY_NOT_IN_DATAFILE, MODULE_NAME, experimentKey)); - }, + var variableUsages = projectConfig.variationVariableUsageMap[variation.id]; + var variableUsage = variableUsages[variable.id]; - /** - * Given an experiment key, returns the traffic allocation within that experiment - * @param {Object} projectConfig Object representing project configuration - * @param {string} experimentKey Key representing the experiment - * @return {Array} Traffic allocation for the experiment - * @throws If experiment key is not in datafile - */ - getTrafficAllocation: function(projectConfig, experimentKey) { - var experiment = projectConfig.experimentKeyMap[experimentKey]; - if (!experiment) { - throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); - } - return experiment.trafficAllocation; - }, - - /** - * Get experiment from provided experiment id. Log an error if no experiment - * exists in the project config with the given ID. - * @param {Object} projectConfig Object representing project configuration - * @param {string} experimentId ID of desired experiment object - * @return {Object} Experiment object - */ - getExperimentFromId: function(projectConfig, experimentId, logger) { - if (projectConfig.experimentIdMap.hasOwnProperty(experimentId)) { - var experiment = projectConfig.experimentIdMap[experimentId]; - if (experiment) { - return experiment; + return variableUsage ? variableUsage.value : null; +}; + +/** + * Given a variable value in string form, try to cast it to the argument type. + * If the type cast succeeds, return the type casted value, otherwise log an + * error and return null. + * @param {string} variableValue Variable value in string form + * @param {string} variableType Type of the variable whose value was passed + * in the first argument. Must be one of + * FEATURE_VARIABLE_TYPES in + * lib/utils/enums/index.js. The return value's + * type is determined by this argument (boolean + * for BOOLEAN, number for INTEGER or DOUBLE, + * and string for STRING). + * @param {Object} logger Logger instance + * @returns {*} Variable value of the appropriate type, or + * null if the type cast failed + */ +export var getTypeCastValue = function(variableValue, variableType, logger) { + var castValue; + + switch (variableType) { + case FEATURE_VARIABLE_TYPES.BOOLEAN: + if (variableValue !== 'true' && variableValue !== 'false') { + logger.log( + LOG_LEVEL.ERROR, + sprintf(ERROR_MESSAGES.UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType) + ); + castValue = null; + } else { + castValue = variableValue === 'true'; } - } + break; - logger.log(LOG_LEVEL.ERROR, jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_ID, MODULE_NAME, experimentId)); - return null; - }, - - /** - * Get feature from provided feature key. Log an error if no feature exists in - * the project config with the given key. - * @param {Object} projectConfig - * @param {string} featureKey - * @param {Object} logger - * @return {Object|null} Feature object, or null if no feature with the given - * key exists - */ - getFeatureFromKey: function(projectConfig, featureKey, logger) { - if (projectConfig.featureKeyMap.hasOwnProperty(featureKey)) { - var feature = projectConfig.featureKeyMap[featureKey]; - if (feature) { - return feature; + case FEATURE_VARIABLE_TYPES.INTEGER: + castValue = parseInt(variableValue, 10); + if (isNaN(castValue)) { + logger.log( + LOG_LEVEL.ERROR, + sprintf(ERROR_MESSAGES.UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType) + ); + castValue = null; } - } + break; - logger.log(LOG_LEVEL.ERROR, jsSdkUtils.sprintf(ERROR_MESSAGES.FEATURE_NOT_IN_DATAFILE, MODULE_NAME, featureKey)); - return null; - }, - - /** - * Get the variable with the given key associated with the feature with the - * given key. If the feature key or the variable key are invalid, log an error - * message. - * @param {Object} projectConfig - * @param {string} featureKey - * @param {string} variableKey - * @param {Object} logger - * @return {Object|null} Variable object, or null one or both of the given - * feature and variable keys are invalid - */ - getVariableForFeature: function(projectConfig, featureKey, variableKey, logger) { - var feature = projectConfig.featureKeyMap[featureKey]; - if (!feature) { - logger.log(LOG_LEVEL.ERROR, jsSdkUtils.sprintf(ERROR_MESSAGES.FEATURE_NOT_IN_DATAFILE, MODULE_NAME, featureKey)); - return null; - } + case FEATURE_VARIABLE_TYPES.DOUBLE: + castValue = parseFloat(variableValue); + if (isNaN(castValue)) { + logger.log( + LOG_LEVEL.ERROR, + sprintf(ERROR_MESSAGES.UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType) + ); + castValue = null; + } + break; - var variable = feature.variableKeyMap[variableKey]; - if (!variable) { - logger.log( - LOG_LEVEL.ERROR, - jsSdkUtils.sprintf(ERROR_MESSAGES.VARIABLE_KEY_NOT_IN_DATAFILE, MODULE_NAME, variableKey, featureKey) - ); - return null; - } + default: + // type is STRING + castValue = variableValue; + break; + } - return variable; - }, - - /** - * Get the value of the given variable for the given variation. If the given - * variable has no value for the given variation, return null. Log an error message if the variation is invalid. If the - * variable or variation are invalid, return null. - * @param {Object} projectConfig - * @param {Object} variable - * @param {Object} variation - * @param {Object} logger - * @return {string|null} The value of the given variable for the given - * variation, or null if the given variable has no value - * for the given variation or if the variation or variable are invalid - */ - getVariableValueForVariation: function(projectConfig, variable, variation, logger) { - if (!variable || !variation) { - return null; - } + return castValue; +}; - if (!projectConfig.variationVariableUsageMap.hasOwnProperty(variation.id)) { - logger.log( - LOG_LEVEL.ERROR, - jsSdkUtils.sprintf(ERROR_MESSAGES.VARIATION_ID_NOT_IN_DATAFILE_NO_EXPERIMENT, MODULE_NAME, variation.id) - ); - return null; - } +/** + * Returns an object containing all audiences in the project config. Keys are audience IDs + * and values are audience objects. + * @param projectConfig + * @returns {Object} + */ +export var getAudiencesById = function(projectConfig) { + return projectConfig.audiencesById; +}; - var variableUsages = projectConfig.variationVariableUsageMap[variation.id]; - var variableUsage = variableUsages[variable.id]; - - return variableUsage ? variableUsage.value : null; - }, - - /** - * Given a variable value in string form, try to cast it to the argument type. - * If the type cast succeeds, return the type casted value, otherwise log an - * error and return null. - * @param {string} variableValue Variable value in string form - * @param {string} variableType Type of the variable whose value was passed - * in the first argument. Must be one of - * FEATURE_VARIABLE_TYPES in - * lib/utils/enums/index.js. The return value's - * type is determined by this argument (boolean - * for BOOLEAN, number for INTEGER or DOUBLE, - * and string for STRING). - * @param {Object} logger Logger instance - * @returns {*} Variable value of the appropriate type, or - * null if the type cast failed - */ - getTypeCastValue: function(variableValue, variableType, logger) { - var castValue; - - switch (variableType) { - case FEATURE_VARIABLE_TYPES.BOOLEAN: - if (variableValue !== 'true' && variableValue !== 'false') { - logger.log( - LOG_LEVEL.ERROR, - jsSdkUtils.sprintf(ERROR_MESSAGES.UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType) - ); - castValue = null; - } else { - castValue = variableValue === 'true'; - } - break; - - case FEATURE_VARIABLE_TYPES.INTEGER: - castValue = parseInt(variableValue, 10); - if (isNaN(castValue)) { - logger.log( - LOG_LEVEL.ERROR, - jsSdkUtils.sprintf(ERROR_MESSAGES.UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType) - ); - castValue = null; - } - break; - - case FEATURE_VARIABLE_TYPES.DOUBLE: - castValue = parseFloat(variableValue); - if (isNaN(castValue)) { - logger.log( - LOG_LEVEL.ERROR, - jsSdkUtils.sprintf(ERROR_MESSAGES.UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType) - ); - castValue = null; - } - break; - - default: - // type is STRING - castValue = variableValue; - break; - } +/** + * Returns true if an event with the given key exists in the datafile, and false otherwise + * @param {Object} projectConfig + * @param {string} eventKey + * @returns {boolean} + */ +export var eventWithKeyExists = function(projectConfig, eventKey) { + return projectConfig.eventKeyMap.hasOwnProperty(eventKey); +}; + +/** + * + * @param {Object} projectConfig + * @param {string} experimentId + * @returns {boolean} Returns true if experiment belongs to + * any feature, false otherwise. + */ +export var isFeatureExperiment = function(projectConfig, experimentId) { + return projectConfig.experimentFeatureMap.hasOwnProperty(experimentId); +}; - return castValue; - }, +/** + * Try to create a project config object from the given datafile and + * configuration properties. + * If successful, return the project config object, otherwise throws an error + * @param {Object} config + * @param {Object} config.datafile + * @param {Object} config.jsonSchemaValidator + * @param {Object} config.logger + * @return {Object} Project config object + */ +export var tryCreatingProjectConfig = function(config) { + configValidator.validateDatafile(config.datafile); + if (!config.jsonSchemaValidator) { + config.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.SKIPPING_JSON_VALIDATION, MODULE_NAME)); + } else { + config.jsonSchemaValidator.validate(config.datafile); + config.logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.VALID_DATAFILE, MODULE_NAME)); + } + return this.createProjectConfig(config.datafile); +}; - /** - * Returns an object containing all audiences in the project config. Keys are audience IDs - * and values are audience objects. - * @param projectConfig - * @returns {Object} - */ - getAudiencesById: function(projectConfig) { - return projectConfig.audiencesById; - }, - - /** - * Returns true if an event with the given key exists in the datafile, and false otherwise - * @param {Object} projectConfig - * @param {string} eventKey - * @returns {boolean} - */ - eventWithKeyExists: function(projectConfig, eventKey) { - return projectConfig.eventKeyMap.hasOwnProperty(eventKey); - }, - - /** - * - * @param {Object} projectConfig - * @param {string} experimentId - * @returns {boolean} Returns true if experiment belongs to - * any feature, false otherwise. - */ - isFeatureExperiment: function(projectConfig, experimentId) { - return projectConfig.experimentFeatureMap.hasOwnProperty(experimentId); - }, - - /** - * Try to create a project config object from the given datafile and - * configuration properties. - * If successful, return the project config object, otherwise throws an error - * @param {Object} config - * @param {Object} config.datafile - * @param {Object} config.jsonSchemaValidator - * @param {Object} config.logger - * @return {Object} Project config object - */ - tryCreatingProjectConfig: function(config) { - configValidator.validateDatafile(config.datafile); - if (!config.jsonSchemaValidator) { - config.logger.log(LOG_LEVEL.INFO, jsSdkUtils.sprintf(LOG_MESSAGES.SKIPPING_JSON_VALIDATION, MODULE_NAME)); - } else { - config.jsonSchemaValidator.validate(config.datafile); - config.logger.log(LOG_LEVEL.INFO, jsSdkUtils.sprintf(LOG_MESSAGES.VALID_DATAFILE, MODULE_NAME)); - } - return module.exports.createProjectConfig(config.datafile); - }, +export default { + createProjectConfig: createProjectConfig, + getExperimentId: getExperimentId, + getLayerId: getLayerId, + getAttributeId: getAttributeId, + getEventId: getEventId, + getExperimentStatus: getExperimentStatus, + isActive: isActive, + isRunning: isRunning, + getExperimentAudienceConditions: getExperimentAudienceConditions, + getVariationKeyFromId: getVariationKeyFromId, + getVariationIdFromExperimentAndVariationKey: getVariationIdFromExperimentAndVariationKey, + getExperimentFromKey: getExperimentFromKey, + getTrafficAllocation: getTrafficAllocation, + getExperimentFromId: getExperimentFromId, + getFeatureFromKey: getFeatureFromKey, + getVariableForFeature: getVariableForFeature, + getVariableValueForVariation: getVariableValueForVariation, + getTypeCastValue: getTypeCastValue, + getAudiencesById: getAudiencesById, + eventWithKeyExists: eventWithKeyExists, + isFeatureExperiment: isFeatureExperiment, + tryCreatingProjectConfig: tryCreatingProjectConfig, }; diff --git a/packages/optimizely-sdk/lib/core/project_config/index.tests.js b/packages/optimizely-sdk/lib/core/project_config/index.tests.js index 11a28b372..a76bdfea4 100644 --- a/packages/optimizely-sdk/lib/core/project_config/index.tests.js +++ b/packages/optimizely-sdk/lib/core/project_config/index.tests.js @@ -1,5 +1,5 @@ /** - * Copyright 2016-2019, Optimizely + * Copyright 2016-2020, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,26 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -var projectConfig = require('./'); -var enums = require('../../utils/enums'); -var testDatafile = require('../../tests/test_data'); -var configValidator = require('../../utils/config_validator'); -var logging = require('@optimizely/js-sdk-logging'); - -var logger = logging.getLogger(); - -var forEach = require('lodash/forEach'); -var cloneDeep = require('lodash/cloneDeep'); -var fns = require('../../utils/fns'); -var chai = require('chai'); -var assert = chai.assert; -var loggerPlugin = require('../../plugins/logger'); -var sinon = require('sinon'); -var sprintf = require('@optimizely/js-sdk-utils').sprintf; - -var ERROR_MESSAGES = enums.ERROR_MESSAGES; -var FEATURE_VARIABLE_TYPES = enums.FEATURE_VARIABLE_TYPES; -var LOG_LEVEL = enums.LOG_LEVEL; +import sinon from 'sinon'; +import { assert } from 'chai'; +import { forEach, cloneDeep } from 'lodash'; +import { getLogger } from '@optimizely/js-sdk-logging'; +import { sprintf } from '@optimizely/js-sdk-utils'; + +import fns from '../../utils/fns'; +import projectConfig from './'; +import { + ERROR_MESSAGES, + FEATURE_VARIABLE_TYPES, + LOG_LEVEL, +} from '../../utils/enums'; +import loggerPlugin from '../../plugins/logger'; +import testDatafile from '../../tests/test_data'; +import configValidator from '../../utils/config_validator'; + +var logger = getLogger(); describe('lib/core/project_config', function() { var parsedAudiences = testDatafile.getParsedAudiences; diff --git a/packages/optimizely-sdk/lib/core/project_config/project_config_manager.js b/packages/optimizely-sdk/lib/core/project_config/project_config_manager.js index fa4e8f967..b2d177ed8 100644 --- a/packages/optimizely-sdk/lib/core/project_config/project_config_manager.js +++ b/packages/optimizely-sdk/lib/core/project_config/project_config_manager.js @@ -1,5 +1,5 @@ /** - * Copyright 2019, Optimizely + * Copyright 2019-2020, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,20 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { sprintf } from '@optimizely/js-sdk-utils'; +import { getLogger } from '@optimizely/js-sdk-logging'; +import { HttpPollingDatafileManager } from '@optimizely/js-sdk-datafile-manager'; -var fns = require('../../utils/fns'); -var sprintf = require('@optimizely/js-sdk-utils').sprintf; -var logging = require('@optimizely/js-sdk-logging'); -var configValidator = require('../../utils/config_validator'); -var datafileManager = require('@optimizely/js-sdk-datafile-manager'); -var enums = require('../../utils/enums'); -var projectConfig = require('../../core/project_config'); -var optimizelyConfig = require('../optimizely_config'); - -var logger = logging.getLogger(); - -var ERROR_MESSAGES = enums.ERROR_MESSAGES; +import fns from '../../utils/fns'; +import { ERROR_MESSAGES } from '../../utils/enums'; +import projectConfig from '../../core/project_config'; +import { getOptimizelyConfig } from '../optimizely_config'; +import configValidator from '../../utils/config_validator'; +var logger = getLogger(); var MODULE_NAME = 'PROJECT_CONFIG_MANAGER'; /** @@ -55,7 +52,7 @@ function getErrorMessage(maybeError, defaultMessage) { * @param {Object=} config.jsonSchemaValidator * @param {string=} config.sdkKey */ -function ProjectConfigManager(config) { +export function ProjectConfigManager(config) { try { this.__initialize(config); } catch (ex) { @@ -104,7 +101,7 @@ ProjectConfigManager.prototype.__initialize = function(config) { jsonSchemaValidator: this.jsonSchemaValidator, logger: logger, }); - this.__optimizelyConfigObj = optimizelyConfig.getOptimizelyConfig(this.__configObj); + this.__optimizelyConfigObj = getOptimizelyConfig(this.__configObj); } catch (ex) { logger.error(ex); projectConfigCreationEx = ex; @@ -124,7 +121,7 @@ ProjectConfigManager.prototype.__initialize = function(config) { if (initialDatafile && this.__configObj) { datafileManagerConfig.datafile = initialDatafile; } - this.datafileManager = new datafileManager.HttpPollingDatafileManager(datafileManagerConfig); + this.datafileManager = new HttpPollingDatafileManager(datafileManagerConfig); this.datafileManager.start(); this.__readyPromise = this.datafileManager .onReady() @@ -265,7 +262,7 @@ ProjectConfigManager.prototype.__handleNewConfigObj = function(newConfigObj) { } this.__configObj = newConfigObj; - this.__optimizelyConfigObj = optimizelyConfig.getOptimizelyConfig(newConfigObj); + this.__optimizelyConfigObj = getOptimizelyConfig(newConfigObj); this.__updateListeners.forEach(function(listener) { listener(newConfigObj); @@ -340,6 +337,6 @@ ProjectConfigManager.prototype.stop = function() { this.__updateListeners = []; }; -module.exports = { +export default { ProjectConfigManager: ProjectConfigManager, }; diff --git a/packages/optimizely-sdk/lib/core/project_config/project_config_manager.tests.js b/packages/optimizely-sdk/lib/core/project_config/project_config_manager.tests.js index 29a49c66a..de38044ea 100644 --- a/packages/optimizely-sdk/lib/core/project_config/project_config_manager.tests.js +++ b/packages/optimizely-sdk/lib/core/project_config/project_config_manager.tests.js @@ -1,5 +1,5 @@ /** - * Copyright 2019, Optimizely + * Copyright 2019-2020 Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,25 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -var assert = require('chai').assert; -var datafileManager = require('@optimizely/js-sdk-datafile-manager'); -var logging = require('@optimizely/js-sdk-logging'); -var sinon = require('sinon'); -var cloneDeep = require('lodash/cloneDeep'); -var sprintf = require('@optimizely/js-sdk-utils').sprintf; -var enums = require('../../utils/enums'); -var jsonSchemaValidator = require('../../utils/json_schema_validator'); -var projectConfig = require('./index'); -var optimizelyConfig = require('../optimizely_config/index'); -var projectConfigManager = require('./project_config_manager'); -var testData = require('../../tests/test_data'); - -var ERROR_MESSAGES = enums.ERROR_MESSAGES; -var LOG_MESSAGES = enums.LOG_MESSAGES; +import sinon from 'sinon'; +import { assert } from 'chai'; +import { cloneDeep } from 'lodash'; +import { sprintf } from '@optimizely/js-sdk-utils'; +import * as logging from '@optimizely/js-sdk-logging'; +import * as datafileManager from '@optimizely/js-sdk-datafile-manager'; + +import projectConfig from './index'; +import { ERROR_MESSAGES, LOG_MESSAGES } from '../../utils/enums'; +import testData from '../../tests/test_data'; +import * as optimizelyConfig from '../optimizely_config/index'; +import projectConfigManager from './project_config_manager'; +import jsonSchemaValidator from '../../utils/json_schema_validator'; describe('lib/core/project_config/project_config_manager', function() { var globalStubErrorHandler; + var stubLogHandler; beforeEach(function() { sinon.stub(datafileManager, 'HttpPollingDatafileManager').returns({ start: sinon.stub(), diff --git a/packages/optimizely-sdk/lib/core/project_config/project_config_schema.js b/packages/optimizely-sdk/lib/core/project_config/project_config_schema.js index ecea71159..d04959b0d 100644 --- a/packages/optimizely-sdk/lib/core/project_config/project_config_schema.js +++ b/packages/optimizely-sdk/lib/core/project_config/project_config_schema.js @@ -1,5 +1,5 @@ /** - * Copyright 2016-2017, Optimizely + * Copyright 2016-2017, 2020, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,12 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - /*eslint-disable */ /** * Project Config JSON Schema file used to validate the project json datafile */ -module.exports = { +export var schema = { $schema: 'http://json-schema.org/draft-04/schema#', type: 'object', properties: { @@ -276,3 +275,5 @@ module.exports = { }, }, }; + +export default schema; diff --git a/packages/optimizely-sdk/lib/optimizely/index.js b/packages/optimizely-sdk/lib/optimizely/index.js index fc99ced13..d52659b67 100644 --- a/packages/optimizely-sdk/lib/optimizely/index.js +++ b/packages/optimizely-sdk/lib/optimizely/index.js @@ -20,8 +20,8 @@ import fns from '../utils/fns' import { validate } from '../utils/attributes_validator'; import decisionService from '../core/decision_service'; import enums from '../utils/enums'; -import eventBuilder from '../core/event_builder/index.js'; -import eventHelpers from '../core/event_builder/event_helpers'; +import { getImpressionEvent, getConversionEvent } from '../core/event_builder/index.js'; +import { buildConversionEvent, buildImpressionEvent } from '../core/event_builder/event_helpers'; import eventTagsValidator from '../utils/event_tags_validator'; import notificationCenter from '../core/notification_center'; import projectConfig from '../core/project_config'; @@ -211,7 +211,7 @@ Optimizely.prototype._sendImpressionEvent = function(experimentKey, variationKey return; } - var impressionEvent = eventHelpers.buildImpressionEvent({ + var impressionEvent = buildImpressionEvent({ experimentKey: experimentKey, variationKey: variationKey, userId: userId, @@ -250,7 +250,7 @@ Optimizely.prototype.__emitNotificationCenterActivate = function(experimentKey, variationId: variationId, logger: this.logger, }; - var impressionEvent = eventBuilder.getImpressionEvent(impressionEventOptions); + var impressionEvent = getImpressionEvent(impressionEventOptions); var experiment = configObj.experimentKeyMap[experimentKey]; var variation; if (experiment && experiment.variationKeyMap) { @@ -299,7 +299,7 @@ Optimizely.prototype.track = function(eventKey, userId, attributes, eventTags) { // remove null values from eventTags eventTags = this.__filterEmptyValues(eventTags); - var conversionEvent = eventHelpers.buildConversionEvent({ + var conversionEvent = buildConversionEvent({ eventKey: eventKey, eventTags: eventTags, userId: userId, @@ -344,7 +344,7 @@ Optimizely.prototype.__emitNotificationCenterTrack = function(eventKey, userId, logger: this.logger, userId: userId, }; - var conversionEvent = eventBuilder.getConversionEvent(conversionEventOptions); + var conversionEvent = getConversionEvent(conversionEventOptions); this.notificationCenter.sendNotifications(NOTIFICATION_TYPES.TRACK, { eventKey: eventKey, diff --git a/packages/optimizely-sdk/lib/utils/json_schema_validator/index.js b/packages/optimizely-sdk/lib/utils/json_schema_validator/index.js index 69876c6e4..ae721fe49 100644 --- a/packages/optimizely-sdk/lib/utils/json_schema_validator/index.js +++ b/packages/optimizely-sdk/lib/utils/json_schema_validator/index.js @@ -1,5 +1,5 @@ /** - * Copyright 2016-2017, Optimizely + * Copyright 2016-2017, 2020, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ */ var validate = require('json-schema').validate; var sprintf = require('@optimizely/js-sdk-utils').sprintf; -var projectConfigSchema = require('../../core/project_config/project_config_schema'); +var projectConfigSchema = require('../../core/project_config/project_config_schema').default; var ERROR_MESSAGES = require('../enums').ERROR_MESSAGES; var MODULE_NAME = 'JSON_SCHEMA_VALIDATOR';