Skip to content

Commit 8b4299f

Browse files
committed
tests
1 parent 309f565 commit 8b4299f

1 file changed

Lines changed: 81 additions & 0 deletions

File tree

lib/project_config/project_config.spec.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,87 @@ describe('createProjectConfig - local holdouts (FSSDK-12369, FSSDK-12760)', () =
485485
expect(forRuleB[0].id).toBe('local_holdout_rule_a_id');
486486
});
487487

488+
it('getHoldoutsForRule should only return holdouts targeting that rule and exclude others', () => {
489+
const datafile = cloneDeep(makeHoldoutsDatafile());
490+
(datafile as any).localHoldouts = [
491+
{
492+
id: 'holdout_for_rule_x',
493+
key: 'holdout_rule_x',
494+
status: 'Running',
495+
includedFlags: [],
496+
excludedFlags: [],
497+
audienceIds: [],
498+
audienceConditions: [],
499+
includedRules: ['rule_x'],
500+
variations: [{ id: 'var_x', key: 'var_x', variables: [] }],
501+
trafficAllocation: [{ entityId: 'var_x', endOfRange: 5000 }],
502+
},
503+
{
504+
id: 'holdout_for_rule_y',
505+
key: 'holdout_rule_y',
506+
status: 'Running',
507+
includedFlags: [],
508+
excludedFlags: [],
509+
audienceIds: [],
510+
audienceConditions: [],
511+
includedRules: ['rule_y'],
512+
variations: [{ id: 'var_y', key: 'var_y', variables: [] }],
513+
trafficAllocation: [{ entityId: 'var_y', endOfRange: 5000 }],
514+
},
515+
{
516+
id: 'holdout_for_both',
517+
key: 'holdout_both',
518+
status: 'Running',
519+
includedFlags: [],
520+
excludedFlags: [],
521+
audienceIds: [],
522+
audienceConditions: [],
523+
includedRules: ['rule_x', 'rule_y'],
524+
variations: [{ id: 'var_both', key: 'var_both', variables: [] }],
525+
trafficAllocation: [{ entityId: 'var_both', endOfRange: 5000 }],
526+
},
527+
];
528+
const config = projectConfig.createProjectConfig(datafile as any);
529+
530+
const forRuleX = getHoldoutsForRule(config, 'rule_x');
531+
const forRuleXIds = forRuleX.map(h => h.id).sort();
532+
expect(forRuleXIds).toEqual(['holdout_for_both', 'holdout_for_rule_x']);
533+
534+
const forRuleY = getHoldoutsForRule(config, 'rule_y');
535+
const forRuleYIds = forRuleY.map(h => h.id).sort();
536+
expect(forRuleYIds).toEqual(['holdout_for_both', 'holdout_for_rule_y']);
537+
538+
// rule_x results must not contain holdout_for_rule_y and vice versa
539+
expect(forRuleXIds).not.toContain('holdout_for_rule_y');
540+
expect(forRuleYIds).not.toContain('holdout_for_rule_x');
541+
});
542+
543+
it('getHoldoutsForRule should not return global holdouts', () => {
544+
const datafile = cloneDeep(makeHoldoutsDatafile());
545+
(datafile as any).localHoldouts = [
546+
{
547+
id: 'local_only',
548+
key: 'local_only',
549+
status: 'Running',
550+
includedFlags: [],
551+
excludedFlags: [],
552+
audienceIds: [],
553+
audienceConditions: [],
554+
includedRules: ['rule_z'],
555+
variations: [{ id: 'var_local', key: 'var_local', variables: [] }],
556+
trafficAllocation: [{ entityId: 'var_local', endOfRange: 5000 }],
557+
},
558+
];
559+
const config = projectConfig.createProjectConfig(datafile as any);
560+
561+
const forRuleZ = getHoldoutsForRule(config, 'rule_z');
562+
expect(forRuleZ).toHaveLength(1);
563+
expect(forRuleZ[0].id).toBe('local_only');
564+
// global holdout must never appear in rule lookups
565+
const allRuleHoldoutIds = forRuleZ.map(h => h.id);
566+
expect(allRuleHoldoutIds).not.toContain('global_holdout_id');
567+
});
568+
488569
it('getHoldoutsForRule should return empty array for an unknown rule ID', () => {
489570
const config = projectConfig.createProjectConfig(cloneDeep(makeHoldoutsDatafile()) as any);
490571
const forUnknown = getHoldoutsForRule(config, 'nonexistent_rule');

0 commit comments

Comments
 (0)