flagsmith-nodejs 2.0.0-beta.6 → 2.0.0-beta.7
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 +37 -29
- package/README.md +7 -0
- package/build/flagsmith-engine/features/models.d.ts +0 -1
- package/build/flagsmith-engine/features/models.js +0 -3
- package/build/flagsmith-engine/identities/models.d.ts +1 -1
- package/build/flagsmith-engine/identities/models.js +1 -1
- package/build/flagsmith-engine/index.js +1 -1
- package/build/flagsmith-engine/organisations/models.d.ts +1 -1
- package/build/flagsmith-engine/organisations/models.js +1 -1
- package/build/flagsmith-engine/segments/models.js +0 -3
- package/build/flagsmith-engine/utils/collections.d.ts +0 -1
- package/build/flagsmith-engine/utils/collections.js +0 -71
- package/build/flagsmith-engine/utils/hashing/index.js +5 -2
- package/build/sdk/analytics.js +0 -1
- package/build/sdk/index.d.ts +5 -0
- package/build/sdk/index.js +152 -54
- package/build/sdk/polling_manager.js +0 -1
- package/build/sdk/types.d.ts +7 -0
- package/build/sdk/types.js +2 -0
- package/example/server/api/index.js +1 -1
- package/flagsmith-engine/features/models.ts +0 -4
- package/flagsmith-engine/identities/models.ts +1 -1
- package/flagsmith-engine/index.ts +1 -1
- package/flagsmith-engine/organisations/models.ts +1 -1
- package/flagsmith-engine/segments/models.ts +0 -2
- package/flagsmith-engine/utils/collections.ts +1 -12
- package/flagsmith-engine/utils/hashing/index.ts +5 -2
- package/package.json +2 -2
- package/sdk/analytics.ts +0 -2
- package/sdk/index.ts +83 -26
- package/sdk/polling_manager.ts +0 -1
- package/sdk/types.ts +8 -0
- package/tests/engine/unit/{egine.test.ts → engine.test.ts} +20 -0
- package/tests/engine/unit/features/models.test.ts +7 -3
- package/tests/engine/unit/identities/identities_builders.test.ts +13 -0
- package/tests/engine/unit/identities/identities_models.test.ts +3 -14
- package/tests/engine/unit/organization/models.test.ts +1 -1
- package/tests/engine/unit/segments/segments_model.test.ts +2 -1
- package/tests/engine/unit/utils.ts +1 -1
- package/tests/sdk/analytics.test.ts +11 -0
- package/tests/sdk/flagsmith-cache.test.ts +150 -0
- package/tests/sdk/flagsmith-environment-flags.test.ts +197 -0
- package/tests/sdk/flagsmith-identity-flags.test.ts +140 -0
- package/tests/sdk/flagsmith.test.ts +100 -85
- package/tests/sdk/polling.test.ts +25 -0
- package/tests/sdk/utils.ts +21 -2
- package/tsconfig.json +1 -1
- package/tests/engine/engine-tests/engine-test-data/data/environment_n9fbf9h3v4fFgH3U3ngWhb.json +0 -12393
- package/tests/engine/engine-tests/engine-test-data/readme.md +0 -30
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import fetch, { Headers } from 'node-fetch';
|
|
2
|
+
import { environmentJSON, environmentModel, flagsJSON, flagsmith, identitiesJSON, TestCache } from './utils';
|
|
3
|
+
|
|
4
|
+
jest.mock('node-fetch');
|
|
5
|
+
jest.mock('../../sdk/polling_manager');
|
|
6
|
+
|
|
7
|
+
const { Response } = jest.requireActual('node-fetch');
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
jest.clearAllMocks();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test('test_wrong_cache_interface_throws_an_error', async () => {
|
|
15
|
+
const cache = {
|
|
16
|
+
set: () => { },
|
|
17
|
+
get: () => { },
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
expect(() => { const flg = flagsmith({ cache }); }).toThrow();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('test_empty_cache_not_read_but_populated', async () => {
|
|
24
|
+
// @ts-ignore
|
|
25
|
+
fetch.mockReturnValue(Promise.resolve(new Response(flagsJSON())));
|
|
26
|
+
|
|
27
|
+
const cache = new TestCache();
|
|
28
|
+
const set = jest.spyOn(cache, 'set');
|
|
29
|
+
|
|
30
|
+
const flg = flagsmith({ cache });
|
|
31
|
+
const allFlags = await (await flg.getEnvironmentFlags()).allFlags();
|
|
32
|
+
|
|
33
|
+
expect(set).toBeCalled();
|
|
34
|
+
expect(await cache.has('flags')).toBe(true);
|
|
35
|
+
|
|
36
|
+
expect(fetch).toBeCalledTimes(1);
|
|
37
|
+
expect(allFlags[0].enabled).toBe(true);
|
|
38
|
+
expect(allFlags[0].value).toBe('some-value');
|
|
39
|
+
expect(allFlags[0].featureName).toBe('some_feature');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('test_api_not_called_when_cache_present', async () => {
|
|
43
|
+
// @ts-ignore
|
|
44
|
+
fetch.mockReturnValue(Promise.resolve(new Response(flagsJSON())));
|
|
45
|
+
|
|
46
|
+
const cache = new TestCache();
|
|
47
|
+
const set = jest.spyOn(cache, 'set');
|
|
48
|
+
|
|
49
|
+
const flg = flagsmith({ cache });
|
|
50
|
+
await (await flg.getEnvironmentFlags()).allFlags();
|
|
51
|
+
const allFlags = await (await flg.getEnvironmentFlags()).allFlags();
|
|
52
|
+
|
|
53
|
+
expect(set).toBeCalled();
|
|
54
|
+
expect(await cache.has('flags')).toBe(true);
|
|
55
|
+
|
|
56
|
+
expect(fetch).toBeCalledTimes(1);
|
|
57
|
+
expect(allFlags[0].enabled).toBe(true);
|
|
58
|
+
expect(allFlags[0].value).toBe('some-value');
|
|
59
|
+
expect(allFlags[0].featureName).toBe('some_feature');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('test_api_called_twice_when_no_cache', async () => {
|
|
63
|
+
// @ts-ignore
|
|
64
|
+
fetch.mockReturnValue(Promise.resolve(new Response(flagsJSON())));
|
|
65
|
+
|
|
66
|
+
const flg = flagsmith();
|
|
67
|
+
await (await flg.getEnvironmentFlags()).allFlags();
|
|
68
|
+
// @ts-ignore
|
|
69
|
+
fetch.mockReturnValue(Promise.resolve(new Response(flagsJSON())));
|
|
70
|
+
const allFlags = await (await flg.getEnvironmentFlags()).allFlags();
|
|
71
|
+
|
|
72
|
+
expect(fetch).toBeCalledTimes(2);
|
|
73
|
+
expect(allFlags[0].enabled).toBe(true);
|
|
74
|
+
expect(allFlags[0].value).toBe('some-value');
|
|
75
|
+
expect(allFlags[0].featureName).toBe('some_feature');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('test_get_environment_flags_uses_local_environment_when_available', async () => {
|
|
79
|
+
// @ts-ignore
|
|
80
|
+
fetch.mockReturnValue(Promise.resolve(new Response(flagsJSON())));
|
|
81
|
+
|
|
82
|
+
const cache = new TestCache();
|
|
83
|
+
const set = jest.spyOn(cache, 'set');
|
|
84
|
+
|
|
85
|
+
const flg = flagsmith({ cache });
|
|
86
|
+
const model = environmentModel(JSON.parse(environmentJSON()));
|
|
87
|
+
flg.environment = model;
|
|
88
|
+
|
|
89
|
+
const allFlags = await (await flg.getEnvironmentFlags()).allFlags();
|
|
90
|
+
|
|
91
|
+
expect(set).toBeCalled();
|
|
92
|
+
expect(fetch).toBeCalledTimes(0);
|
|
93
|
+
expect(allFlags[0].enabled).toBe(model.featureStates[0].enabled);
|
|
94
|
+
expect(allFlags[0].value).toBe(model.featureStates[0].getValue());
|
|
95
|
+
expect(allFlags[0].featureName).toBe(model.featureStates[0].feature.name);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test('test_cache_used_for_identity_flags', async () => {
|
|
99
|
+
// @ts-ignore
|
|
100
|
+
fetch.mockReturnValue(Promise.resolve(new Response(identitiesJSON())));
|
|
101
|
+
|
|
102
|
+
const cache = new TestCache();
|
|
103
|
+
const set = jest.spyOn(cache, 'set');
|
|
104
|
+
|
|
105
|
+
const identifier = 'identifier';
|
|
106
|
+
const traits = { some_trait: 'some_value' };
|
|
107
|
+
const flg = flagsmith({ cache });
|
|
108
|
+
|
|
109
|
+
(await flg.getIdentityFlags(identifier, traits)).allFlags();
|
|
110
|
+
const identityFlags = (await flg.getIdentityFlags(identifier, traits)).allFlags();
|
|
111
|
+
|
|
112
|
+
expect(set).toBeCalled();
|
|
113
|
+
expect(await cache.has('flags-identifier')).toBe(true);
|
|
114
|
+
|
|
115
|
+
expect(fetch).toBeCalledTimes(1);
|
|
116
|
+
|
|
117
|
+
expect(identityFlags[0].enabled).toBe(true);
|
|
118
|
+
expect(identityFlags[0].value).toBe('some-value');
|
|
119
|
+
expect(identityFlags[0].featureName).toBe('some_feature');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test('test_cache_used_for_identity_flags_local_evaluation', async () => {
|
|
123
|
+
// @ts-ignore
|
|
124
|
+
fetch.mockReturnValue(Promise.resolve(new Response(environmentJSON())));
|
|
125
|
+
|
|
126
|
+
const cache = new TestCache();
|
|
127
|
+
const set = jest.spyOn(cache, 'set');
|
|
128
|
+
|
|
129
|
+
const identifier = 'identifier';
|
|
130
|
+
const traits = { some_trait: 'some_value' };
|
|
131
|
+
const flg = flagsmith({
|
|
132
|
+
cache,
|
|
133
|
+
environmentKey: 'ser.key',
|
|
134
|
+
enableLocalEvaluation: true,
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
(await flg.getIdentityFlags(identifier, traits)).allFlags();
|
|
138
|
+
const identityFlags = (await flg.getIdentityFlags(identifier, traits)).allFlags();
|
|
139
|
+
|
|
140
|
+
expect(set).toBeCalled();
|
|
141
|
+
expect(await cache.has('flags-identifier')).toBe(true);
|
|
142
|
+
|
|
143
|
+
expect(fetch).toBeCalledTimes(1);
|
|
144
|
+
|
|
145
|
+
expect(identityFlags[0].enabled).toBe(true);
|
|
146
|
+
expect(identityFlags[0].value).toBe('some-value');
|
|
147
|
+
expect(identityFlags[0].featureName).toBe('some_feature');
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test('test_cache_used_for_all_flags', async () => { });
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import Flagsmith from '../../sdk';
|
|
2
|
+
import fetch from 'node-fetch';
|
|
3
|
+
import { environmentJSON, environmentModel, flagsJSON, flagsmith, identitiesJSON } from './utils';
|
|
4
|
+
import { DefaultFlag } from '../../sdk/models';
|
|
5
|
+
|
|
6
|
+
jest.mock('node-fetch');
|
|
7
|
+
jest.mock('../../sdk/polling_manager');
|
|
8
|
+
const { Response } = jest.requireActual('node-fetch');
|
|
9
|
+
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
// @ts-ignore
|
|
12
|
+
jest.clearAllMocks();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('test_get_environment_flags_calls_api_when_no_local_environment', async () => {
|
|
16
|
+
// @ts-ignore
|
|
17
|
+
fetch.mockReturnValue(Promise.resolve(new Response(flagsJSON())));
|
|
18
|
+
|
|
19
|
+
const flg = flagsmith();
|
|
20
|
+
const allFlags = await (await flg.getEnvironmentFlags()).allFlags();
|
|
21
|
+
|
|
22
|
+
expect(fetch).toBeCalledTimes(1);
|
|
23
|
+
expect(allFlags[0].enabled).toBe(true);
|
|
24
|
+
expect(allFlags[0].value).toBe('some-value');
|
|
25
|
+
expect(allFlags[0].featureName).toBe('some_feature');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('test_get_environment_flags_uses_local_environment_when_available', async () => {
|
|
29
|
+
// @ts-ignore
|
|
30
|
+
fetch.mockReturnValue(Promise.resolve(new Response(flagsJSON())));
|
|
31
|
+
|
|
32
|
+
const flg = flagsmith();
|
|
33
|
+
const model = environmentModel(JSON.parse(environmentJSON()));
|
|
34
|
+
flg.environment = model;
|
|
35
|
+
|
|
36
|
+
const allFlags = await (await flg.getEnvironmentFlags()).allFlags();
|
|
37
|
+
expect(fetch).toBeCalledTimes(0);
|
|
38
|
+
expect(allFlags[0].enabled).toBe(model.featureStates[0].enabled);
|
|
39
|
+
expect(allFlags[0].value).toBe(model.featureStates[0].getValue());
|
|
40
|
+
expect(allFlags[0].featureName).toBe(model.featureStates[0].feature.name);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('test_default_flag_is_used_when_no_environment_flags_returned', async () => {
|
|
44
|
+
// @ts-ignore
|
|
45
|
+
fetch.mockReturnValue(Promise.resolve(new Response(JSON.stringify([]))));
|
|
46
|
+
|
|
47
|
+
const defaultFlag = new DefaultFlag('some-default-value', true);
|
|
48
|
+
|
|
49
|
+
const defaultFlagHandler = (featureName: string) => defaultFlag;
|
|
50
|
+
|
|
51
|
+
const flg = new Flagsmith({
|
|
52
|
+
environmentKey: 'key',
|
|
53
|
+
defaultFlagHandler: defaultFlagHandler,
|
|
54
|
+
customHeaders: {
|
|
55
|
+
'X-Test-Header': '1',
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const flags = await flg.getEnvironmentFlags();
|
|
60
|
+
const flag = flags.getFlag('some_feature');
|
|
61
|
+
expect(flag.isDefault).toBe(true);
|
|
62
|
+
expect(flag.enabled).toBe(defaultFlag.enabled);
|
|
63
|
+
expect(flag.value).toBe(defaultFlag.value);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test('test_analytics_processor_tracks_flags', async () => {
|
|
67
|
+
// @ts-ignore
|
|
68
|
+
fetch.mockReturnValue(Promise.resolve(new Response(flagsJSON())));
|
|
69
|
+
|
|
70
|
+
const defaultFlag = new DefaultFlag('some-default-value', true);
|
|
71
|
+
|
|
72
|
+
const defaultFlagHandler = (featureName: string) => defaultFlag;
|
|
73
|
+
|
|
74
|
+
const flg = new Flagsmith({
|
|
75
|
+
environmentKey: 'key',
|
|
76
|
+
defaultFlagHandler: defaultFlagHandler,
|
|
77
|
+
enableAnalytics: true,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const flags = await flg.getEnvironmentFlags();
|
|
81
|
+
const flag = flags.getFlag('some_feature');
|
|
82
|
+
|
|
83
|
+
expect(flag.isDefault).toBe(false);
|
|
84
|
+
expect(flag.enabled).toBe(true);
|
|
85
|
+
expect(flag.value).toBe('some-value');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('test_getFeatureValue', async () => {
|
|
89
|
+
// @ts-ignore
|
|
90
|
+
fetch.mockReturnValue(Promise.resolve(new Response(flagsJSON())));
|
|
91
|
+
|
|
92
|
+
const defaultFlag = new DefaultFlag('some-default-value', true);
|
|
93
|
+
|
|
94
|
+
const defaultFlagHandler = (featureName: string) => defaultFlag;
|
|
95
|
+
|
|
96
|
+
const flg = new Flagsmith({
|
|
97
|
+
environmentKey: 'key',
|
|
98
|
+
defaultFlagHandler: defaultFlagHandler,
|
|
99
|
+
enableAnalytics: true,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const flags = await flg.getEnvironmentFlags();
|
|
103
|
+
const featureValue = flags.getFeatureValue('some_feature');
|
|
104
|
+
|
|
105
|
+
expect(featureValue).toBe('some-value');
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test('test_throws_when_no_default_flag_handler_after_multiple_API_errors', async () => {
|
|
109
|
+
fetch
|
|
110
|
+
// @ts-ignore
|
|
111
|
+
.mockRejectedValue(new Error('Error during fetching the API response'));
|
|
112
|
+
|
|
113
|
+
const flg = new Flagsmith({
|
|
114
|
+
environmentKey: 'key',
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
await expect(async () => {
|
|
118
|
+
const flags = await flg.getEnvironmentFlags();
|
|
119
|
+
const flag = flags.getFlag('some_feature');
|
|
120
|
+
}).rejects.toThrow('Error during fetching the API response');
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test('test_non_200_response_raises_flagsmith_api_error', async () => {
|
|
124
|
+
const errorResponse403 = new Response('403 Forbidden', {
|
|
125
|
+
status: 403
|
|
126
|
+
});
|
|
127
|
+
// @ts-ignore
|
|
128
|
+
fetch.mockReturnValue(Promise.resolve(errorResponse403));
|
|
129
|
+
|
|
130
|
+
const flg = new Flagsmith({
|
|
131
|
+
environmentKey: 'some'
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
await expect(flg.getEnvironmentFlags()).rejects.toThrow();
|
|
135
|
+
});
|
|
136
|
+
test('test_default_flag_is_not_used_when_environment_flags_returned', async () => {
|
|
137
|
+
// @ts-ignore
|
|
138
|
+
fetch.mockReturnValue(Promise.resolve(new Response(flagsJSON())));
|
|
139
|
+
|
|
140
|
+
const defaultFlag = new DefaultFlag('some-default-value', true);
|
|
141
|
+
|
|
142
|
+
const defaultFlagHandler = (featureName: string) => defaultFlag;
|
|
143
|
+
|
|
144
|
+
const flg = new Flagsmith({
|
|
145
|
+
environmentKey: 'key',
|
|
146
|
+
defaultFlagHandler: defaultFlagHandler
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const flags = await flg.getEnvironmentFlags();
|
|
150
|
+
const flag = flags.getFlag('some_feature');
|
|
151
|
+
|
|
152
|
+
expect(flag.isDefault).toBe(false);
|
|
153
|
+
expect(flag.value).not.toBe(defaultFlag.value);
|
|
154
|
+
expect(flag.value).toBe('some-value');
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test('test_default_flag_is_used_when_bad_api_response_happens', async () => {
|
|
158
|
+
// @ts-ignore
|
|
159
|
+
fetch.mockReturnValue(Promise.resolve(new Response('bad-data')));
|
|
160
|
+
|
|
161
|
+
const defaultFlag = new DefaultFlag('some-default-value', true);
|
|
162
|
+
|
|
163
|
+
const defaultFlagHandler = (featureName: string) => defaultFlag;
|
|
164
|
+
|
|
165
|
+
const flg = new Flagsmith({
|
|
166
|
+
environmentKey: 'key',
|
|
167
|
+
defaultFlagHandler: defaultFlagHandler
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
const flags = await flg.getEnvironmentFlags();
|
|
171
|
+
const flag = flags.getFlag('some_feature');
|
|
172
|
+
|
|
173
|
+
expect(flag.isDefault).toBe(true);
|
|
174
|
+
expect(flag.value).toBe(defaultFlag.value);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
test('test_local_evaluation', async () => {
|
|
178
|
+
// @ts-ignore
|
|
179
|
+
fetch.mockReturnValue(Promise.resolve(new Response(environmentJSON())));
|
|
180
|
+
|
|
181
|
+
const defaultFlag = new DefaultFlag('some-default-value', true);
|
|
182
|
+
|
|
183
|
+
const defaultFlagHandler = (featureName: string) => defaultFlag;
|
|
184
|
+
|
|
185
|
+
const flg = new Flagsmith({
|
|
186
|
+
environmentKey: 'ser.key',
|
|
187
|
+
enableLocalEvaluation: true,
|
|
188
|
+
defaultFlagHandler: defaultFlagHandler
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
const flags = await flg.getEnvironmentFlags();
|
|
192
|
+
const flag = flags.getFlag('some_feature');
|
|
193
|
+
|
|
194
|
+
expect(flag.isDefault).toBe(false);
|
|
195
|
+
expect(flag.value).not.toBe(defaultFlag.value);
|
|
196
|
+
expect(flag.value).toBe('some-value');
|
|
197
|
+
});
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import Flagsmith from '../../sdk';
|
|
2
|
+
import fetch from 'node-fetch';
|
|
3
|
+
import { environmentJSON, flagsmith, identitiesJSON } from './utils';
|
|
4
|
+
import { DefaultFlag } from '../../sdk/models';
|
|
5
|
+
|
|
6
|
+
jest.mock('node-fetch');
|
|
7
|
+
jest.mock('../../sdk/polling_manager');
|
|
8
|
+
const { Response } = jest.requireActual('node-fetch');
|
|
9
|
+
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
// @ts-ignore
|
|
12
|
+
jest.clearAllMocks();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
test('test_get_identity_flags_calls_api_when_no_local_environment_no_traits', async () => {
|
|
17
|
+
// @ts-ignore
|
|
18
|
+
fetch.mockReturnValue(Promise.resolve(new Response(identitiesJSON())));
|
|
19
|
+
const identifier = 'identifier';
|
|
20
|
+
|
|
21
|
+
const flg = flagsmith();
|
|
22
|
+
|
|
23
|
+
const identityFlags = (await flg.getIdentityFlags(identifier)).allFlags();
|
|
24
|
+
|
|
25
|
+
expect(identityFlags[0].enabled).toBe(true);
|
|
26
|
+
expect(identityFlags[0].value).toBe('some-value');
|
|
27
|
+
expect(identityFlags[0].featureName).toBe('some_feature');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('test_get_identity_flags_calls_api_when_local_environment_no_traits', async () => {
|
|
31
|
+
// @ts-ignore
|
|
32
|
+
fetch.mockReturnValue(Promise.resolve(new Response(environmentJSON())));
|
|
33
|
+
const identifier = 'identifier';
|
|
34
|
+
|
|
35
|
+
const flg = flagsmith({
|
|
36
|
+
environmentKey: 'ser.key',
|
|
37
|
+
enableLocalEvaluation: true,
|
|
38
|
+
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
const identityFlags = (await flg.getIdentityFlags(identifier)).allFlags();
|
|
43
|
+
|
|
44
|
+
expect(identityFlags[0].enabled).toBe(true);
|
|
45
|
+
expect(identityFlags[0].value).toBe('some-value');
|
|
46
|
+
expect(identityFlags[0].featureName).toBe('some_feature');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('test_get_identity_flags_calls_api_when_no_local_environment_with_traits', async () => {
|
|
50
|
+
// @ts-ignore
|
|
51
|
+
fetch.mockReturnValue(Promise.resolve(new Response(identitiesJSON())));
|
|
52
|
+
const identifier = 'identifier';
|
|
53
|
+
const traits = { some_trait: 'some_value' };
|
|
54
|
+
const flg = flagsmith();
|
|
55
|
+
|
|
56
|
+
const identityFlags = (await flg.getIdentityFlags(identifier, traits)).allFlags();
|
|
57
|
+
|
|
58
|
+
expect(identityFlags[0].enabled).toBe(true);
|
|
59
|
+
expect(identityFlags[0].value).toBe('some-value');
|
|
60
|
+
expect(identityFlags[0].featureName).toBe('some_feature');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test('test_default_flag_is_not_used_when_identity_flags_returned', async () => {
|
|
64
|
+
// @ts-ignore
|
|
65
|
+
fetch.mockReturnValue(Promise.resolve(new Response(identitiesJSON())));
|
|
66
|
+
|
|
67
|
+
const defaultFlag = new DefaultFlag('some-default-value', true);
|
|
68
|
+
|
|
69
|
+
const defaultFlagHandler = (featureName: string) => defaultFlag;
|
|
70
|
+
|
|
71
|
+
const flg = new Flagsmith({
|
|
72
|
+
environmentKey: 'key',
|
|
73
|
+
defaultFlagHandler: defaultFlagHandler
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const flags = await flg.getIdentityFlags('identifier');
|
|
77
|
+
const flag = flags.getFlag('some_feature');
|
|
78
|
+
|
|
79
|
+
expect(flag.isDefault).toBe(false);
|
|
80
|
+
expect(flag.value).not.toBe(defaultFlag.value);
|
|
81
|
+
expect(flag.value).toBe('some-value');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('test_default_flag_is_used_when_no_identity_flags_returned', async () => {
|
|
85
|
+
// @ts-ignore
|
|
86
|
+
fetch.mockReturnValue(Promise.resolve(new Response(JSON.stringify({ flags: [], traits: [] }))));
|
|
87
|
+
|
|
88
|
+
const defaultFlag = new DefaultFlag('some-default-value', true);
|
|
89
|
+
const defaultFlagHandler = (featureName: string) => defaultFlag;
|
|
90
|
+
|
|
91
|
+
const flg = new Flagsmith({
|
|
92
|
+
environmentKey: 'key',
|
|
93
|
+
defaultFlagHandler: defaultFlagHandler
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const flags = await flg.getIdentityFlags('identifier');
|
|
97
|
+
const flag = flags.getFlag('some_feature');
|
|
98
|
+
|
|
99
|
+
expect(flag.isDefault).toBe(true);
|
|
100
|
+
expect(flag.value).toBe(defaultFlag.value);
|
|
101
|
+
expect(flag.enabled).toBe(defaultFlag.enabled);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('test_default_flag_is_used_when_no_identity_flags_returned_due_to_error', async () => {
|
|
105
|
+
// @ts-ignore
|
|
106
|
+
fetch.mockReturnValue(Promise.resolve(new Response('bad data')));
|
|
107
|
+
|
|
108
|
+
const defaultFlag = new DefaultFlag('some-default-value', true);
|
|
109
|
+
const defaultFlagHandler = (featureName: string) => defaultFlag;
|
|
110
|
+
|
|
111
|
+
const flg = new Flagsmith({
|
|
112
|
+
environmentKey: 'key',
|
|
113
|
+
defaultFlagHandler: defaultFlagHandler
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const flags = await flg.getIdentityFlags('identifier');
|
|
117
|
+
const flag = flags.getFlag('some_feature');
|
|
118
|
+
|
|
119
|
+
expect(flag.isDefault).toBe(true);
|
|
120
|
+
expect(flag.value).toBe(defaultFlag.value);
|
|
121
|
+
expect(flag.enabled).toBe(defaultFlag.enabled);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('test_default_flag_is_used_when_no_identity_flags_returned_and_no_custom_default_flag_handler', async () => {
|
|
125
|
+
// @ts-ignore
|
|
126
|
+
fetch.mockReturnValue(Promise.resolve(new Response(JSON.stringify({ flags: [], traits: [] }))));
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
const flg = new Flagsmith({
|
|
130
|
+
environmentKey: 'key',
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const flags = await flg.getIdentityFlags('identifier');
|
|
134
|
+
const flag = flags.getFlag('some_feature');
|
|
135
|
+
|
|
136
|
+
expect(flag.isDefault).toBe(true);
|
|
137
|
+
expect(flag.value).toBe(undefined);
|
|
138
|
+
expect(flag.enabled).toBe(false);
|
|
139
|
+
});
|
|
140
|
+
|