flagsmith-nodejs 6.0.1 → 6.1.0

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.
Files changed (70) hide show
  1. package/.github/workflows/publish.yml +17 -17
  2. package/.github/workflows/pull_request.yaml +33 -33
  3. package/.husky/pre-commit +0 -0
  4. package/.prettierignore +2 -1
  5. package/README.md +2 -1
  6. package/build/cjs/flagsmith-engine/features/util.js +3 -3
  7. package/build/cjs/flagsmith-engine/index.d.ts +1 -1
  8. package/build/cjs/flagsmith-engine/index.js +2 -1
  9. package/build/cjs/flagsmith-engine/segments/models.js +7 -7
  10. package/build/cjs/flagsmith-engine/utils/hashing/index.js +1 -1
  11. package/build/cjs/index.d.ts +4 -4
  12. package/build/cjs/index.js +3 -1
  13. package/build/cjs/sdk/analytics.d.ts +1 -1
  14. package/build/cjs/sdk/index.d.ts +5 -5
  15. package/build/cjs/sdk/index.js +7 -5
  16. package/build/cjs/sdk/models.d.ts +25 -0
  17. package/build/cjs/sdk/models.js +25 -0
  18. package/build/cjs/sdk/types.d.ts +14 -4
  19. package/build/cjs/sdk/utils.d.ts +4 -4
  20. package/build/cjs/sdk/utils.js +2 -2
  21. package/build/esm/flagsmith-engine/features/models.js +1 -1
  22. package/build/esm/flagsmith-engine/features/util.js +3 -3
  23. package/build/esm/flagsmith-engine/index.d.ts +1 -1
  24. package/build/esm/flagsmith-engine/index.js +1 -1
  25. package/build/esm/flagsmith-engine/segments/models.js +7 -7
  26. package/build/esm/flagsmith-engine/utils/hashing/index.js +2 -2
  27. package/build/esm/flagsmith-engine/utils/index.js +1 -1
  28. package/build/esm/index.d.ts +4 -4
  29. package/build/esm/index.js +3 -3
  30. package/build/esm/sdk/analytics.d.ts +1 -1
  31. package/build/esm/sdk/index.d.ts +5 -5
  32. package/build/esm/sdk/index.js +6 -5
  33. package/build/esm/sdk/models.d.ts +25 -0
  34. package/build/esm/sdk/models.js +25 -0
  35. package/build/esm/sdk/types.d.ts +14 -4
  36. package/build/esm/sdk/utils.d.ts +4 -4
  37. package/build/esm/sdk/utils.js +2 -2
  38. package/flagsmith-engine/environments/util.ts +2 -2
  39. package/flagsmith-engine/features/models.ts +1 -1
  40. package/flagsmith-engine/features/util.ts +14 -14
  41. package/flagsmith-engine/identities/models.ts +1 -1
  42. package/flagsmith-engine/index.ts +1 -1
  43. package/flagsmith-engine/segments/evaluators.ts +2 -3
  44. package/flagsmith-engine/segments/models.ts +25 -15
  45. package/flagsmith-engine/utils/hashing/index.ts +3 -3
  46. package/flagsmith-engine/utils/index.ts +4 -2
  47. package/index.ts +19 -22
  48. package/package.json +1 -1
  49. package/sdk/analytics.ts +7 -5
  50. package/sdk/index.ts +38 -21
  51. package/sdk/models.ts +25 -0
  52. package/sdk/offline_handlers.ts +1 -1
  53. package/sdk/types.ts +17 -8
  54. package/sdk/utils.ts +8 -8
  55. package/tests/engine/e2e/engine.test.ts +2 -4
  56. package/tests/engine/unit/engine.test.ts +1 -5
  57. package/tests/engine/unit/features/models.test.ts +2 -2
  58. package/tests/engine/unit/identities/identities_builders.test.ts +1 -1
  59. package/tests/engine/unit/segments/segment_evaluators.test.ts +52 -23
  60. package/tests/engine/unit/segments/segments_model.test.ts +35 -37
  61. package/tests/engine/unit/utils/utils.test.ts +28 -30
  62. package/tests/sdk/analytics.test.ts +25 -26
  63. package/tests/sdk/flagsmith-cache.test.ts +84 -76
  64. package/tests/sdk/flagsmith-environment-flags.test.ts +93 -93
  65. package/tests/sdk/flagsmith-identity-flags.test.ts +146 -149
  66. package/tests/sdk/flagsmith.test.ts +40 -42
  67. package/tests/sdk/offline-handlers.test.ts +32 -32
  68. package/tests/sdk/polling.test.ts +0 -1
  69. package/tests/sdk/utils.ts +26 -18
  70. package/vitest.config.ts +10 -15
