Skip to content

Commit f8cd69c

Browse files
committed
feature list test
1 parent 9f56e30 commit f8cd69c

File tree

2 files changed

+230
-4
lines changed

2 files changed

+230
-4
lines changed

lib/core/decision_service/index.spec.ts

Lines changed: 160 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,7 +1038,165 @@ describe('DecisionService', () => {
10381038
});
10391039
});
10401040

1041-
// describe('getVariationsForFeatureList', () => {
1041+
describe('getVariationsForFeatureList', () => {
1042+
beforeEach(() => {
1043+
mockBucket.mockReset();
1044+
});
1045+
1046+
it('should return correct results for all features in the feature list', () => {
1047+
const { decisionService } = getDecisionService();
1048+
1049+
const resolveVariationSpy = vi.spyOn(decisionService as any, 'resolveVariation')
1050+
.mockImplementation((
1051+
config,
1052+
experiment: any,
1053+
user,
1054+
shouldIgnoreUPS,
1055+
userProfileTracker
1056+
) => {
1057+
if (experiment.key === 'exp_2') {
1058+
return {
1059+
result: 'variation_2',
1060+
reasons: [],
1061+
};
1062+
} else if (experiment.key === 'exp_4') {
1063+
return {
1064+
result: 'variation_flag_2',
1065+
reasons: [],
1066+
};
1067+
}
1068+
return {
1069+
result: null,
1070+
reasons: [],
1071+
}
1072+
});
1073+
1074+
const config = createProjectConfig(getDecisionTestDatafile());
1075+
1076+
const user = new OptimizelyUserContext({
1077+
optimizely: {} as any,
1078+
userId: 'tester',
1079+
attributes: {
1080+
age: 40,
1081+
},
1082+
});
1083+
1084+
const featureList = [
1085+
config.featureKeyMap['flag_1'],
1086+
config.featureKeyMap['flag_2'],
1087+
];
1088+
1089+
const variations = decisionService.getVariationsForFeatureList(config, featureList, user);
1090+
1091+
expect(variations[0].result).toEqual({
1092+
experiment: config.experimentKeyMap['exp_2'],
1093+
variation: config.variationIdMap['5002'],
1094+
decisionSource: DECISION_SOURCES.FEATURE_TEST,
1095+
});
1096+
1097+
expect(variations[1].result).toEqual({
1098+
experiment: config.experimentKeyMap['exp_4'],
1099+
variation: config.variationIdMap['5100'],
1100+
decisionSource: DECISION_SOURCES.FEATURE_TEST,
1101+
});
10421102

1043-
// });
1103+
const variations2 = decisionService.getVariationsForFeatureList(config, featureList.reverse(), user);
1104+
1105+
expect(variations2[0].result).toEqual({
1106+
experiment: config.experimentKeyMap['exp_4'],
1107+
variation: config.variationIdMap['5100'],
1108+
decisionSource: DECISION_SOURCES.FEATURE_TEST,
1109+
});
1110+
1111+
expect(variations2[1].result).toEqual({
1112+
experiment: config.experimentKeyMap['exp_2'],
1113+
variation: config.variationIdMap['5002'],
1114+
decisionSource: DECISION_SOURCES.FEATURE_TEST,
1115+
});
1116+
});
1117+
1118+
it('should batch user profile lookup and save', () => {
1119+
const { decisionService, userProfileService } = getDecisionService({ userProfileService: true });
1120+
1121+
const resolveVariationSpy = vi.spyOn(decisionService as any, 'resolveVariation')
1122+
.mockImplementation((
1123+
config,
1124+
experiment: any,
1125+
user,
1126+
shouldIgnoreUPS,
1127+
userProfileTracker: any,
1128+
) => {
1129+
if (experiment.key === 'exp_2') {
1130+
userProfileTracker.userProfile[experiment.id] = {
1131+
variation_id: '5002',
1132+
};
1133+
userProfileTracker.isProfileUpdated = true;
1134+
1135+
return {
1136+
result: 'variation_2',
1137+
reasons: [],
1138+
};
1139+
} else if (experiment.key === 'exp_4') {
1140+
userProfileTracker.userProfile[experiment.id] = {
1141+
variation_id: '5100',
1142+
};
1143+
userProfileTracker.isProfileUpdated = true;
1144+
1145+
return {
1146+
result: 'variation_flag_2',
1147+
reasons: [],
1148+
};
1149+
}
1150+
return {
1151+
result: null,
1152+
reasons: [],
1153+
}
1154+
});
1155+
1156+
const config = createProjectConfig(getDecisionTestDatafile());
1157+
1158+
const user = new OptimizelyUserContext({
1159+
optimizely: {} as any,
1160+
userId: 'tester',
1161+
attributes: {
1162+
age: 40,
1163+
},
1164+
});
1165+
1166+
const featureList = [
1167+
config.featureKeyMap['flag_1'],
1168+
config.featureKeyMap['flag_2'],
1169+
];
1170+
1171+
const variations = decisionService.getVariationsForFeatureList(config, featureList, user);
1172+
1173+
expect(variations[0].result).toEqual({
1174+
experiment: config.experimentKeyMap['exp_2'],
1175+
variation: config.variationIdMap['5002'],
1176+
decisionSource: DECISION_SOURCES.FEATURE_TEST,
1177+
});
1178+
1179+
expect(variations[1].result).toEqual({
1180+
experiment: config.experimentKeyMap['exp_4'],
1181+
variation: config.variationIdMap['5100'],
1182+
decisionSource: DECISION_SOURCES.FEATURE_TEST,
1183+
});
1184+
1185+
expect(userProfileService?.lookup).toHaveBeenCalledTimes(1);
1186+
expect(userProfileService?.lookup).toHaveBeenCalledWith('tester');
1187+
1188+
expect(userProfileService?.save).toHaveBeenCalledTimes(1);
1189+
expect(userProfileService?.save).toHaveBeenCalledWith({
1190+
user_id: 'tester',
1191+
experiment_bucket_map: {
1192+
'2002': {
1193+
variation_id: '5002',
1194+
},
1195+
'2004': {
1196+
variation_id: '5100',
1197+
},
1198+
},
1199+
});
1200+
});
1201+
});
10441202
});

