Skip to content

Commit ad00ade

Browse files
[FME-10573] update js commons to 2.7.9-rc.2
1 parent 80b9ae3 commit ad00ade

File tree

5 files changed

+283
-12
lines changed

5 files changed

+283
-12
lines changed

package-lock.json

Lines changed: 9 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@splitsoftware/splitio-browserjs",
3-
"version": "1.5.0",
3+
"version": "1.5.1-rc.0",
44
"description": "Split SDK for JavaScript on Browser",
55
"main": "cjs/index.js",
66
"module": "esm/index.js",
@@ -59,7 +59,7 @@
5959
"bugs": "https://github.com/splitio/javascript-browser-client/issues",
6060
"homepage": "https://github.com/splitio/javascript-browser-client#readme",
6161
"dependencies": {
62-
"@splitsoftware/splitio-commons": "2.7.0",
62+
"@splitsoftware/splitio-commons": "2.7.9-rc.2",
6363
"tslib": "^2.3.1",
6464
"unfetch": "^4.2.0"
6565
},
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
import sinon from 'sinon';
2+
import { SplitFactory } from '../../';
3+
import { base } from '@splitsoftware/splitio-commons/src/utils/settingsValidation';
4+
5+
const listener = {
6+
logImpression: sinon.stub()
7+
};
8+
9+
const baseConfig = {
10+
core: {
11+
authorizationKey: '<fake-token>',
12+
key: 'facundo@split.io'
13+
},
14+
sync: {
15+
impressionsMode: 'DEBUG'
16+
},
17+
streamingEnabled: false
18+
};
19+
20+
export default async function (fetchMock, assert) {
21+
22+
assert.test('FallbackTreatment / Split factory with no fallbackTreatment defined', async t => {
23+
24+
const splitio = SplitFactory(baseConfig);
25+
const client = splitio.client();
26+
27+
await client.whenReady();
28+
29+
t.equal(client.getTreatment('non_existent_flag'), 'control', 'The evaluation will return `control` if the flag does not exist and no fallbackTreatment is defined');
30+
t.equal(client.getTreatment('non_existent_flag_2'), 'control', 'The evaluation will return `control` if the flag does not exist and no fallbackTreatment is defined');
31+
32+
await client.destroy();
33+
t.end();
34+
35+
});
36+
37+
assert.test('FallbackTreatment / Split factory with global fallbackTreatment defined', async t => {
38+
39+
const config = Object.assign({}, baseConfig);
40+
config.fallbackTreatments = {
41+
global: 'FALLBACK_TREATMENT'
42+
};
43+
const splitio = SplitFactory(config);
44+
const client = splitio.client();
45+
46+
await client.whenReady();
47+
48+
49+
t.equal(client.getTreatment('non_existent_flag'), 'FALLBACK_TREATMENT', 'The evaluation will return `FALLBACK_TREATMENT` if the flag does not exist and no fallbackTreatment is defined');
50+
t.equal(client.getTreatment('non_existent_flag_2'), 'FALLBACK_TREATMENT', 'The evaluation will return `FALLBACK_TREATMENT` if the flag does not exist and no fallbackTreatment is defined');
51+
52+
await client.destroy();
53+
t.end();
54+
55+
});
56+
57+
assert.test('FallbackTreatment / Split factory with specific fallbackTreatment defined', async t => {
58+
59+
const config = Object.assign({}, baseConfig);
60+
config.fallbackTreatments = {
61+
byFlag: {
62+
'non_existent_flag': 'FALLBACK_TREATMENT',
63+
}
64+
};
65+
const splitio = SplitFactory(config);
66+
const client = splitio.client();
67+
68+
await client.whenReady();
69+
70+
t.equal(client.getTreatment('non_existent_flag'), 'FALLBACK_TREATMENT', 'The evaluation will return `FALLBACK_TREATMENT` if the flag does not exist and no fallbackTreatment is defined');
71+
t.equal(client.getTreatment('non_existent_flag_2'), 'control', 'The evaluation will return `control` if the flag does not exist and no fallbackTreatment is defined');
72+
73+
t.equal(client.getTreatment('non_existent_flag'), 'FALLBACK_TREATMENT', 'The evaluation will return `FALLBACK_TREATMENT` if the flag does not exist and no fallbackTreatment is defined');
74+
t.equal(client.getTreatment('non_existent_flag_2'), 'control', 'The evaluation will return `control` if the flag does not exist and no fallbackTreatment is defined');
75+
76+
await client.destroy();
77+
t.end();
78+
79+
});
80+
81+
82+
assert.test('FallbackTreatment / flag override beats global fallbackTreatment', async t => {
83+
84+
const config = Object.assign({}, baseConfig);
85+
config.fallbackTreatments = {
86+
global: 'OFF_FALLBACK',
87+
byFlag: {
88+
'my_flag': 'ON_FALLBACK',
89+
}
90+
};
91+
const splitio = SplitFactory(config);
92+
const client = splitio.client();
93+
94+
await client.whenReady();
95+
96+
t.equal(client.getTreatment('my_flag'), 'ON_FALLBACK', 'The evaluation will return `ON_FALLBACK` if the flag does not exist and no fallbackTreatment is defined');
97+
t.equal(client.getTreatment('non_existent_flag_2'), 'OFF_FALLBACK', 'The evaluation will return `OFF_FALLBACK` if the flag does not exist and no fallbackTreatment is defined');
98+
99+
t.equal(client.getTreatment('my_flag'), 'ON_FALLBACK', 'The evaluation will return `ON_FALLBACK` if the flag does not exist and no fallbackTreatment is defined');
100+
t.equal(client.getTreatment('non_existent_flag_2'), 'OFF_FALLBACK', 'The evaluation will return `OFF_FALLBACK` if the flag does not exist and no fallbackTreatment is defined');
101+
102+
await client.destroy();
103+
t.end();
104+
105+
});
106+
107+
assert.test('FallbackTreatment / override applies only when original is control', async t => {
108+
109+
const config = Object.assign({}, baseConfig);
110+
config.fallbackTreatments = {
111+
global: 'OFF_FALLBACK'
112+
};
113+
const splitio = SplitFactory(config);
114+
const client = splitio.client();
115+
116+
await client.whenReady();
117+
118+
t.equal(client.getTreatment('user_account_in_whitelist'), 'off', 'The evaluation will return the treatment defined in the flag if it exists');
119+
t.equal(client.getTreatment('non_existent_flag'), 'OFF_FALLBACK', 'The evaluation will return `OFF_FALLBACK` if the flag does not exist and no fallbackTreatment is defined');
120+
121+
await client.destroy();
122+
t.end();
123+
124+
});
125+
126+
assert.test('FallbackTreatment / Impressions correctness with fallback when client is not whenReady', async t => {
127+
128+
const config = Object.assign({}, baseConfig);
129+
config.urls = {
130+
events: 'https://events.fallbacktreatment/api'
131+
};
132+
config.fallbackTreatments = {
133+
byFlag: {
134+
'any_flag': 'OFF_FALLBACK'
135+
}
136+
};
137+
const splitio = SplitFactory(config);
138+
const client = splitio.client();
139+
140+
t.equal(client.getTreatment('any_flag'), 'OFF_FALLBACK', 'The evaluation will return the fallbackTreatment if the client is not whenReady yet');
141+
t.equal(client.getTreatment('user_account_in_whitelist'), 'control', 'The evaluation will return the fallbackTreatment if the client is not whenReady yet');
142+
143+
await client.whenReady();
144+
145+
fetchMock.postOnce(config.urls.events + '/testImpressions/bulk', (_, opts) => {
146+
147+
const payload = JSON.parse(opts.body);
148+
149+
function validateImpressionData(featureFlagName, expectedLabel) {
150+
const impressions = payload.find(e => e.f === featureFlagName).i;
151+
152+
t.equal(impressions[0].r, expectedLabel, `${featureFlagName} impression with label ${expectedLabel}`);
153+
}
154+
155+
validateImpressionData('any_flag', 'fallback - not whenReady');
156+
validateImpressionData('user_account_in_whitelist', 'not whenReady');
157+
t.end();
158+
159+
return 200;
160+
});
161+
162+
await client.destroy();
163+
164+
});
165+
166+
assert.test('FallbackTreatment / Fallback dynamic config propagation', async t => {
167+
168+
const config = Object.assign({}, baseConfig);
169+
config.fallbackTreatments = {
170+
global: { treatment: 'OFF_FALLBACK', config: '{"global": true}' },
171+
byFlag: {
172+
'my_flag': { treatment: 'ON_FALLBACK', config: '{"flag": true}' }
173+
}
174+
};
175+
const splitio = SplitFactory(config);
176+
const client = splitio.client();
177+
178+
await client.whenReady();
179+
180+
t.deepEqual(client.getTreatmentWithConfig('my_flag'), { treatment: 'ON_FALLBACK', config: '{"flag": true}' }, 'The evaluation will propagate the config along with the treatment from the fallbackTreatment');
181+
t.deepEqual(client.getTreatmentWithConfig('non_existent_flag'), { treatment: 'OFF_FALLBACK', config: '{"global": true}' }, 'The evaluation will propagate the config along with the treatment from the fallbackTreatment');
182+
183+
await client.destroy();
184+
t.end();
185+
186+
});
187+
188+
assert.test('FallbackTreatment / Evaluations non existing flags with fallback do not generate impressions', async t => {
189+
190+
const config = Object.assign({}, baseConfig);
191+
config.urls = {
192+
events: 'https://events.fallbacktreatment/api'
193+
};
194+
config.fallbackTreatments = {
195+
global: { treatment: 'OFF_FALLBACK', config: '{"global": true}' },
196+
byFlag: {
197+
'my_flag': { treatment: 'ON_FALLBACK', config: '{"flag": true}' }
198+
}
199+
};
200+
config.impressionListener = listener;
201+
202+
const splitio = SplitFactory(config);
203+
const client = splitio.client();
204+
205+
await client.whenReady();
206+
207+
t.deepEqual(client.getTreatmentWithConfig('my_flag'), { treatment: 'ON_FALLBACK', config: '{"flag": true}' }, 'The evaluation will propagate the config along with the treatment from the fallbackTreatment');
208+
t.deepEqual(client.getTreatmentWithConfig('non_existent_flag'), { treatment: 'OFF_FALLBACK', config: '{"global": true}' }, 'The evaluation will propagate the config along with the treatment from the fallbackTreatment');
209+
210+
let POSTED_IMPRESSIONS_COUNT;
211+
212+
fetchMock.postOnce(config.urls.events + '/testImpressions/bulk', (_, opts) => {
213+
214+
const payload = JSON.parse(opts.body);
215+
t.equal(payload.length, 1, 'We should have just one impression for the two evaluated flags');
216+
217+
function validateImpressionData(featureFlagName, expectedLength) {
218+
219+
const impressions = payload.find(e => e.f === featureFlagName).i;
220+
t.equal(impressions.length, expectedLength, `${featureFlagName} has ${expectedLength} impressions`);
221+
}
222+
223+
validateImpressionData('my_flag', 1);
224+
validateImpressionData('non_existent_flag', 0);
225+
POSTED_IMPRESSIONS_COUNT = payload.reduce((acc, curr) => acc + curr.i.length, 0);
226+
t.equal(POSTED_IMPRESSIONS_COUNT, 1, 'We should have just one impression in total.');
227+
228+
return 200;
229+
});
230+
231+
setTimeout(() => {
232+
t.equal(listener.logImpression.callCount, POSTED_IMPRESSIONS_COUNT, 'Impression listener should be called once per each impression generated.');
233+
234+
t.end();
235+
}, 0);
236+
await client.destroy();
237+
238+
239+
});
240+
241+
assert.test('FallbackTreatment / LocalhostMode', async t => {
242+
243+
const config = {
244+
...baseConfig,
245+
core: {
246+
...baseConfig.core,
247+
authorizationKey: 'localhost',
248+
},
249+
fallbackTreatments: {
250+
global: 'OFF_FALLBACK'
251+
},
252+
features: {
253+
testing_split: 'on',
254+
}
255+
};
256+
const splitio = SplitFactory(config);
257+
const client = splitio.client();
258+
259+
await client.whenReady();
260+
261+
t.deepEqual(client.getTreatment('testing_split'), 'on', 'The evaluation should return the treatment defined in localhost mode');
262+
t.deepEqual(client.getTreatment('non_existent_flag'), 'OFF_FALLBACK', 'The evaluation will return `OFF_FALLBACK` if the flag does not exist');
263+
264+
await client.destroy();
265+
266+
t.end();
267+
});
268+
269+
}