@@ -1,213 +1,210 @@
1
1
  import Flagsmith from '../../sdk/index.js';
2
2
  import {
3
- fetch,
4
- environmentJSON,
5
- flagsmith,
6
- identitiesJSON,
7
- identityWithTransientTraitsJSON,
8
- transientIdentityJSON,
9
- badFetch
3
+ fetch,
4
+ environmentJSON,
5
+ flagsmith,
6
+ identitiesJSON,
7
+ identityWithTransientTraitsJSON,
8
+ transientIdentityJSON,
9
+ badFetch
10
10
  } from './utils.js';
11
11
  import { DefaultFlag } from '../../sdk/models.js';
12
12
 
13
13
  vi.mock('../../sdk/polling_manager');
14
14
 
15
15
  test('test_get_identity_flags_calls_api_when_no_local_environment_no_traits', async () => {
16
- const identifier = 'identifier';
16
+ const identifier = 'identifier';
17
17
 
18
- const flg = flagsmith();
18
+ const flg = flagsmith();
19
19
 
20
- const identityFlags = (await flg.getIdentityFlags(identifier)).allFlags();
20
+ const identityFlags = (await flg.getIdentityFlags(identifier)).allFlags();
21
21
 
22
- expect(identityFlags[0].enabled).toBe(true);
23
- expect(identityFlags[0].value).toBe('some-value');
24
- expect(identityFlags[0].featureName).toBe('some_feature');
22
+ expect(identityFlags[0].enabled).toBe(true);
23
+ expect(identityFlags[0].value).toBe('some-value');
24
+ expect(identityFlags[0].featureName).toBe('some_feature');
25
25
  });
26
26
 
27
27
  test('test_get_identity_flags_uses_environment_when_local_environment_no_traits', async () => {
28
- const identifier = 'identifier';
28
+ const identifier = 'identifier';
29
29
 
30
- const flg = flagsmith({
31
- environmentKey: 'ser.key',
32
- enableLocalEvaluation: true,
33
- });
30
+ const flg = flagsmith({
31
+ environmentKey: 'ser.key',
32
+ enableLocalEvaluation: true
33
+ });
34
34
 
35
+ const identityFlags = (await flg.getIdentityFlags(identifier)).allFlags();
35
36
 
36
- const identityFlags = (await flg.getIdentityFlags(identifier)).allFlags();
37
-
38
- expect(identityFlags[0].enabled).toBe(true);
39
- expect(identityFlags[0].value).toBe('some-value');
40
- expect(identityFlags[0].featureName).toBe('some_feature');
37
+ expect(identityFlags[0].enabled).toBe(true);
38
+ expect(identityFlags[0].value).toBe('some-value');
39
+ expect(identityFlags[0].featureName).toBe('some_feature');
41
40
  });
42
41
 
43
42
  test('test_get_identity_flags_calls_api_when_no_local_environment_with_traits', async () => {
44
- const identifier = 'identifier';
45
- const traits = { some_trait: 'some_value' };
46
- const flg = flagsmith();
43
+ const identifier = 'identifier';
44
+ const traits = { some_trait: 'some_value' };
45
+ const flg = flagsmith();
47
46
 
48
- const identityFlags = (await flg.getIdentityFlags(identifier, traits)).allFlags();
47
+ const identityFlags = (await flg.getIdentityFlags(identifier, traits)).allFlags();
49
48
 
50
- expect(identityFlags[0].enabled).toBe(true);
51
- expect(identityFlags[0].value).toBe('some-value');
52
- expect(identityFlags[0].featureName).toBe('some_feature');
49
+ expect(identityFlags[0].enabled).toBe(true);
50
+ expect(identityFlags[0].value).toBe('some-value');
51
+ expect(identityFlags[0].featureName).toBe('some_feature');
53
52
  });
