Skip to content

Commit 7d058bf

Browse files
mnoman09NomanShoaibmsohailhussain
authored
fix: Checking variation in flagvariation map instead of checking it only in experiment (#729)
* Removed getflagVariationByKey from optimizely and moved it to project config also instead of getting variation from rule * fix * Added unit test * Fixed unit test Co-authored-by: mnoman09 <[email protected]> Co-authored-by: msohailhussain <[email protected]>
1 parent 1550705 commit 7d058bf

File tree

6 files changed

+61
-29
lines changed

6 files changed

+61
-29
lines changed

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
getExperimentAudienceConditions,
3232
getExperimentFromId,
3333
getExperimentFromKey,
34+
getFlagVariationByKey,
3435
getTrafficAllocation,
3536
getVariationIdFromExperimentAndVariationKey,
3637
getVariationFromId,
@@ -614,7 +615,11 @@ export class DecisionService {
614615
decideReasons.push(...decisionVariation.reasons);
615616
variationKey = decisionVariation.result;
616617
if (variationKey) {
617-
const variation = experiment.variationKeyMap[variationKey];
618+
let variation = null;
619+
variation = experiment.variationKeyMap[variationKey];
620+
if (!variation) {
621+
variation = getFlagVariationByKey(configObj, feature.key, variationKey);
622+
}
618623
variationForFeatureExperiment = {
619624
experiment: experiment,
620625
variation: variation,
@@ -1016,7 +1021,7 @@ export class DecisionService {
10161021
const decideReasons: (string | number)[][] = [];
10171022

10181023
// check forced decision first
1019-
const forcedDecisionResponse = user.findValidatedForcedDecision(flagKey, rule.key);
1024+
const forcedDecisionResponse = user.findValidatedForcedDecision(configObj, flagKey, rule.key);
10201025
decideReasons.push(...forcedDecisionResponse.reasons);
10211026

10221027
const forcedVariaton = forcedDecisionResponse.result;
@@ -1048,7 +1053,7 @@ export class DecisionService {
10481053

10491054
// check forced decision first
10501055
const rule = rules[ruleIndex];
1051-
const forcedDecisionResponse = user.findValidatedForcedDecision(flagKey, rule.key);
1056+
const forcedDecisionResponse = user.findValidatedForcedDecision(configObj, flagKey, rule.key);
10521057
decideReasons.push(...forcedDecisionResponse.reasons);
10531058

10541059
const forcedVariaton = forcedDecisionResponse.result;

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,26 @@ export const getExperimentFromId = function(
508508
return null;
509509
};
510510

511+
/**
512+
* Returns flag variation for specified flagKey and variationKey
513+
* @param {flagKey} string
514+
* @param {variationKey} string
515+
* @return {Variation|null}
516+
*/
517+
export const getFlagVariationByKey = function(projectConfig: ProjectConfig, flagKey: string, variationKey: string): Variation | null {
518+
if (!projectConfig) {
519+
return null;
520+
}
521+
522+
const variations = projectConfig.flagVariationsMap[flagKey];
523+
const result = find(variations, item => item.key === variationKey)
524+
if (result) {
525+
return result;
526+
}
527+
528+
return null;
529+
};
530+
511531
/**
512532
* Get feature from provided feature key. Log an error if no feature exists in
513533
* the project config with the given key.
@@ -817,6 +837,7 @@ export default {
817837
getExperimentFromKey,
818838
getTrafficAllocation,
819839
getExperimentFromId,
840+
getFlagVariationByKey,
820841
getFeatureFromKey,
821842
getVariableForFeature,
822843
getVariableValueForVariation,

packages/optimizely-sdk/lib/optimizely/index.ts

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,7 +1481,7 @@ export default class Optimizely {
14811481

14821482
const allDecideOptions = this.getAllDecideOptions(options);
14831483

1484-
const forcedDecisionResponse = user.findValidatedForcedDecision(key);
1484+
const forcedDecisionResponse = user.findValidatedForcedDecision(configObj, key);
14851485
reasons.push(...forcedDecisionResponse.reasons);
14861486
const variation = forcedDecisionResponse.result;
14871487
if (variation) {
@@ -1672,24 +1672,4 @@ export default class Optimizely {
16721672
return this.decideForKeys(user, allFlagKeys, options);
16731673
}
16741674

1675-
/**
1676-
* Returns flag variation for specified flagKey and variationKey
1677-
* @param {flagKey} string
1678-
* @param {variationKey} string
1679-
* @return {OptimizelyVariation|null}
1680-
*/
1681-
getFlagVariationByKey(flagKey: string, variationKey: string): OptimizelyVariation | null {
1682-
const configObj = this.projectConfigManager.getConfig();
1683-
if (!configObj) {
1684-
return null;
1685-
}
1686-
1687-
const variations = configObj.flagVariationsMap[flagKey];
1688-
const result = find(variations, item => item.key === variationKey)
1689-
if (result) {
1690-
return result;
1691-
}
1692-
1693-
return null;
1694-
}
16951675
}

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ describe('lib/optimizely_user_context', function() {
176176
);
177177
assert.deepEqual(decision, fakeDecision);
178178
});
179-
});
179+
});
180180