lib/tests/decision_test_datafile.ts

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,15 @@ const testDatafile = {
123123
"defaultValue": "0"
124124
}
125125
]
126+
},
127+
{
128+
id: "1002",
129+
key: "flag_2",
130+
"rolloutId": "rollout-374517-931741182375293",
131+
experimentIds: [
132+
"2004"
133+
],
134+
"variables": []
126135
}
127136
],
128137
"rollouts": [
@@ -260,12 +269,42 @@ const testDatafile = {
260269
],
261270
forcedVariations: {
262271

272+
},
273+
audienceIds: [],
274+
audienceConditions: []
275+
},
276+
]
277+
},
278+
{
279+
id: "rollout-374517-931741182375293",
280+
experiments: [
281+
{
282+
id: "default-rollout-374517-931741182375293",
283+
key: "default-rollout-374517-931741182375293",
284+
status: "Running",
285+
layerId: "rollout-374517-931741182375293",
286+
variations: [
287+
{
288+
id: "1177722",
289+
key: "off",
290+
featureEnabled: false,
291+
variables: []
292+
}
293+
],
294+
trafficAllocation: [
295+
{
296+
"entityId": "1177722",
297+
"endOfRange": 10000
298+
}
299+
],
300+
forcedVariations: {
301+
263302
},
264303
audienceIds: [],
265304
audienceConditions: []
266305
}
267306
]
268-
}
307+
},
269308
],
270309
experiments: [
271310
{
@@ -371,12 +410,41 @@ const testDatafile = {
371410
],
372411
forcedVariations: {
373412

413+
},
414+
audienceIds: [],
415+
audienceConditions: []
416+
},
417+
{
418+
id: "2004",
419+
key: "exp_4",
420+
status: "Running",
421+
layerId: "9300001497754",
422+
variations: [
423+
{
424+
id: "5100",
425+
key: "variation_flag_2",
426+
featureEnabled: true,
427+
variables: []
428+
}
429+
],
430+
trafficAllocation: [
431+
{
432+
entityId: "5100",
433+
endOfRange: 5000
434+
},
435+
{
436+
entityId: "5100",
437+
endOfRange: 10000
438+
}
439+
],
440+
forcedVariations: {
441+
374442
},
375443
audienceIds: [],
376444
audienceConditions: []
377445
}
378446
],
379-
"groups": []
447+
groups: []
380448
}
381449

382450
export const getDecisionTestDatafile = () => {

0 commit comments

Comments
 (0)