54
53
 
55
54
  test('test_default_flag_is_not_used_when_identity_flags_returned', async () => {
56
- const defaultFlag = new DefaultFlag('some-default-value', true);
55
+ const defaultFlag = new DefaultFlag('some-default-value', true);
57
56
 
58
- const defaultFlagHandler = (featureName: string) => defaultFlag;
57
+ const defaultFlagHandler = (featureName: string) => defaultFlag;
59
58
 
60
- const flg = flagsmith({
61
- environmentKey: 'key',
62
- defaultFlagHandler: defaultFlagHandler
63
- });
59
+ const flg = flagsmith({
60
+ environmentKey: 'key',
61
+ defaultFlagHandler: defaultFlagHandler
62
+ });
64
63
 
65
- const flags = await flg.getIdentityFlags('identifier');
66
- const flag = flags.getFlag('some_feature');
64
+ const flags = await flg.getIdentityFlags('identifier');
65
+ const flag = flags.getFlag('some_feature');
67
66
 
68
- expect(flag.isDefault).toBe(false);
69
- expect(flag.value).not.toBe(defaultFlag.value);
70
- expect(flag.value).toBe('some-value');
67
+ expect(flag.isDefault).toBe(false);
68
+ expect(flag.value).not.toBe(defaultFlag.value);
69
+ expect(flag.value).toBe('some-value');
71
70
  });
72
71
 
73
72
  test('test_default_flag_is_used_when_no_identity_flags_returned', async () => {
74
- fetch.mockResolvedValue(new Response(JSON.stringify({ flags: [], traits: [] })));
73
+ fetch.mockResolvedValue(new Response(JSON.stringify({ flags: [], traits: [] })));
75
74
 
76
- const defaultFlag = new DefaultFlag('some-default-value', true);
77
- const defaultFlagHandler = (featureName: string) => defaultFlag;
75
+ const defaultFlag = new DefaultFlag('some-default-value', true);
76
+ const defaultFlagHandler = (featureName: string) => defaultFlag;
78
77
 
79
- const flg = new Flagsmith({
80
- environmentKey: 'key',
81
- defaultFlagHandler: defaultFlagHandler
82
- });
78
+ const flg = new Flagsmith({
79
+ environmentKey: 'key',
80
+ defaultFlagHandler: defaultFlagHandler
81
+ });
83
82
 
84
- const flags = await flg.getIdentityFlags('identifier');
85
- const flag = flags.getFlag('some_feature');
83
+ const flags = await flg.getIdentityFlags('identifier');
84
+ const flag = flags.getFlag('some_feature');
86
85
 
87
- expect(flag.isDefault).toBe(true);
88
- expect(flag.value).toBe(defaultFlag.value);
89
- expect(flag.enabled).toBe(defaultFlag.enabled);
86
+ expect(flag.isDefault).toBe(true);
87
+ expect(flag.value).toBe(defaultFlag.value);
88
+ expect(flag.enabled).toBe(defaultFlag.enabled);
90
89
  });
91
90
 
92
91
  test('test_default_flag_is_used_when_no_identity_flags_returned_due_to_error', async () => {
93
- fetch.mockResolvedValue(new Response('bad data'))
92
+ fetch.mockResolvedValue(new Response('bad data'));
94
93
 
95
- const defaultFlag = new DefaultFlag('some-default-value', true);
96
- const defaultFlagHandler = (featureName: string) => defaultFlag;
94
+ const defaultFlag = new DefaultFlag('some-default-value', true);
95
+ const defaultFlagHandler = (featureName: string) => defaultFlag;
97
96
 
98
- const flg = new Flagsmith({
99
- environmentKey: 'key',
100
- defaultFlagHandler: defaultFlagHandler
101
- });
97
+ const flg = new Flagsmith({
98
+ environmentKey: 'key',
99
+ defaultFlagHandler: defaultFlagHandler
100
+ });
102
101
 
103
- const flags = await flg.getIdentityFlags('identifier');
104
- const flag = flags.getFlag('some_feature');
102
+ const flags = await flg.getIdentityFlags('identifier');
103
+ const flag = flags.getFlag('some_feature');
105
104
 
106
- expect(flag.isDefault).toBe(true);
107
- expect(flag.value).toBe(defaultFlag.value);
108
- expect(flag.enabled).toBe(defaultFlag.enabled);
105
+ expect(flag.isDefault).toBe(true);
106
+ expect(flag.value).toBe(defaultFlag.value);
107
+ expect(flag.enabled).toBe(defaultFlag.enabled);
109
108
  });