181181
describe('#decideForKeys', function() {
182182
it('should return an expected decision results object', function() {
@@ -381,6 +381,23 @@ describe('lib/optimizely_user_context', function() {
381381
optlyInstance.notificationCenter.sendNotifications.restore();
382382
});
383383

384+
it('should return an expected decision object when forced decision is called and variation of different experiment but same flag key', function() {
385+
var flagKey = 'feature_1';
386+
var ruleKey = 'exp_with_audience';
387+
var variationKey = '3324490633';
388+
389+
var user = optlyInstance.createUserContext(userId);
390+
user.setForcedDecision({ flagKey: flagKey, ruleKey }, { variationKey });
391+
var decision = user.decide(flagKey, options);
392+
393+
assert.equal(decision.variationKey, variationKey);
394+
assert.equal(decision.ruleKey, ruleKey);
395+
assert.equal(decision.enabled, true);
396+
assert.equal(decision.userContext.getUserId(), userId);
397+
assert.deepEqual(decision.userContext.getAttributes(), {});
398+
assert.deepEqual(Object.keys(decision.userContext.forcedDecisionsMap).length, 1);
399+
});
400+
384401
it('should return forced decision object when forced decision is set for a flag and do NOT dispatch an event with DISABLE_DECISION_EVENT passed in decide options', function() {
385402
var user = optlyInstance.createUserContext(userId);
386403
var featureKey = 'feature_1';

packages/optimizely-sdk/lib/optimizely_user_context/index.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ import {
2626
UserAttributes,
2727
Variation
2828
} from '../../lib/shared_types';
29+
import {
30+
getFlagVariationByKey,
31+
ProjectConfig,
32+
} from '../core/project_config';
2933
import { LOG_MESSAGES, CONTROL_ATTRIBUTES } from '../utils/enums';
3034

3135
const logger = getLogger();
@@ -211,22 +215,24 @@ export default class OptimizelyUserContext {
211215

212216
/**
213217
* Finds a validated forced decision for specific flagKey and optional ruleKey.
218+
* @param {ProjectConfig}config A projectConfig.
214219
* @param {string} flagKey A flagKey.
215220
* @param {ruleKey} ruleKey A ruleKey (optional).
216221
* @return {DecisionResponse<Variation|null>} DecisionResponse object containing valid variation object and decide reasons.
217222
*/
218223
findValidatedForcedDecision(
224+
config: ProjectConfig,
219225
flagKey: string,
220-
ruleKey?: string
226+
ruleKey?: string,
221227
): DecisionResponse<Variation | null> {
222228

223229
const decideReasons: (string | number)[][] = [];
224230
const forcedDecision = this.findForcedDecision({ flagKey, ruleKey });
225231
let variation = null;
226232
let variationKey;
227-
if (forcedDecision) {
233+
if (config && forcedDecision) {
228234
variationKey = forcedDecision.variationKey;
229-
variation = this.optimizely.getFlagVariationByKey(flagKey, variationKey);
235+
variation = getFlagVariationByKey(config, flagKey, variationKey);
230236
if (variation) {
231237
if (ruleKey) {
232238
logger.info(

packages/optimizely-sdk/lib/shared_types.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import { EventProcessor } from '@optimizely/js-sdk-event-processor';
1818

1919
import { NotificationCenter } from '@optimizely/js-sdk-utils';
2020

21+
import { ProjectConfig } from './core/project_config';
22+
2123
export interface BucketerParams {
2224
experimentId: string;
2325
experimentKey: string;
@@ -381,8 +383,9 @@ export interface OptimizelyUserContext {
381383
): { [key: string]: OptimizelyDecision };
382384
trackEvent(eventName: string, eventTags?: EventTags): void;
383385
findValidatedForcedDecision(
386+
config: ProjectConfig,
384387
flagKey: string,
385-
ruleKey?: string,
388+
ruleKey?: string
386389
): DecisionResponse<Variation | null>;
387390
setForcedDecision(context: OptimizelyDecisionContext, decision: OptimizelyForcedDecision): boolean;
388391
getForcedDecision(context: OptimizelyDecisionContext): OptimizelyForcedDecision | null;

0 commit comments

Comments
 (0)