Skip to content

Commit a291452

Browse files
alexjoeyyongraju-opti
authored andcommitted
[AI-FSSDK] [FSSDK-12958] Test decision error discards local holdout events
1 parent 94d7e6b commit a291452

1 file changed

Lines changed: 19 additions & 2 deletions

File tree

‎lib/optimizely/index.spec.ts‎

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -943,11 +943,12 @@ describe('Optimizely', () => {
943943
trafficAllocation: [{ entityId: `${id}_var`, endOfRange: 10000 }],
944944
});
945945

946-
const setup = (localHoldouts: any[], sendFlagDecisions = true) => {
946+
const setup = (localHoldouts: any[], sendFlagDecisions = true, cmabService: any = {}) => {
947947
const datafile: any = getDecisionTestDatafile();
948948
datafile.holdouts = [];
949949
datafile.localHoldouts = localHoldouts;
950950
datafile.sendFlagDecisions = sendFlagDecisions;
951+
datafile.experiments.find((e: any) => e.key === 'exp_3').cmab.trafficAllocation = 10000;
951952
const eventProcessor = getForwardingEventProcessor({
952953
dispatchEvent: vi.fn(() => Promise.resolve({ statusCode: 200 })),
953954
});
@@ -962,7 +963,7 @@ describe('Optimizely', () => {
962963
logger,
963964
odpManager,
964965
disposable: true,
965-
cmabService: {} as any
966+
cmabService,
966967
});
967968
const holdoutEvents = () => processSpy.mock.calls
968969
.map((call: any) => call[0] as ImpressionEvent)
@@ -1012,6 +1013,22 @@ describe('Optimizely', () => {
10121013
expect(processSpy).not.toHaveBeenCalled();
10131014
});
10141015

1016+
it('should return an error decision and send no impressions when a later rule errors after a local holdout hit', async () => {
1017+
const cmabService = { getDecision: vi.fn().mockRejectedValue(new Error('cmab fetch failed')) };
1018+
const { optimizely, processSpy } = setup([makeLocalHoldout('lh', ['2001'])], true, cmabService);
1019+
const user = new OptimizelyUserContext({ optimizely, userId: 'tester', attributes: { country: 'BD', age: 80 } });
1020+
1021+
const decision = await optimizely.decideAsync(user, 'flag_1', [OptimizelyDecideOption.INCLUDE_REASONS]);
1022+
1023+
expect(cmabService.getDecision).toHaveBeenCalledOnce();
1024+
expect(decision.variationKey).toBeNull();
1025+
expect(decision.enabled).toBe(false);
1026+
expect(decision.ruleKey).toBeNull();
1027+
expect(decision.reasons).toContain('Failed to fetch CMAB data for experiment exp_3.');
1028+
expect(decision.reasons.some((r) => r.includes('lh_key'))).toBe(true);
1029+
expect(processSpy).not.toHaveBeenCalled();
1030+
});
1031+
10151032
it('should skip the held-out rule and send no holdout impression for isFeatureEnabled', () => {
10161033
const { optimizely, processSpy, holdoutEvents } = setup([makeLocalHoldout('lh', ['2001'])]);
10171034

0 commit comments

Comments
 (0)