110
109
 
111
110
  test('test_default_flag_is_used_when_no_identity_flags_returned_and_no_custom_default_flag_handler', async () => {
112
- fetch.mockResolvedValue(new Response(JSON.stringify({ flags: [], traits: [] })))
111
+ fetch.mockResolvedValue(new Response(JSON.stringify({ flags: [], traits: [] })));
113
112
 
114
- const flg = flagsmith({
115
- environmentKey: 'key',
116
- });
113
+ const flg = flagsmith({
114
+ environmentKey: 'key'
115
+ });
117
116
 
118
- const flags = await flg.getIdentityFlags('identifier');
119
- const flag = flags.getFlag('some_feature');
117
+ const flags = await flg.getIdentityFlags('identifier');
118
+ const flag = flags.getFlag('some_feature');
120
119
 
121
- expect(flag.isDefault).toBe(true);
122
- expect(flag.value).toBe(undefined);
123
- expect(flag.enabled).toBe(false);
120
+ expect(flag.isDefault).toBe(true);
121
+ expect(flag.value).toBe(undefined);
122
+ expect(flag.enabled).toBe(false);
124
123
  });
125
124
 
126
125
  test('test_get_identity_flags_multivariate_value_with_local_evaluation_enabled', async () => {
127
- fetch.mockResolvedValue(new Response(environmentJSON));
128
- const identifier = 'identifier';
126
+ fetch.mockResolvedValue(new Response(environmentJSON));
127
+ const identifier = 'identifier';
129
128
 
130
- const flg = flagsmith({
131
- environmentKey: 'ser.key',
132
- enableLocalEvaluation: true,
133
- });
129
+ const flg = flagsmith({
130
+ environmentKey: 'ser.key',
131
+ enableLocalEvaluation: true
132
+ });
134
133
 
135
- const identityFlags = (await flg.getIdentityFlags(identifier))
134
+ const identityFlags = await flg.getIdentityFlags(identifier);
136
135
 
137
- expect(identityFlags.getFeatureValue('mv_feature')).toBe('bar');
138
- expect(identityFlags.isFeatureEnabled('mv_feature')).toBe(false);
136
+ expect(identityFlags.getFeatureValue('mv_feature')).toBe('bar');
137
+ expect(identityFlags.isFeatureEnabled('mv_feature')).toBe(false);
139
138
  });
140
139
 
