flagsmith-nodejs 1.1.3 → 2.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/pull_request.yaml +33 -0
- package/.gitmodules +3 -0
- package/.husky/pre-commit +6 -0
- package/.tool-versions +1 -0
- package/example/README.md +0 -6
- package/example/package-lock.json +1070 -2
- package/example/package.json +4 -3
- package/example/server/api/index.js +23 -18
- package/example/server/index.js +7 -6
- package/flagsmith-engine/environments/integrations/models.ts +4 -0
- package/flagsmith-engine/environments/models.ts +50 -0
- package/flagsmith-engine/environments/util.ts +29 -0
- package/flagsmith-engine/features/constants.ts +4 -0
- package/flagsmith-engine/features/models.ts +105 -0
- package/flagsmith-engine/features/util.ts +38 -0
- package/flagsmith-engine/identities/models.ts +60 -0
- package/flagsmith-engine/identities/traits/models.ts +9 -0
- package/flagsmith-engine/identities/util.ts +30 -0
- package/flagsmith-engine/index.ts +93 -0
- package/flagsmith-engine/organisations/models.ts +25 -0
- package/flagsmith-engine/organisations/util.ts +11 -0
- package/flagsmith-engine/projects/models.ts +22 -0
- package/flagsmith-engine/projects/util.ts +18 -0
- package/flagsmith-engine/segments/constants.ts +31 -0
- package/flagsmith-engine/segments/evaluators.ts +72 -0
- package/flagsmith-engine/segments/models.ts +103 -0
- package/flagsmith-engine/segments/util.ts +29 -0
- package/flagsmith-engine/utils/collections.ts +14 -0
- package/flagsmith-engine/utils/errors.ts +1 -0
- package/flagsmith-engine/utils/hashing/index.ts +52 -0
- package/flagsmith-engine/utils/index.ts +10 -0
- package/index.ts +6 -0
- package/jest.config.js +5 -0
- package/package.json +30 -12
- package/sdk/analytics.ts +60 -0
- package/sdk/errors.ts +2 -0
- package/sdk/index.ts +329 -0
- package/sdk/models.ts +145 -0
- package/sdk/polling_manager.ts +31 -0
- package/sdk/utils.ts +45 -0
- package/tests/engine/e2e/engine.test.ts +51 -0
- package/tests/engine/engine-tests/engine-test-data/data/environment_n9fbf9h3v4fFgH3U3ngWhb.json +12393 -0
- package/tests/engine/engine-tests/engine-test-data/readme.md +30 -0
- package/tests/engine/unit/egine.test.ts +96 -0
- package/tests/engine/unit/environments/builder.test.ts +148 -0
- package/tests/engine/unit/environments/models.test.ts +49 -0
- package/tests/engine/unit/features/models.test.ts +72 -0
- package/tests/engine/unit/identities/identities_builders.test.ts +85 -0
- package/tests/engine/unit/identities/identities_models.test.ts +105 -0
- package/tests/engine/unit/organization/models.test.ts +12 -0
- package/tests/engine/unit/segments/segments_model.test.ts +101 -0
- package/tests/engine/unit/segments/util.ts +151 -0
- package/tests/engine/unit/utils.ts +114 -0
- package/tests/index.js +0 -0
- package/tests/sdk/analytics.test.ts +43 -0
- package/tests/sdk/data/environment.json +70 -0
- package/tests/sdk/data/flags.json +20 -0
- package/tests/sdk/data/identities.json +29 -0
- package/tests/sdk/flagsmith.test.ts +203 -0
- package/tests/sdk/polling.test.ts +34 -0
- package/tests/sdk/utils.ts +39 -0
- package/tsconfig.json +19 -0
- package/flagsmith-core.js +0 -243
- package/index.d.ts +0 -85
- package/index.js +0 -3
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Engine Test Data
|
|
2
|
+
|
|
3
|
+
This repository contains a single directory containing json files that can be used to test that any Flagsmith engine
|
|
4
|
+
written in a given language is correct.
|
|
5
|
+
|
|
6
|
+
Each JSON file should consist of a single object in the following format.
|
|
7
|
+
|
|
8
|
+
```json
|
|
9
|
+
{
|
|
10
|
+
"environment": {...}, // the environment document as found in DynamoDB
|
|
11
|
+
"identities_and_responses": [
|
|
12
|
+
{
|
|
13
|
+
"identity": {...}, // the identity as found in DynamoDB,
|
|
14
|
+
"response": {...}, // the response that was obtained from the current API
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
To use this data, you will need to write a test case in the repository which contains the engine code and include
|
|
21
|
+
this repository as a submodule to get access to the json files.
|
|
22
|
+
|
|
23
|
+
To add the git submodule:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
git submodule add git@github.com:Flagsmith/engine-test-data.git tests/engine_tests/engine-test-data
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
An example of how to use the test data can be found in the flagsmith-flag-engine repository
|
|
30
|
+
[here](https://github.com/Flagsmith/flagsmith-engine/blob/main/tests/engine_tests/test_engine.py).
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getEnvironmentFeatureState,
|
|
3
|
+
getEnvironmentFeatureStates,
|
|
4
|
+
getIdentityFeatureState,
|
|
5
|
+
getIdentityFeatureStates
|
|
6
|
+
} from '../../../flagsmith-engine';
|
|
7
|
+
import { CONSTANTS } from '../../../flagsmith-engine/features/constants';
|
|
8
|
+
import { FeatureModel, FeatureStateModel } from '../../../flagsmith-engine/features/models';
|
|
9
|
+
import { TraitModel } from '../../../flagsmith-engine/identities/traits/models';
|
|
10
|
+
import {
|
|
11
|
+
environment,
|
|
12
|
+
environmentWithSegmentOverride,
|
|
13
|
+
feature1,
|
|
14
|
+
getEnvironmentFeatureStateForFeature,
|
|
15
|
+
getEnvironmentFeatureStateForFeatureByName,
|
|
16
|
+
identity,
|
|
17
|
+
identityInSegment,
|
|
18
|
+
segmentConditionProperty,
|
|
19
|
+
segmentConditionStringValue
|
|
20
|
+
} from './utils';
|
|
21
|
+
|
|
22
|
+
test('test_identity_get_feature_state_without_any_override', () => {
|
|
23
|
+
const feature_state = getIdentityFeatureState(environment(), identity(), feature1().name);
|
|
24
|
+
|
|
25
|
+
expect(feature_state.feature).toStrictEqual(feature1());
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('test_identity_get_all_feature_states_no_segments', () => {
|
|
29
|
+
const env = environment();
|
|
30
|
+
const ident = identity();
|
|
31
|
+
const overridden_feature = new FeatureModel(3, 'overridden_feature', CONSTANTS.STANDARD);
|
|
32
|
+
|
|
33
|
+
env.featureStates.push(new FeatureStateModel(overridden_feature, false, 3));
|
|
34
|
+
|
|
35
|
+
ident.identityFeatures = [new FeatureStateModel(overridden_feature, true, 4)];
|
|
36
|
+
|
|
37
|
+
const featureStates = getIdentityFeatureStates(env, ident);
|
|
38
|
+
|
|
39
|
+
expect(featureStates.length).toBe(3);
|
|
40
|
+
for (const featuresState of featureStates) {
|
|
41
|
+
const environmentFeatureState = getEnvironmentFeatureStateForFeature(
|
|
42
|
+
env,
|
|
43
|
+
featuresState.feature
|
|
44
|
+
);
|
|
45
|
+
const expected =
|
|
46
|
+
environmentFeatureState?.feature == overridden_feature
|
|
47
|
+
? true
|
|
48
|
+
: environmentFeatureState?.enabled;
|
|
49
|
+
expect(featuresState.enabled).toBe(expected);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('test_identity_get_all_feature_states_with_traits', () => {
|
|
54
|
+
const trait_models = new TraitModel(segmentConditionProperty, segmentConditionStringValue);
|
|
55
|
+
|
|
56
|
+
const featureStates = getIdentityFeatureStates(
|
|
57
|
+
environmentWithSegmentOverride(),
|
|
58
|
+
identityInSegment(),
|
|
59
|
+
[trait_models]
|
|
60
|
+
);
|
|
61
|
+
expect(featureStates[0].getValue()).toBe('segment_override');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('test_environment_get_all_feature_states', () => {
|
|
65
|
+
const env = environment();
|
|
66
|
+
const featureStates = getEnvironmentFeatureStates(env);
|
|
67
|
+
|
|
68
|
+
expect(featureStates).toBe(env.featureStates);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('test_environment_get_feature_states_hides_disabled_flags_if_enabled', () => {
|
|
72
|
+
const env = environment();
|
|
73
|
+
|
|
74
|
+
env.project.hideDisabledFlags = true;
|
|
75
|
+
|
|
76
|
+
const featureStates = getEnvironmentFeatureStates(env);
|
|
77
|
+
|
|
78
|
+
expect(featureStates).not.toBe(env.featureStates);
|
|
79
|
+
for (const fs of featureStates) {
|
|
80
|
+
expect(fs.enabled).toBe(true);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('test_environment_get_feature_state', () => {
|
|
85
|
+
const env = environment();
|
|
86
|
+
const feature = feature1();
|
|
87
|
+
const featureState = getEnvironmentFeatureState(env, feature.name);
|
|
88
|
+
|
|
89
|
+
expect(featureState.feature).toStrictEqual(feature);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('test_environment_get_feature_state_raises_feature_state_not_found', () => {
|
|
93
|
+
expect(() => {
|
|
94
|
+
getEnvironmentFeatureState(environment(), 'not_a_feature_name');
|
|
95
|
+
}).toThrowError('Feature State Not Found');
|
|
96
|
+
});
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { EnvironmentModel } from '../../../../flagsmith-engine/environments/models';
|
|
2
|
+
import {
|
|
3
|
+
buildEnvironmentAPIKeyModel,
|
|
4
|
+
buildEnvironmentModel
|
|
5
|
+
} from '../../../../flagsmith-engine/environments/util';
|
|
6
|
+
import { CONSTANTS } from '../../../../flagsmith-engine/features/constants';
|
|
7
|
+
import {
|
|
8
|
+
FeatureStateModel,
|
|
9
|
+
MultivariateFeatureStateValueModel
|
|
10
|
+
} from '../../../../flagsmith-engine/features/models';
|
|
11
|
+
import { getEnvironmentFeatureStateForFeatureByName } from '../utils';
|
|
12
|
+
|
|
13
|
+
test('test_get_flags_for_environment_returns_feature_states_for_environment_dictionary', () => {
|
|
14
|
+
const stringValue = 'foo';
|
|
15
|
+
const featureWithStringValueName = 'feature_with_string_value';
|
|
16
|
+
|
|
17
|
+
const environmentDict = {
|
|
18
|
+
id: 1,
|
|
19
|
+
api_key: 'api-key',
|
|
20
|
+
project: {
|
|
21
|
+
id: 1,
|
|
22
|
+
name: 'test project',
|
|
23
|
+
organisation: {
|
|
24
|
+
id: 1,
|
|
25
|
+
name: 'Test Org',
|
|
26
|
+
stop_serving_flags: false,
|
|
27
|
+
persist_trait_data: true,
|
|
28
|
+
feature_analytics: true
|
|
29
|
+
},
|
|
30
|
+
hide_disabled_flags: false
|
|
31
|
+
},
|
|
32
|
+
feature_states: [
|
|
33
|
+
{
|
|
34
|
+
id: 1,
|
|
35
|
+
enabled: true,
|
|
36
|
+
feature_state_value: undefined,
|
|
37
|
+
feature: { id: 1, name: 'enabled_feature', type: CONSTANTS.STANDARD }
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: 2,
|
|
41
|
+
enabled: false,
|
|
42
|
+
feature_state_value: undefined,
|
|
43
|
+
feature: { id: 2, name: 'disabled_feature', type: CONSTANTS.STANDARD }
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: 3,
|
|
47
|
+
enabled: true,
|
|
48
|
+
feature_state_value: stringValue,
|
|
49
|
+
feature: {
|
|
50
|
+
id: 3,
|
|
51
|
+
name: featureWithStringValueName,
|
|
52
|
+
type: CONSTANTS.STANDARD
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const environmentModel = buildEnvironmentModel(environmentDict);
|
|
59
|
+
|
|
60
|
+
expect(environmentModel).toBeInstanceOf(EnvironmentModel);
|
|
61
|
+
expect(environmentModel.featureStates.length).toBe(3);
|
|
62
|
+
for (const fs of environmentModel.featureStates) {
|
|
63
|
+
expect(fs).toBeInstanceOf(FeatureStateModel);
|
|
64
|
+
}
|
|
65
|
+
const receivedValue = getEnvironmentFeatureStateForFeatureByName(
|
|
66
|
+
environmentModel,
|
|
67
|
+
featureWithStringValueName
|
|
68
|
+
)?.getValue();
|
|
69
|
+
expect(receivedValue).toBe(stringValue);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('test_build_environment_model_with_multivariate_flag', () => {
|
|
73
|
+
const variate1Value = 'value-1';
|
|
74
|
+
const variate2Value = 'value-2';
|
|
75
|
+
|
|
76
|
+
const environmentJSON = {
|
|
77
|
+
id: 1,
|
|
78
|
+
api_key: 'api-key',
|
|
79
|
+
project: {
|
|
80
|
+
id: 1,
|
|
81
|
+
name: 'test project',
|
|
82
|
+
organisation: {
|
|
83
|
+
id: 1,
|
|
84
|
+
name: 'Test Org',
|
|
85
|
+
stop_serving_flags: false,
|
|
86
|
+
persist_trait_data: true,
|
|
87
|
+
feature_analytics: true
|
|
88
|
+
},
|
|
89
|
+
hide_disabled_flags: false
|
|
90
|
+
},
|
|
91
|
+
feature_states: [
|
|
92
|
+
{
|
|
93
|
+
id: 1,
|
|
94
|
+
enabled: true,
|
|
95
|
+
feature_state_value: undefined,
|
|
96
|
+
feature: {
|
|
97
|
+
id: 1,
|
|
98
|
+
name: 'enabled_feature',
|
|
99
|
+
type: CONSTANTS.STANDARD
|
|
100
|
+
},
|
|
101
|
+
multivariate_feature_state_values: [
|
|
102
|
+
{
|
|
103
|
+
id: 1,
|
|
104
|
+
percentage_allocation: 10.0,
|
|
105
|
+
multivariate_feature_option: {
|
|
106
|
+
value: variate1Value
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
id: 2,
|
|
111
|
+
percentage_allocation: 10.0,
|
|
112
|
+
multivariate_feature_option: {
|
|
113
|
+
value: variate2Value,
|
|
114
|
+
id: 2
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const environmentModel = buildEnvironmentModel(environmentJSON);
|
|
123
|
+
|
|
124
|
+
expect(environmentModel).toBeInstanceOf(EnvironmentModel);
|
|
125
|
+
expect(environmentJSON.feature_states.length).toBe(1);
|
|
126
|
+
|
|
127
|
+
const fs = environmentModel.featureStates[0];
|
|
128
|
+
|
|
129
|
+
for (const mvfs of fs.multivariateFeatureStateValues) {
|
|
130
|
+
expect(mvfs).toBeInstanceOf(MultivariateFeatureStateValueModel);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test('test_build_environment_api_key_model', () => {
|
|
135
|
+
const environmentKeyJSON = {
|
|
136
|
+
key: 'ser.7duQYrsasJXqdGsdaagyfU',
|
|
137
|
+
active: true,
|
|
138
|
+
created_at: '2022-02-07T04:58:25.969438+00:00',
|
|
139
|
+
client_api_key: 'RQchaCQ2mYicSCAwKoAg2E',
|
|
140
|
+
id: 10,
|
|
141
|
+
name: 'api key 2',
|
|
142
|
+
expires_at: undefined
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const environmentAPIKeyModel = buildEnvironmentAPIKeyModel(environmentKeyJSON);
|
|
146
|
+
|
|
147
|
+
expect(environmentAPIKeyModel.key).toBe(environmentKeyJSON['key']);
|
|
148
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { EnvironmentAPIKeyModel } from '../../../../flagsmith-engine/environments/models';
|
|
2
|
+
|
|
3
|
+
test('test_environment_api_key_model_is_valid_is_true_for_non_expired_active_key', () => {
|
|
4
|
+
const environmentAPIKeyModel = new EnvironmentAPIKeyModel(
|
|
5
|
+
1,
|
|
6
|
+
'ser.random_key',
|
|
7
|
+
Date.now(),
|
|
8
|
+
'test_key',
|
|
9
|
+
'test_key'
|
|
10
|
+
);
|
|
11
|
+
expect(environmentAPIKeyModel.isValid()).toBe(true);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test('test_environment_api_key_model_is_valid_is_true_for_non_expired_active_key_with_expired_date_in_future', () => {
|
|
15
|
+
const environmentAPIKeyModel = new EnvironmentAPIKeyModel(
|
|
16
|
+
1,
|
|
17
|
+
'ser.random_key',
|
|
18
|
+
Date.now(),
|
|
19
|
+
'test_key',
|
|
20
|
+
'test_key',
|
|
21
|
+
Date.now() + 1000 * 60 * 60 * 24 * 2
|
|
22
|
+
);
|
|
23
|
+
expect(environmentAPIKeyModel.isValid()).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('test_environment_api_key_model_is_valid_is_false_for_expired_active_key', () => {
|
|
27
|
+
const environmentAPIKeyModel = new EnvironmentAPIKeyModel(
|
|
28
|
+
1,
|
|
29
|
+
'ser.random_key',
|
|
30
|
+
Date.now() - 1000 * 60 * 60 * 24 * 2,
|
|
31
|
+
'test_key',
|
|
32
|
+
'test_key',
|
|
33
|
+
Date.now()
|
|
34
|
+
);
|
|
35
|
+
expect(environmentAPIKeyModel.isValid()).toBe(false);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('test_environment_api_key_model_is_valid_is_false_for_non_expired_inactive_key', () => {
|
|
39
|
+
const environmentAPIKeyModel = new EnvironmentAPIKeyModel(
|
|
40
|
+
1,
|
|
41
|
+
'ser.random_key',
|
|
42
|
+
Date.now(),
|
|
43
|
+
'test_key',
|
|
44
|
+
'test_key'
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
environmentAPIKeyModel.active = false;
|
|
48
|
+
expect(environmentAPIKeyModel.isValid()).toBe(false);
|
|
49
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { CONSTANTS } from '../../../../flagsmith-engine/features/constants';
|
|
2
|
+
import {
|
|
3
|
+
FeatureModel,
|
|
4
|
+
FeatureStateModel,
|
|
5
|
+
MultivariateFeatureOptionModel,
|
|
6
|
+
MultivariateFeatureStateValueModel
|
|
7
|
+
} from '../../../../flagsmith-engine/features/models';
|
|
8
|
+
import { feature1 } from '../utils';
|
|
9
|
+
|
|
10
|
+
test('test_initializing_feature_state_creates_default_feature_state_uuid', () => {
|
|
11
|
+
const featureState = new FeatureStateModel(feature1(), true, 1);
|
|
12
|
+
expect(featureState.featurestateUUID).toBeDefined();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('test_initializing_multivariate_feature_state_value_creates_default_uuid', () => {
|
|
16
|
+
const mvFeatureOption = new MultivariateFeatureOptionModel('value');
|
|
17
|
+
const mvFsValueModel = new MultivariateFeatureStateValueModel(mvFeatureOption, 10, 1);
|
|
18
|
+
|
|
19
|
+
expect(mvFsValueModel.mvFsValueUuid).toBeDefined();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('test_feature_state_get_value_no_mv_values', () => {
|
|
23
|
+
const value = 'foo';
|
|
24
|
+
const featureState = new FeatureStateModel(feature1(), true, 1);
|
|
25
|
+
|
|
26
|
+
featureState.setValue(value);
|
|
27
|
+
|
|
28
|
+
expect(featureState.getValue()).toBe(value);
|
|
29
|
+
expect(featureState.getValue(1)).toBe(value);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test('test_feature_state_get_value_mv_values', () => {
|
|
33
|
+
const mvFeatureControlValue = 'control';
|
|
34
|
+
const mvFeatureValue1 = 'foo';
|
|
35
|
+
const mvFeatureValue2 = 'bar';
|
|
36
|
+
|
|
37
|
+
const cases = [
|
|
38
|
+
[10, mvFeatureValue1],
|
|
39
|
+
[40, mvFeatureValue2],
|
|
40
|
+
[70, mvFeatureControlValue]
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
for (const testCase of cases) {
|
|
44
|
+
const myFeature = new FeatureModel(1, 'mv_feature', CONSTANTS.STANDARD);
|
|
45
|
+
|
|
46
|
+
const mvFeatureOption1 = new MultivariateFeatureOptionModel(mvFeatureValue1, 1);
|
|
47
|
+
const mvFeatureOption2 = new MultivariateFeatureOptionModel(mvFeatureValue2, 2);
|
|
48
|
+
|
|
49
|
+
const mvFeatureStateValue1 = new MultivariateFeatureStateValueModel(
|
|
50
|
+
mvFeatureOption1,
|
|
51
|
+
30,
|
|
52
|
+
1
|
|
53
|
+
);
|
|
54
|
+
const mvFeatureStateValue2 = new MultivariateFeatureStateValueModel(
|
|
55
|
+
mvFeatureOption2,
|
|
56
|
+
30,
|
|
57
|
+
2
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const mvFeatureState = new FeatureStateModel(myFeature, true, 1);
|
|
61
|
+
mvFeatureState.multivariateFeatureStateValues = [
|
|
62
|
+
mvFeatureStateValue1,
|
|
63
|
+
mvFeatureStateValue2
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
mvFeatureState.setValue(mvFeatureControlValue);
|
|
67
|
+
|
|
68
|
+
// TODO
|
|
69
|
+
// expect(mvFeatureState.getValue(3)).toBe(testCase[1]);
|
|
70
|
+
expect(1).toBe(1);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { FeatureStateModel } from '../../../../flagsmith-engine/features/models';
|
|
2
|
+
import { IdentityModel } from '../../../../flagsmith-engine/identities/models';
|
|
3
|
+
import { buildIdentityModel } from '../../../../flagsmith-engine/identities/util';
|
|
4
|
+
|
|
5
|
+
test('test_build_identity_model_from_dictionary_no_feature_states', () => {
|
|
6
|
+
const identity = {
|
|
7
|
+
id: 1,
|
|
8
|
+
identifier: 'test-identity',
|
|
9
|
+
environment_api_key: 'api-key',
|
|
10
|
+
created_date: '2021-08-22T06:25:23.406995Z',
|
|
11
|
+
identity_traits: [{ trait_key: 'trait_key', trait_value: 'trait_value' }]
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const identityModel = buildIdentityModel(identity);
|
|
15
|
+
|
|
16
|
+
expect(identityModel.identityFeatures?.length).toBe(0);
|
|
17
|
+
expect(identityModel.identityTraits.length).toBe(1);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('test_build_identity_model_from_dictionary_uses_identity_feature_list_for_identity_features', () => {
|
|
21
|
+
const identity_dict = {
|
|
22
|
+
id: 1,
|
|
23
|
+
identifier: 'test-identity',
|
|
24
|
+
environment_api_key: 'api-key',
|
|
25
|
+
created_date: '2021-08-22T06:25:23.406995Z',
|
|
26
|
+
identity_features: [
|
|
27
|
+
{
|
|
28
|
+
id: 1,
|
|
29
|
+
feature: {
|
|
30
|
+
id: 1,
|
|
31
|
+
name: 'test_feature',
|
|
32
|
+
type: 'STANDARD'
|
|
33
|
+
},
|
|
34
|
+
enabled: true,
|
|
35
|
+
feature_state_value: 'some-value'
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const identityModel = buildIdentityModel(identity_dict);
|
|
41
|
+
|
|
42
|
+
expect(identityModel.identityFeatures?.length).toBe(1);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('test_build_build_identity_model_from_dict_creates_identity_uuid', () => {
|
|
46
|
+
const identity_model = buildIdentityModel({
|
|
47
|
+
identifier: 'test_user',
|
|
48
|
+
environment_api_key: 'some_key'
|
|
49
|
+
});
|
|
50
|
+
expect(identity_model.identityUuid).not.toBe(undefined);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('test_build_identity_model_from_dictionary_with_feature_states', () => {
|
|
54
|
+
const identity_dict = {
|
|
55
|
+
id: 1,
|
|
56
|
+
identifier: 'test-identity',
|
|
57
|
+
environment_api_key: 'api-key',
|
|
58
|
+
created_date: '2021-08-22T06:25:23.406995Z',
|
|
59
|
+
identity_features: [
|
|
60
|
+
{
|
|
61
|
+
id: 1,
|
|
62
|
+
feature: {
|
|
63
|
+
id: 1,
|
|
64
|
+
name: 'test_feature',
|
|
65
|
+
type: 'STANDARD'
|
|
66
|
+
},
|
|
67
|
+
enabled: true,
|
|
68
|
+
feature_state_value: 'some-value'
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const identityModel = buildIdentityModel(identity_dict);
|
|
74
|
+
|
|
75
|
+
expect(identityModel).toBeInstanceOf(IdentityModel);
|
|
76
|
+
expect(identityModel.identityFeatures?.length).toBe(1);
|
|
77
|
+
expect(identityModel?.identityFeatures![0]).toBeInstanceOf(FeatureStateModel);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('test_identity_dict_created_using_model_can_convert_back_to_model', () => {
|
|
81
|
+
const identityModel = new IdentityModel('some_key', [], [], '', '');
|
|
82
|
+
|
|
83
|
+
const identityJSON = JSON.parse(JSON.stringify(identityModel));
|
|
84
|
+
expect(buildIdentityModel(identityJSON)).toBeInstanceOf(IdentityModel);
|
|
85
|
+
});
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { FeatureStateModel } from '../../../../flagsmith-engine/features/models';
|
|
2
|
+
import { IdentityModel } from '../../../../flagsmith-engine/identities/models';
|
|
3
|
+
import { TraitModel } from '../../../../flagsmith-engine/identities/traits/models';
|
|
4
|
+
import { buildIdentityModel } from '../../../../flagsmith-engine/identities/util';
|
|
5
|
+
import { feature1, identityInSegment } from '../utils';
|
|
6
|
+
|
|
7
|
+
test('test_composite_key', () => {
|
|
8
|
+
const identity = {
|
|
9
|
+
id: 1,
|
|
10
|
+
identifier: 'test-identity',
|
|
11
|
+
environment_api_key: 'api-key',
|
|
12
|
+
created_date: '2021-08-22T06:25:23.406995Z',
|
|
13
|
+
identity_traits: [{ trait_key: 'trait_key', trait_value: 'trait_value' }]
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const identityModel = buildIdentityModel(identity);
|
|
17
|
+
|
|
18
|
+
expect(identityModel.compositeKey).toBe('api-key_test-identity');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('test_identiy_model_creates_default_identity_uuid', () => {
|
|
22
|
+
const identity = {
|
|
23
|
+
id: 1,
|
|
24
|
+
identifier: 'test-identity',
|
|
25
|
+
environment_api_key: 'api-key',
|
|
26
|
+
created_date: '2021-08-22T06:25:23.406995Z',
|
|
27
|
+
identity_traits: [{ trait_key: 'trait_key', trait_value: 'trait_value' }]
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const identityModel = buildIdentityModel(identity);
|
|
31
|
+
|
|
32
|
+
expect(identityModel.identityUuid).toBeDefined();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('test_generate_composite_key', () => {
|
|
36
|
+
const identity = {
|
|
37
|
+
id: 1,
|
|
38
|
+
identifier: 'test-identity',
|
|
39
|
+
environment_api_key: 'api-key',
|
|
40
|
+
created_date: '2021-08-22T06:25:23.406995Z',
|
|
41
|
+
identity_traits: [{ trait_key: 'trait_key', trait_value: 'trait_value' }]
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const identityModel = buildIdentityModel(identity);
|
|
45
|
+
|
|
46
|
+
expect(IdentityModel.generateCompositeKey('api-key', 'test-identity')).toBe(
|
|
47
|
+
'api-key_test-identity'
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('test_update_traits_remove_traits_with_none_value', () => {
|
|
52
|
+
const ident = identityInSegment();
|
|
53
|
+
|
|
54
|
+
const trait_key = ident.identityTraits[0].traitKey;
|
|
55
|
+
const trait_to_remove = new TraitModel(trait_key, undefined);
|
|
56
|
+
|
|
57
|
+
ident.update_traits([trait_to_remove]);
|
|
58
|
+
|
|
59
|
+
expect(ident.identityTraits.length).toBe(0);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('test_update_identity_traits_updates_trait_value', () => {
|
|
63
|
+
const identity = identityInSegment();
|
|
64
|
+
|
|
65
|
+
const traitKey = identity.identityTraits[0].traitKey;
|
|
66
|
+
const traitValue = 'updated_trait_value';
|
|
67
|
+
const traitToUpdate = new TraitModel(traitKey, traitValue);
|
|
68
|
+
|
|
69
|
+
identity.update_traits([traitToUpdate]);
|
|
70
|
+
|
|
71
|
+
expect(identity.identityTraits.length).toBe(1);
|
|
72
|
+
expect(identity.identityTraits[0]).toBe(traitToUpdate);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test('test_update_traits_adds_new_traits', () => {
|
|
76
|
+
const identity = identityInSegment();
|
|
77
|
+
|
|
78
|
+
const newTrait = new TraitModel('new_key', 'foobar');
|
|
79
|
+
|
|
80
|
+
identity.update_traits([newTrait]);
|
|
81
|
+
|
|
82
|
+
expect(identity.identityTraits.length).toBe(2);
|
|
83
|
+
expect(identity.identityTraits).toContain(newTrait);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test('test_append_feature_state', () => {
|
|
87
|
+
const ident = identityInSegment();
|
|
88
|
+
|
|
89
|
+
const fs1 = new FeatureStateModel(feature1(), false, 1);
|
|
90
|
+
|
|
91
|
+
ident.identityFeatures.push(fs1);
|
|
92
|
+
|
|
93
|
+
expect(ident.identityFeatures).toContain(fs1);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test('test_appending_feature_states_raises_duplicate_feature_state_if_fs_for_the_feature_already_exists', () => {
|
|
97
|
+
const ident = identityInSegment();
|
|
98
|
+
|
|
99
|
+
const fs1 = new FeatureStateModel(feature1(), false, 1);
|
|
100
|
+
const fs2 = new FeatureStateModel(feature1(), true, 1);
|
|
101
|
+
ident.identityFeatures.push(fs1);
|
|
102
|
+
expect(() => {
|
|
103
|
+
ident.identityFeatures.push(fs2);
|
|
104
|
+
}).toThrowError();
|
|
105
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { buildOrganizationModel } from '../../../../flagsmith-engine/organisations/util';
|
|
2
|
+
|
|
3
|
+
test('Test builder', () => {
|
|
4
|
+
const model = buildOrganizationModel({
|
|
5
|
+
persist_trait_data: true,
|
|
6
|
+
name: 'Flagsmith',
|
|
7
|
+
feature_analytics: false,
|
|
8
|
+
stop_serving_flags: false,
|
|
9
|
+
id: 13
|
|
10
|
+
});
|
|
11
|
+
expect(model.unique_slug).toBe('13-Flagsmith');
|
|
12
|
+
});
|