diff --git a/lib/optimizely/index.tests.js b/lib/optimizely/index.tests.js index 20debfe31..dc9d6f6ed 100644 --- a/lib/optimizely/index.tests.js +++ b/lib/optimizely/index.tests.js @@ -17,7 +17,7 @@ import { assert, expect } from 'chai'; import sinon from 'sinon'; import { sprintf } from '../utils/fns'; import { NOTIFICATION_TYPES } from '../notification_center/type'; -import Optimizely from './'; +import Optimizely, { INVALID_ATTRIBUTES, INVALID_IDENTIFIER } from './'; import OptimizelyUserContext from '../optimizely_user_context'; import { OptimizelyDecideOption } from '../shared_types'; import AudienceEvaluator from '../core/audience_evaluator'; @@ -4379,14 +4379,16 @@ describe('lib/optimizely', function() { assert.deepEqual(userId, user.getUserId()); }); - it('should return null OptimizelyUserContext when input userId is null', function() { - var user = optlyInstance.createUserContext(null); - assert.deepEqual(null, user); + it('should throw error when input userId is null', function() { + assert.throws(() => { + optlyInstance.createUserContext(null); + }, Error, INVALID_IDENTIFIER); }); - it('should return null OptimizelyUserContext when input userId is undefined', function() { - var user = optlyInstance.createUserContext(undefined); - assert.deepEqual(null, user); + it('should throw error when input userId is undefined', function() { + assert.throws(() => { + optlyInstance.createUserContext(undefined); + }, Error, INVALID_IDENTIFIER); }); it('should create multiple instances of OptimizelyUserContext', function() { @@ -4405,11 +4407,11 @@ describe('lib/optimizely', function() { assert.deepEqual(user2.getUserId(), userId2); }); - it('should call the error handler for invalid user ID and return null', function() { + it('should call the error handler for invalid user ID and throw', function() { const { optlyInstance, errorNotifier, createdLogger } = getOptlyInstance({ datafileObj: testData.getTestDecideProjectConfig(), }); - assert.isNull(optlyInstance.createUserContext(1)); + assert.throws(() => optlyInstance.createUserContext(1), Error, INVALID_IDENTIFIER); sinon.assert.calledOnce(errorNotifier.notify); // var errorMessage = errorHandler.handleError.lastCall.args[0].message; // assert.strictEqual(errorMessage, sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); @@ -4418,11 +4420,11 @@ describe('lib/optimizely', function() { // assert.strictEqual(logMessage, sprintf(INVALID_INPUT_FORMAT, 'OPTIMIZELY', 'user_id')); }); - it('should call the error handler for invalid attributes and return null', function() { + it('should call the error handler for invalid attributes and throw', function() { const { optlyInstance, errorNotifier, createdLogger } = getOptlyInstance({ datafileObj: testData.getTestDecideProjectConfig(), }); - assert.isNull(optlyInstance.createUserContext('user1', 'invalid_attributes')); + assert.throws(() => optlyInstance.createUserContext('user1', 'invalid_attributes'), Error, INVALID_ATTRIBUTES); sinon.assert.calledOnce(errorNotifier.notify); // var errorMessage = errorHandler.handleError.lastCall.args[0].message; // assert.strictEqual(errorMessage, sprintf(INVALID_ATTRIBUTES, 'ATTRIBUTES_VALIDATOR')); diff --git a/lib/optimizely/index.ts b/lib/optimizely/index.ts index 0d6c937f8..c84d6a4cb 100644 --- a/lib/optimizely/index.ts +++ b/lib/optimizely/index.ts @@ -114,6 +114,8 @@ type DecisionReasons = (string | number)[]; export const INSTANCE_CLOSED = 'Instance closed'; export const ONREADY_TIMEOUT = 'onReady timeout expired after %s ms'; +export const INVALID_IDENTIFIER = 'Invalid identifier'; +export const INVALID_ATTRIBUTES = 'Invalid attributes'; /** * options required to create optimizely object @@ -1356,13 +1358,17 @@ export default class Optimizely extends BaseService implements Client { * @param {string} userId (Optional) The user ID to be used for bucketing. * @param {UserAttributes} attributes (Optional) user attributes. * @return {OptimizelyUserContext|null} An OptimizelyUserContext associated with this OptimizelyClient or - * null if provided inputs are invalid + * throws if provided inputs are invalid */ - createUserContext(userId?: string, attributes?: UserAttributes): OptimizelyUserContext | null { + createUserContext(userId?: string, attributes?: UserAttributes): OptimizelyUserContext { const userIdentifier = userId ?? this.vuidManager?.getVuid(); - if (userIdentifier === undefined || !this.validateInputs({ user_id: userIdentifier }, attributes)) { - return null; + if (userIdentifier === undefined || !this.validateInputs({ user_id: userIdentifier })) { + throw new Error(INVALID_IDENTIFIER); + } + + if (!this.validateInputs({}, attributes)) { + throw new Error(INVALID_ATTRIBUTES); } const userContext = new OptimizelyUserContext({ diff --git a/lib/shared_types.ts b/lib/shared_types.ts index 0a1582e4a..93d5d4524 100644 --- a/lib/shared_types.ts +++ b/lib/shared_types.ts @@ -293,7 +293,7 @@ export interface OptimizelyVariable { export interface Client { // TODO: In the future, will add a function to allow overriding the VUID. getVuid(): string | undefined; - createUserContext(userId?: string, attributes?: UserAttributes): OptimizelyUserContext | null; + createUserContext(userId?: string, attributes?: UserAttributes): OptimizelyUserContext; notificationCenter: NotificationCenter; activate(experimentKey: string, userId: string, attributes?: UserAttributes): string | null; track(eventKey: string, userId: string, attributes?: UserAttributes, eventTags?: EventTags): void;