141
-
142
140
  test('test_transient_identity', async () => {
143
- fetch.mockResolvedValue(new Response(transientIdentityJSON));
144
- const identifier = 'transient_identifier';
145
- const traits = { some_trait: 'some_value' };
146
- const traitsInRequest = [{trait_key:Object.keys(traits)[0],trait_value:traits.some_trait}]
147
- const transient = true;
148
- const flg = flagsmith();
149
- const identityFlags = (await flg.getIdentityFlags(identifier, traits, transient)).allFlags();
150
-
151
- expect(fetch).toHaveBeenCalledWith(
152
- `https://edge.api.flagsmith.com/api/v1/identities/`,
153
- expect.objectContaining({
154
- method: 'POST',
155
- headers: { 'Content-Type': 'application/json', 'X-Environment-Key': 'sometestfakekey' },
156
- body: JSON.stringify({identifier, traits: traitsInRequest, transient })
157
- }
158
- ));
159
-
160
- expect(identityFlags[0].enabled).toBe(false);
161
- expect(identityFlags[0].value).toBe('some-transient-identity-value');
162
- expect(identityFlags[0].featureName).toBe('some_feature');
141
+ fetch.mockResolvedValue(new Response(transientIdentityJSON));
142
+ const identifier = 'transient_identifier';
143
+ const traits = { some_trait: 'some_value' };
144
+ const traitsInRequest = [{ trait_key: Object.keys(traits)[0], trait_value: traits.some_trait }];
145
+ const transient = true;
146
+ const flg = flagsmith();
147
+ const identityFlags = (await flg.getIdentityFlags(identifier, traits, transient)).allFlags();
148
+
149
+ expect(fetch).toHaveBeenCalledWith(
150
+ `https://edge.api.flagsmith.com/api/v1/identities/`,
151
+ expect.objectContaining({
152
+ method: 'POST',
153
+ headers: { 'Content-Type': 'application/json', 'X-Environment-Key': 'sometestfakekey' },
154
+ body: JSON.stringify({ identifier, traits: traitsInRequest, transient })
155
+ })
156
+ );
157
+
158
+ expect(identityFlags[0].enabled).toBe(false);
159
+ expect(identityFlags[0].value).toBe('some-transient-identity-value');
160
+ expect(identityFlags[0].featureName).toBe('some_feature');
163
161
  });
164
162
 
165
-
166
163
  test('test_identity_with_transient_traits', async () => {
167
- fetch.mockResolvedValue(new Response(identityWithTransientTraitsJSON));
168
- const identifier = 'transient_trait_identifier';
169
- const traits = {
170
- some_trait: 'some_value',
171
- another_trait: {value: 'another_value', transient: true},
172
- explicitly_non_transient_trait: {value: 'non_transient_value', transient: false}
173
- }
174
- const traitsInRequest = [
175
- {
176
- trait_key:Object.keys(traits)[0],
177
- trait_value:traits.some_trait,
178
- },
179
- {
180
- trait_key:Object.keys(traits)[1],
181
- trait_value:traits.another_trait.value,
182
- transient: true,
183
- },
184
- {
185
- trait_key:Object.keys(traits)[2],
186
- trait_value:traits.explicitly_non_transient_trait.value,
187
- transient: false,
188
- },
189
- ]
190
- const flg = flagsmith();
191
-
192
- const identityFlags = (await flg.getIdentityFlags(identifier, traits)).allFlags();
193
- expect(fetch).toHaveBeenCalledWith(
194
- `https://edge.api.flagsmith.com/api/v1/identities/`,
195
- expect.objectContaining({
196
- method: 'POST',
197
- headers: { 'Content-Type': 'application/json', 'X-Environment-Key': 'sometestfakekey' },
198
- body: JSON.stringify({identifier, traits: traitsInRequest})
199
- })
200
- );
201
- expect(identityFlags[0].enabled).toBe(true);
202
- expect(identityFlags[0].value).toBe('some-identity-with-transient-trait-value');
203
- expect(identityFlags[0].featureName).toBe('some_feature');
164
+ fetch.mockResolvedValue(new Response(identityWithTransientTraitsJSON));
165
+ const identifier = 'transient_trait_identifier';
166
+ const traits = {
167
+ some_trait: 'some_value',
168
+ another_trait: { value: 'another_value', transient: true },
169
+ explicitly_non_transient_trait: { value: 'non_transient_value', transient: false }
170
+ };
171
+ const traitsInRequest = [
172
+ {
173
+ trait_key: Object.keys(traits)[0],
174
+ trait_value: traits.some_trait
175
+ },
176
+ {
177
+ trait_key: Object.keys(traits)[1],
178
+ trait_value: traits.another_trait.value,
179
+ transient: true
180
+ },
181
+ {
182
+ trait_key: Object.keys(traits)[2],
183
+ trait_value: traits.explicitly_non_transient_trait.value,
184
+ transient: false
185
+ }
186
+ ];
187
+ const flg = flagsmith();
188
+
189
+ const identityFlags = (await flg.getIdentityFlags(identifier, traits)).allFlags();
190
+ expect(fetch).toHaveBeenCalledWith(
191
+ `https://edge.api.flagsmith.com/api/v1/identities/`,
192
+ expect.objectContaining({
193
+ method: 'POST',
194
+ headers: { 'Content-Type': 'application/json', 'X-Environment-Key': 'sometestfakekey' },
195
+ body: JSON.stringify({ identifier, traits: traitsInRequest })
196
+ })
197
+ );
198
+ expect(identityFlags[0].enabled).toBe(true);
199
+ expect(identityFlags[0].value).toBe('some-identity-with-transient-trait-value');
200
+ expect(identityFlags[0].featureName).toBe('some_feature');
204
201
  });
