-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sameeran/ff 1130 sdk assigns subjects to a holdout js common #27
Changes from all commits
54f3e77
e4095ce
9fdaab4
438fcec
1e51348
ee0478e
02bc5bd
370ffda
ed0f1d9
b233553
ddd7130
375b13d
b837c3f
b4a85fe
87cfce9
c02aa8d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -87,7 +87,7 @@ describe('EppoClient E2E test', () => { | |
const mockExperimentConfig = { | ||
name: flagKey, | ||
enabled: true, | ||
subjectShards: 100, | ||
subjectShards: 10000, | ||
overrides: {}, | ||
typedOverrides: {}, | ||
rules: [ | ||
|
@@ -99,32 +99,35 @@ describe('EppoClient E2E test', () => { | |
allocations: { | ||
allocation1: { | ||
percentExposure: 1, | ||
statusQuoVariationKey: null, | ||
shippedVariationKey: null, | ||
holdouts: [], | ||
variations: [ | ||
{ | ||
name: 'control', | ||
value: 'control', | ||
typedValue: 'control', | ||
shardRange: { | ||
start: 0, | ||
end: 34, | ||
end: 3333, | ||
}, | ||
}, | ||
{ | ||
name: 'variant-1', | ||
value: 'variant-1', | ||
typedValue: 'variant-1', | ||
shardRange: { | ||
start: 34, | ||
end: 67, | ||
start: 3333, | ||
end: 6667, | ||
}, | ||
}, | ||
{ | ||
name: 'variant-2', | ||
value: 'variant-2', | ||
typedValue: 'variant-2', | ||
shardRange: { | ||
start: 67, | ||
end: 100, | ||
start: 6667, | ||
end: 10000, | ||
}, | ||
}, | ||
], | ||
|
@@ -470,14 +473,17 @@ describe('EppoClient E2E test', () => { | |
allocations: { | ||
allocation1: { | ||
percentExposure: 1, | ||
statusQuoVariationKey: null, | ||
shippedVariationKey: null, | ||
holdouts: [], | ||
variations: [ | ||
{ | ||
name: 'control', | ||
value: 'control', | ||
typedValue: 'control', | ||
shardRange: { | ||
start: 0, | ||
end: 100, | ||
end: 10000, | ||
}, | ||
}, | ||
{ | ||
|
@@ -502,6 +508,9 @@ describe('EppoClient E2E test', () => { | |
allocations: { | ||
allocation1: { | ||
percentExposure: 1, | ||
statusQuoVariationKey: null, | ||
shippedVariationKey: null, | ||
holdouts: [], | ||
variations: [ | ||
{ | ||
name: 'control', | ||
|
@@ -518,7 +527,7 @@ describe('EppoClient E2E test', () => { | |
typedValue: 'treatment', | ||
shardRange: { | ||
start: 0, | ||
end: 100, | ||
end: 10000, | ||
}, | ||
}, | ||
], | ||
|
@@ -546,14 +555,17 @@ describe('EppoClient E2E test', () => { | |
allocations: { | ||
allocation1: { | ||
percentExposure: 1, | ||
statusQuoVariationKey: null, | ||
shippedVariationKey: null, | ||
holdouts: [], | ||
variations: [ | ||
{ | ||
name: 'some-new-treatment', | ||
value: 'some-new-treatment', | ||
typedValue: 'some-new-treatment', | ||
shardRange: { | ||
start: 0, | ||
end: 100, | ||
end: 10000, | ||
}, | ||
}, | ||
], | ||
|
@@ -596,13 +608,221 @@ describe('EppoClient E2E test', () => { | |
|
||
const client = new EppoClient(storage); | ||
let assignment = client.getAssignment('subject-10', flagKey, { appVersion: 9 }); | ||
expect(assignment).toEqual(null); | ||
expect(assignment).toBeNull(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice being more explicit |
||
assignment = client.getAssignment('subject-10', flagKey); | ||
expect(assignment).toEqual(null); | ||
expect(assignment).toBeNull(); | ||
assignment = client.getAssignment('subject-10', flagKey, { appVersion: 11 }); | ||
expect(assignment).toEqual('control'); | ||
}); | ||
|
||
it('returns control variation and logs holdout key if subject is in holdout in an experiment allocation', () => { | ||
const entry = { | ||
...mockExperimentConfig, | ||
allocations: { | ||
allocation1: { | ||
percentExposure: 1, | ||
statusQuoVariationKey: 'variation-7', | ||
shippedVariationKey: null, | ||
holdouts: [ | ||
{ | ||
holdoutKey: 'holdout-2', | ||
statusQuoShardRange: { | ||
start: 0, | ||
end: 200, | ||
}, | ||
shippedShardRange: null, // this is an experiment allocation because shippedShardRange is null | ||
}, | ||
{ | ||
holdoutKey: 'holdout-3', | ||
statusQuoShardRange: { | ||
start: 200, | ||
end: 400, | ||
}, | ||
shippedShardRange: null, | ||
}, | ||
], | ||
variations: [ | ||
{ | ||
name: 'control', | ||
value: 'control', | ||
typedValue: 'control', | ||
shardRange: { | ||
start: 0, | ||
end: 3333, | ||
}, | ||
variationKey: 'variation-7', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was key introduced as an immutable identifier for a variation? Is it basically There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup. I think in could be helpful to have variation keys in case we need to add more methods for working with variations |
||
}, | ||
{ | ||
name: 'variant-1', | ||
value: 'variant-1', | ||
typedValue: 'variant-1', | ||
shardRange: { | ||
start: 3333, | ||
end: 6667, | ||
}, | ||
variationKey: 'variation-8', | ||
}, | ||
{ | ||
name: 'variant-2', | ||
value: 'variant-2', | ||
typedValue: 'variant-2', | ||
shardRange: { | ||
start: 6667, | ||
end: 10000, | ||
}, | ||
variationKey: 'variation-9', | ||
}, | ||
], | ||
}, | ||
}, | ||
}; | ||
|
||
storage.setEntries({ [flagKey]: entry }); | ||
|
||
const mockLogger = td.object<IAssignmentLogger>(); | ||
const client = new EppoClient(storage); | ||
client.setLogger(mockLogger); | ||
td.reset(); | ||
|
||
// subject-79 --> holdout shard is 186 | ||
let assignment = client.getAssignment('subject-79', flagKey); | ||
expect(assignment).toEqual('control'); | ||
// Only log holdout key (not variation) if this is an experiment allocation | ||
expect(td.explain(mockLogger.logAssignment).calls[0].args[0].holdoutVariation).toBeNull(); | ||
expect(td.explain(mockLogger.logAssignment).calls[0].args[0].holdout).toEqual('holdout-2'); | ||
|
||
// subject-8 --> holdout shard is 201 | ||
assignment = client.getAssignment('subject-8', flagKey); | ||
expect(assignment).toEqual('control'); | ||
// Only log holdout key (not variation) if this is an experiment allocation | ||
expect(td.explain(mockLogger.logAssignment).calls[1].args[0].holdoutVariation).toBeNull(); | ||
expect(td.explain(mockLogger.logAssignment).calls[1].args[0].holdout).toEqual('holdout-3'); | ||
|
||
// subject-11 --> holdout shard is 9137 (outside holdout), non-holdout assignment shard is 8414 | ||
assignment = client.getAssignment('subject-11', flagKey); | ||
expect(assignment).toEqual('variant-2'); | ||
expect(td.explain(mockLogger.logAssignment).calls[2].args[0].holdoutVariation).toBeNull(); | ||
expect(td.explain(mockLogger.logAssignment).calls[2].args[0].holdout).toBeNull(); | ||
Comment on lines
+704
to
+705
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❤️ |
||
}); | ||
|
||
it('returns the shipped variation and logs holdout key and variation if subject is in holdout in a rollout allocation', () => { | ||
const entry = { | ||
...mockExperimentConfig, | ||
allocations: { | ||
allocation1: { | ||
percentExposure: 1, | ||
statusQuoVariationKey: 'variation-7', | ||
shippedVariationKey: 'variation-8', | ||
holdouts: [ | ||
{ | ||
holdoutKey: 'holdout-2', | ||
statusQuoShardRange: { | ||
start: 0, | ||
end: 100, | ||
}, | ||
shippedShardRange: { | ||
start: 100, | ||
end: 200, | ||
}, | ||
}, | ||
{ | ||
holdoutKey: 'holdout-3', | ||
statusQuoShardRange: { | ||
start: 200, | ||
end: 300, | ||
}, | ||
shippedShardRange: { | ||
start: 300, | ||
end: 400, | ||
}, | ||
}, | ||
], | ||
variations: [ | ||
{ | ||
name: 'control', | ||
value: 'control', | ||
typedValue: 'control', | ||
shardRange: { | ||
start: 0, | ||
end: 0, | ||
}, | ||
variationKey: 'variation-7', | ||
}, | ||
{ | ||
name: 'variant-1', | ||
value: 'variant-1', | ||
typedValue: 'variant-1', | ||
shardRange: { | ||
start: 0, | ||
end: 0, | ||
}, | ||
variationKey: 'variation-8', | ||
}, | ||
{ | ||
name: 'variant-2', | ||
value: 'variant-2', | ||
typedValue: 'variant-2', | ||
shardRange: { | ||
start: 0, | ||
end: 10000, | ||
}, | ||
variationKey: 'variation-9', | ||
}, | ||
], | ||
}, | ||
}, | ||
}; | ||
|
||
storage.setEntries({ [flagKey]: entry }); | ||
|
||
const mockLogger = td.object<IAssignmentLogger>(); | ||
const client = new EppoClient(storage); | ||
client.setLogger(mockLogger); | ||
td.reset(); | ||
|
||
// subject-227 --> holdout shard is 57 | ||
let assignment = client.getAssignment('subject-227', flagKey); | ||
expect(assignment).toEqual('control'); | ||
// Log both holdout key and variation if this is a rollout allocation | ||
expect(td.explain(mockLogger.logAssignment).calls[0].args[0].holdoutVariation).toEqual( | ||
'status_quo', | ||
); | ||
expect(td.explain(mockLogger.logAssignment).calls[0].args[0].holdout).toEqual('holdout-2'); | ||
|
||
// subject-79 --> holdout shard is 186 | ||
assignment = client.getAssignment('subject-79', flagKey); | ||
expect(assignment).toEqual('variant-1'); | ||
// Log both holdout key and variation if this is a rollout allocation | ||
expect(td.explain(mockLogger.logAssignment).calls[1].args[0].holdoutVariation).toEqual( | ||
'all_shipped_variants', | ||
); | ||
expect(td.explain(mockLogger.logAssignment).calls[1].args[0].holdout).toEqual('holdout-2'); | ||
|
||
// subject-8 --> holdout shard is 201 | ||
assignment = client.getAssignment('subject-8', flagKey); | ||
expect(assignment).toEqual('control'); | ||
// Log both holdout key and variation if this is a rollout allocation | ||
expect(td.explain(mockLogger.logAssignment).calls[2].args[0].holdoutVariation).toEqual( | ||
'status_quo', | ||
); | ||
expect(td.explain(mockLogger.logAssignment).calls[2].args[0].holdout).toEqual('holdout-3'); | ||
|
||
// subject-50 --> holdout shard is 347 | ||
assignment = client.getAssignment('subject-50', flagKey); | ||
expect(assignment).toEqual('variant-1'); | ||
// Log both holdout key and variation if this is a rollout allocation | ||
expect(td.explain(mockLogger.logAssignment).calls[3].args[0].holdoutVariation).toEqual( | ||
'all_shipped_variants', | ||
); | ||
expect(td.explain(mockLogger.logAssignment).calls[3].args[0].holdout).toEqual('holdout-3'); | ||
|
||
// subject-7 --> holdout shard is 9483 (outside holdout), non-holdout assignment shard is 8673 | ||
assignment = client.getAssignment('subject-7', flagKey); | ||
expect(assignment).toEqual('variant-2'); | ||
expect(td.explain(mockLogger.logAssignment).calls[4].args[0].holdoutVariation).toBeNull(); | ||
expect(td.explain(mockLogger.logAssignment).calls[4].args[0].holdout).toBeNull(); | ||
}); | ||
|
||
function getAssignmentsWithSubjectAttributes( | ||
subjectsWithAttributes: { | ||
subjectKey: string; | ||
|
@@ -732,7 +952,7 @@ describe('EppoClient E2E test', () => { | |
}, | ||
); | ||
|
||
expect(variation).not.toEqual(null); | ||
expect(variation).not.toBeNull(); | ||
expect(td.explain(mockLogger.logAssignment).callCount).toEqual(1); | ||
}); | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice