Skip to content

Commit 688e764

Browse files
committed
feat: abstracted-from-segment-result
1 parent b2c7499 commit 688e764

File tree

2 files changed

+127
-40
lines changed

2 files changed

+127
-40
lines changed

flagsmith-engine/segments/models.ts

Lines changed: 49 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { isSemver } from './util.js';
2121
import { EvaluationResultSegments } from '../evaluationResult/models.js';
2222
import { EvaluationContext } from '../evaluationContext/evaluationContext.types.js';
2323
import { CONSTANTS } from '../features/constants.js';
24+
import { SegmentContext } from '../evaluationResult/evaluationResult.types.js';
2425

2526
export const all = (iterable: Array<any>) => iterable.filter(e => !!e).length === iterable.length;
2627
export const any = (iterable: Array<any>) => iterable.filter(e => !!e).length > 0;
@@ -167,49 +168,57 @@ export class SegmentModel {
167168
if (segmentContext) {
168169
const segment = new SegmentModel(parseInt(segmentContext.key), segmentContext.name);
169170
segment.rules = segmentContext.rules.map(rule => new SegmentRuleModel(rule.type));
170-
segment.featureStates =
171-
segmentContext.overrides?.map(override => {
172-
const feature = new FeatureModel(
173-
parseInt(override.feature_key),
174-
override.name,
175-
override?.variants?.length && override?.variants?.length > 1
176-
? CONSTANTS.MULTIVARIATE
177-
: CONSTANTS.STANDARD
178-
);
179-
180-
const featureState = new FeatureStateModel(
181-
feature,
182-
override.enabled,
183-
override.priority || 0
184-
);
185-
186-
if (override.value !== undefined) {
187-
featureState.setValue(override.value);
188-
}
189-
190-
if (
191-
override.variants &&
192-
override?.variants?.length > 1 &&
193-
override.variants.length > 0
194-
) {
195-
featureState.multivariateFeatureStateValues = override.variants.map(
196-
variant =>
197-
new MultivariateFeatureStateValueModel(
198-
new MultivariateFeatureOptionModel(
199-
variant.value,
200-
variant?.id as number
201-
),
202-
variant.weight as number,
203-
variant.id as number
204-
)
205-
);
206-
}
207-
208-
return featureState;
209-
}) || [];
171+
segment.featureStates = SegmentModel.createFeatureStatesFromOverrides(
172+
segmentContext.overrides || []
173+
);
210174
segmentModels.push(segment);
211175
}
212176
}
177+
213178
return segmentModels;
214179
}
180+
181+
private static createFeatureStatesFromOverrides(
182+
overrides: SegmentContext['overrides']
183+
): FeatureStateModel[] {
184+
if (!overrides) return [];
185+
return overrides.map(override => {
186+
const feature = new FeatureModel(
187+
parseInt(override.feature_key),
188+
override.name,
189+
override.variants?.length && override.variants.length > 0
190+
? CONSTANTS.MULTIVARIATE
191+
: CONSTANTS.STANDARD
192+
);
193+
194+
const featureState = new FeatureStateModel(
195+
feature,
196+
override.enabled,
197+
override.priority || 0
198+
);
199+
200+
if (override.value !== undefined) {
201+
featureState.setValue(override.value);
202+
}
203+
204+
if (override.variants && override.variants.length > 0) {
205+
featureState.multivariateFeatureStateValues = this.createMultivariateValues(
206+
override.variants
207+
);
208+
}
209+
210+
return featureState;
211+
});
212+
}
213+
214+
private static createMultivariateValues(variants: any[]): MultivariateFeatureStateValueModel[] {
215+
return variants.map(
216+
variant =>
217+
new MultivariateFeatureStateValueModel(
218+
new MultivariateFeatureOptionModel(variant.value, variant.id as number),
219+
variant.weight as number,
220+
variant.id as number
221+
)
222+
);
223+
}
215224
}

tests/engine/unit/segments/segments_model.test.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { EvaluationContext } from '../../../../flagsmith-engine/evaluationContext/evaluationContext.types';
2+
import { CONSTANTS } from '../../../../flagsmith-engine/features/constants';
13
import {
24
ALL_RULE,
35
ANY_RULE,
@@ -8,6 +10,7 @@ import {
810
all,
911
any,
1012
SegmentConditionModel,
13+
SegmentModel,
1114
SegmentRuleModel
1215
} from '../../../../flagsmith-engine/segments/models';
1316

@@ -135,3 +138,78 @@ test('test_segment_rule_matching_function', () => {
135138
expect(new SegmentRuleModel(testCase[0]).matchingFunction()).toBe(testCase[1]);
136139
}
137140
});
141+
142+
test('test_fromSegmentResult_with_multiple_variants', () => {
143+
const segmentResults = [{ key: '1', name: 'test_segment' }];
144+
145+
const evaluationContext: EvaluationContext = {
146+
identity: {
147+
key: 'not_exist',
148+
identifier: 'not_exist'
149+
},
150+
environment: {
151+
key: 'test',
152+
name: 'test'
153+
},
154+
features: {},
155+
segments: {
156+
'1': {
157+
key: '1',
158+
name: 'test_segment',
159+
rules: [
160+
{
161+
type: 'ALL',
162+
conditions: [
163+
{
164+
property: '$.identity.identifier',
165+
operator: 'EQUAL',
166+
value: 'test-user'
167+
}
168+
]
169+
}
170+
],
171+
overrides: [
172+
{
173+
key: 'override',
174+
feature_key: '1',
175+
name: 'multivariate_feature',
176+
enabled: true,
177+
value: 'default_value',
178+
priority: 1,
179+
variants: [
180+
{ id: 1, value: 'variant_a', weight: 30 },
181+
{ id: 2, value: 'variant_b', weight: 70 }
182+
]
183+
}
184+
]
185+
}
186+
}
187+
};
188+
189+
const result = SegmentModel.fromSegmentResult(segmentResults, evaluationContext);
190+
191+
expect(result).toHaveLength(1);
192+
193+
const segment = result[0];
194+
expect(segment.name).toBe('test_segment');
195+
expect(segment.featureStates).toHaveLength(1);
196+
197+
const featureState = segment.featureStates[0];
198+
expect(featureState.feature.name).toBe('multivariate_feature');
199+
expect(featureState.feature.type).toBe(CONSTANTS.MULTIVARIATE);
200+
expect(featureState.enabled).toBe(true);
201+
expect(featureState.getValue()).toBe('default_value');
202+
203+
// Test multivariate variants
204+
expect(featureState.multivariateFeatureStateValues).toHaveLength(2);
205+
206+
const variant1 = featureState.multivariateFeatureStateValues[0];
207+
expect(variant1.multivariateFeatureOption.value).toBe('variant_a');
208+
expect(variant1.percentageAllocation).toBe(30);
209+
expect(variant1.id).toBe(1);
210+
211+
const variant2 = featureState.multivariateFeatureStateValues[1];
212+
expect(variant2.multivariateFeatureOption.value).toBe('variant_b');
213+
expect(variant2.percentageAllocation).toBe(70);
214+
expect(variant2.id).toBe(2);
215+
});

0 commit comments

Comments
 (0)