205
202
 
206
203
  test('getIdentityFlags fails if API call failed and no default flag handler was provided', async () => {
207
- const flg = flagsmith({
208
- fetch: badFetch,
209
- })
210
- await expect(flg.getIdentityFlags('user'))
211
- .rejects
212
- .toThrow('getIdentityFlags failed and no default flag handler was provided')
213
- })
204
+ const flg = flagsmith({
205
+ fetch: badFetch
206
+ });
207
+ await expect(flg.getIdentityFlags('user')).rejects.toThrow(
208
+ 'getIdentityFlags failed and no default flag handler was provided'
209
+ );
210
+ });
@@ -29,26 +29,26 @@ test('test_flagsmith_local_evaluation_key_required', () => {
29
29
  environmentKey: 'bad.key',
30
30
  enableLocalEvaluation: true
31
31
  });
32
- }).toThrow('Using local evaluation requires a server-side environment key')
32
+ }).toThrow('Using local evaluation requires a server-side environment key');
33
33
  });
34
34
 
35
35
  test('test_update_environment_sets_environment', async () => {
36
36
  const flg = flagsmith({
37
- environmentKey: 'ser.key',
37
+ environmentKey: 'ser.key'
38
38
  });
39
39
  const model = environmentModel(JSON.parse(environmentJSON));
40
40
  expect(await flg.getEnvironment()).toStrictEqual(model);
41
41
  });
42
42
 