src/__tests__/online/browser.spec.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import membershipsNicolas from '../mocks/memberships.nicolas@split.io.json';
2828
import membershipsMarcio from '../mocks/memberships.marcio@split.io.json';
2929
import membershipsEmmanuel from '../mocks/memberships.emmanuel@split.io.json';
3030
import { InLocalStorage } from '../../index';
31+
import evaluationsFallbackSuite from '../browserSuites/evaluations-fallback.spec';
3132

3233
const settings = settingsFactory({
3334
core: {
@@ -97,6 +98,7 @@ tape('## E2E CI Tests ##', function (assert) {
9798

9899
/* Check client evaluations. */
99100
assert.test('E2E / In Memory', evaluationsSuite.bind(null, configInMemory, fetchMock));
101+
assert.test('E2E / In Memory Fallback', evaluationsFallbackSuite.bind(null, configInMemory, fetchMock));
100102
assert.test('E2E / In Memory with Bucketing Key', evaluationsSuite.bind(null, configInMemoryWithBucketingKey, fetchMock));
101103
assert.test('E2E / In LocalStorage with In Memory Fallback', evaluationsSuite.bind(null, configInLocalStorage, fetchMock));
102104
/* Check impressions */

src/settings/defaults.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type SplitIO from '@splitsoftware/splitio-commons/types/splitio';
22
import { LogLevels, isLogLevelString } from '@splitsoftware/splitio-commons/src/logger/index';
33
import { CONSENT_GRANTED } from '@splitsoftware/splitio-commons/src/utils/constants';
44

5-
const packageVersion = '1.5.0';
5+
const packageVersion = '1.5.1-rc.0';
66

77
/**
88
* In browser, the default debug level, can be set via the `localStorage.splitio_debug` item.

0 commit comments

Comments
 (0)