43
43
  test('test_set_agent_options', async () => {
44
- const agent = new Agent({})
44
+ const agent = new Agent({});
45
45
 
46
46
  fetch.mockImplementationOnce((url, options) => {
47
47
  //@ts-ignore I give up
48
48
  if (options.dispatcher !== agent) {
49
- throw new Error("Agent has not been set on retry fetch")
49
+ throw new Error('Agent has not been set on retry fetch');
50
50
  }
51
- return Promise.resolve(new Response(environmentJSON))
51
+ return Promise.resolve(new Response(environmentJSON));
52
52
  });
53
53
 
54
54
  const flg = flagsmith({
@@ -69,7 +69,6 @@ test('test_get_identity_segments', async () => {
69
69
  expect(segments2.length).toEqual(0);
70
70
  });
71
71
 
72
-
73
72
  test('test_get_identity_segments_empty_without_local_eval', async () => {
74
73
  const flg = new Flagsmith({
75
74
  environmentKey: 'ser.key',
@@ -82,7 +81,7 @@ test('test_get_identity_segments_empty_without_local_eval', async () => {
82
81
  test('test_update_environment_uses_req_when_inited', async () => {
83
82
  const flg = flagsmith({
84
83
  environmentKey: 'ser.key',
85
- enableLocalEvaluation: true,
84
+ enableLocalEvaluation: true
86
85
  });
87
86
 
88
87
  delay(400);
@@ -100,7 +99,7 @@ test('test_isFeatureEnabled_environment', async () => {
100
99
  const flg = new Flagsmith({
101
100
  environmentKey: 'key',
102
101
  defaultFlagHandler: defaultFlagHandler,
103
- enableAnalytics: true,
102
+ enableAnalytics: true
104
103
  });
105
104
 
106
105
  const flags = await flg.getEnvironmentFlags();
@@ -110,9 +109,9 @@ test('test_isFeatureEnabled_environment', async () => {
110
109
  });
111
110
 
112
111
  test('test_fetch_recovers_after_single_API_error', async () => {
113
- fetch.mockRejectedValueOnce('Error during fetching the API response')
112
+ fetch.mockRejectedValueOnce('Error during fetching the API response');
114
113
  const flg = flagsmith({
115
- environmentKey: 'key',
114
+ environmentKey: 'key'
116
115
  });
117
116
 
118
117
  const flags = await flg.getEnvironmentFlags();
@@ -132,7 +131,7 @@ test.each([
132
131
  enableLocalEvaluation,
133
132
  environmentKey,
134
133
  defaultFlagHandler: () => new DefaultFlag('some-default-value', true),
135
- fetch: badFetch,
134
+ fetch: badFetch
136
135
  });
137
136
  const flags = await flg.getEnvironmentFlags();
138
137
  const flag = flags.getFlag('some_feature');
@@ -144,9 +143,9 @@ test.each([
144
143
 
145
144
  test('default flag handler used when timeout occurs', async () => {
146
145
  fetch.mockImplementation(async (...args) => {
147
- const forever = new Promise(() => {})
148
- await forever
149
- throw new Error('waited forever')
146
+ const forever = new Promise(() => {});
147
+ await forever;
148
+ throw new Error('waited forever');
150
149
  });
151
150
 
152
151
  const defaultFlag = new DefaultFlag('some-default-value', true);
@@ -156,7 +155,7 @@ test('default flag handler used when timeout occurs', async () => {
156
155
  const flg = flagsmith({
157
156
  environmentKey: 'key',
158
157
  defaultFlagHandler: defaultFlagHandler,
159
- requestTimeoutSeconds: 0.0001,
158
+ requestTimeoutSeconds: 0.0001
160
159
  });
161
160
 
162
161
  const flags = await flg.getEnvironmentFlags();
@@ -164,35 +163,32 @@ test('default flag handler used when timeout occurs', async () => {
164
163
  expect(flag.isDefault).toBe(true);
165
164
  expect(flag.enabled).toBe(defaultFlag.enabled);
166
165
  expect(flag.value).toBe(defaultFlag.value);
167
- })
166
+ });
168
167
 
169
168
  test('request timeout uses default if not provided', async () => {
170
-
171
169
  const flg = new Flagsmith({
172
- environmentKey: 'key',
170
+ environmentKey: 'key'
173
171
  });
174
172
 
175
173
  expect(flg.requestTimeoutMs).toBe(10000);
176
- })
174
+ });
177
175
 
178
176
  test('test_throws_when_no_identityFlags_returned_due_to_error', async () => {
179
177
  const flg = flagsmith({
180
178
  environmentKey: 'key',
181
- fetch: badFetch,
179
+ fetch: badFetch
182
180
  });
183
181
 
184
- await expect(async () => await flg.getIdentityFlags('identifier'))
185
- .rejects
186
- .toThrow();
182
+ await expect(async () => await flg.getIdentityFlags('identifier')).rejects.toThrow();
187
183
  });
188
184
 
189
185
  test('test onEnvironmentChange is called when provided', async () => {
190
- const callback = vi.fn()
186
+ const callback = vi.fn();
191
187
 
192
188
  const flg = new Flagsmith({
193
189
  environmentKey: 'ser.key',
194
190
  enableLocalEvaluation: true,
195
- onEnvironmentChange: callback,
191
+ onEnvironmentChange: callback
196
192
  });
197
193
 
198
194
  fetch.mockRejectedValueOnce(new Error('API error'));
@@ -209,7 +205,7 @@ test('test onEnvironmentChange is called after error', async () => {
209
205
  environmentKey: 'ser.key',
210
206
  enableLocalEvaluation: true,
211
207
  onEnvironmentChange: callback,
212
- fetch: badFetch,
208
+ fetch: badFetch
213
209
  });
214
210
  await flg.updateEnvironment();
215
211
  expect(callback).toHaveBeenCalled();
@@ -217,15 +213,17 @@ test('test onEnvironmentChange is called after error', async () => {
217
213
 
218
214
  test('getIdentityFlags throws error if identifier is empty string', async () => {
219
215
  const flg = flagsmith({
220
- environmentKey: 'key',
216
+ environmentKey: 'key'
221
217
  });
222
218
 
223
- await expect(flg.getIdentityFlags('')).rejects.toThrow('`identifier` argument is missing or invalid.');
224
- })
219
+ await expect(flg.getIdentityFlags('')).rejects.toThrow(
220
+ '`identifier` argument is missing or invalid.'
221
+ );
222
+ });
225
223
 
226
224
  test('getIdentitySegments throws error if identifier is empty string', async () => {
227
225
  const flg = flagsmith({
228
- environmentKey: 'key',
226
+ environmentKey: 'key'
229
227
  });
230
228
 
231
229
  await expect(flg.getIdentitySegments('')).rejects.toThrow(
@@ -254,15 +252,13 @@ test('offline_mode', async () => {
254
252
  expect(flag.enabled).toBe(true);
255
253
  expect(flag.value).toBe('offline-value');
256
254
 
257
-
258
- const identityFlags: Flags = await flg.getIdentityFlags("identity");
255
+ const identityFlags: Flags = await flg.getIdentityFlags('identity');
259
256
  flag = identityFlags.getFlag('some_feature');
260
257
  expect(flag.isDefault).toBe(false);
261
258
  expect(flag.enabled).toBe(true);
262
259
  expect(flag.value).toBe('offline-value');
263
260
  });
264
261
 
265
-
266
262
  test('test_flagsmith_uses_offline_handler_if_set_and_no_api_response', async () => {
267
263
  // Given
268
264
  const environment: EnvironmentModel = environmentModel(JSON.parse(offlineEnvironmentJSON));
@@ -281,14 +277,13 @@ test('test_flagsmith_uses_offline_handler_if_set_and_no_api_response', async ()
281
277
  vi.spyOn(flg, 'getEnvironmentFlags');
282
278
  vi.spyOn(flg, 'getIdentityFlags');
283
279
 
284
-
285
280
  flg.environmentFlagsUrl = 'http://some.flagsmith.com/api/v1/environment-flags';
286
281
  flg.identitiesUrl = 'http://some.flagsmith.com/api/v1/identities';
287
282
 
288
283
  // Mock a 500 Internal Server Error response
289
284
  const errorResponse = new Response(null, {
290
285
  status: 500,
291
- statusText: 'Internal Server Error',
286
+ statusText: 'Internal Server Error'
292
287
  });
293
288
 
294
289
  fetch.mockResolvedValue(errorResponse);
@@ -318,25 +313,28 @@ test('cannot use offline mode without offline handler', () => {
318
313
 
319
314
  test('cannot use both default handler and offline handler', () => {
320
315
  // When and Then
321
- expect(() => flagsmith({
322
- offlineHandler: new BaseOfflineHandler(),
323
- defaultFlagHandler: () => new DefaultFlag('foo', true)
324
- })).toThrowError('ValueError: Cannot use both defaultFlagHandler and offlineHandler.');
316
+ expect(() =>
317
+ flagsmith({
318
+ offlineHandler: new BaseOfflineHandler(),
319
+ defaultFlagHandler: () => new DefaultFlag('foo', true)
320
+ })
321
+ ).toThrowError('ValueError: Cannot use both defaultFlagHandler and offlineHandler.');
325
322
  });
326
323
 
327
324
  test('cannot create Flagsmith client in remote evaluation without API key', () => {
328
325
  // When and Then
329
- expect(() => new Flagsmith({ environmentKey: '' })).toThrowError('ValueError: environmentKey is required.');
326
+ expect(() => new Flagsmith({ environmentKey: '' })).toThrowError(
327
+ 'ValueError: environmentKey is required.'
328
+ );
330
329
  });
331
330
 
332
-
333
331
  test('test_localEvaluation_true__identity_overrides_evaluated', async () => {
334
332
  const flg = flagsmith({
335
333
  environmentKey: 'ser.key',
336
334
  enableLocalEvaluation: true
337
335
  });
338
336
 
339
- await flg.updateEnvironment()
337
+ await flg.updateEnvironment();
340
338
  const flags = await flg.getIdentityFlags('overridden-id');
341
339
  expect(flags.getFeatureValue('some_feature')).toEqual('some-overridden-value');
342
340
  });