Skip to content

Rule-based segments support #870

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 38 commits into from
May 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
70a1bac
Update tests and mocks
EmilianoSanchez Mar 11, 2025
9241e6d
Add rbs in /splitChanges payload
EmilianoSanchez Mar 12, 2025
12eb78f
Evaluation tests
EmilianoSanchez Mar 17, 2025
e1192c9
Evaluation tests in Redis
EmilianoSanchez Mar 17, 2025
6cc08c1
Streaming tests
EmilianoSanchez Mar 18, 2025
aecbd2c
Update dep
EmilianoSanchez Mar 20, 2025
710ea15
Merge branch 'rb_segments_test_updates' into rb_segments_add_tests
EmilianoSanchez Mar 20, 2025
22d56cf
Merge branch 'rb_segments_baseline' into rb_segments_test_updates
EmilianoSanchez Apr 3, 2025
a0a95c4
Merge branch 'rb_segments_baseline' into rb_segments_test_updates
EmilianoSanchez Apr 3, 2025
9c2a423
Merge branch 'rb_segments_test_updates' into rb_segments_add_tests
EmilianoSanchez Apr 3, 2025
7f1e85e
Update tests
EmilianoSanchez Apr 3, 2025
8ea167a
Fix tests
EmilianoSanchez Apr 3, 2025
2a783d6
Merge branch 'rb_segments_add_tests' into prerequisites
EmilianoSanchez Apr 3, 2025
612a8c3
Add tests
EmilianoSanchez Apr 4, 2025
9b356db
Add proxy fallback test
EmilianoSanchez Apr 15, 2025
20d7a7c
Merge branch 'rb_segments_add_tests' into prerequisites
EmilianoSanchez Apr 15, 2025
3dab06b
Fix test
EmilianoSanchez Apr 15, 2025
ef2fe4a
Merge branch 'rb_segments_add_tests' into prerequisites
EmilianoSanchez Apr 15, 2025
b0a8a1f
rc
EmilianoSanchez Apr 15, 2025
37c8669
cdn rc
EmilianoSanchez Apr 15, 2025
33e5ea9
Update JS-commons
EmilianoSanchez Apr 15, 2025
dc18dbf
Merge branch 'rb_segments_test_updates' into rb_segments_add_tests
EmilianoSanchez Apr 15, 2025
138f583
Merge branch 'rb_segments_add_tests' into prerequisites
EmilianoSanchez Apr 15, 2025
ebd9c3d
Merge pull request #862 from splitio/rb_segments_test_updates
EmilianoSanchez Apr 16, 2025
90c19d6
Merge pull request #863 from splitio/rb_segments_add_tests
EmilianoSanchez Apr 16, 2025
4cd04ea
Update rule-base segments DTO in test mocks
EmilianoSanchez May 9, 2025
a4bef02
Merge branch 'development' into rb_segments_baseline
EmilianoSanchez May 9, 2025
d0c4ca6
rc
EmilianoSanchez May 9, 2025
8845f70
rc
EmilianoSanchez May 9, 2025
628c62a
stable version
EmilianoSanchez May 12, 2025
b90296a
Merge pull request #875 from splitio/development
EmilianoSanchez May 16, 2025
dbe0fd3
Merge branch 'master' into rb_segments_baseline
EmilianoSanchez May 19, 2025
783e69c
Merge branch 'rb_segments_baseline' into prerequisites
EmilianoSanchez May 19, 2025
1a4aa7d
rc
EmilianoSanchez May 20, 2025
303b333
Fix typos
EmilianoSanchez May 26, 2025
ad5f027
Fix karma debug config for latest version of MacOS
EmilianoSanchez May 26, 2025
9367b2f
Stable version
EmilianoSanchez May 27, 2025
44ea95c
Merge pull request #869 from splitio/prerequisites
EmilianoSanchez May 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
11.4.0 (May 28, 2025)
- Added support for rule-based segments. These segments determine membership at runtime by evaluating their configured rules against the user attributes provided to the SDK.
- Added support for feature flag prerequisites. This allows customers to define dependency conditions between flags, which are evaluated before any allowlists or targeting rules.
- Updated @splitsoftware/splitio-commons package to version 2.4.0.

11.3.0 (May 16, 2025)
- Updated @splitsoftware/splitio-commons package to version 2.3.0, which optimizes the Redis storage to:
- Avoid lazy require of the `ioredis` dependency when the SDK is initialized, and
Expand Down
8 changes: 7 additions & 1 deletion karma/config.debug.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,14 @@
const merge = require('lodash/merge');

module.exports = merge({}, require('./config'), {
customLaunchers: {
ChromeNoSandbox: {
base: 'Chrome',
flags: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-gpu']
}
},
browsers: [
'Chrome'
'ChromeNoSandbox'
],
webpack: {
mode: 'development'
Expand Down
18 changes: 9 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@splitsoftware/splitio",
"version": "11.3.0",
"version": "11.4.0",
"description": "Split SDK",
"files": [
"README.md",
Expand Down Expand Up @@ -38,7 +38,7 @@
"node": ">=14.0.0"
},
"dependencies": {
"@splitsoftware/splitio-commons": "2.3.0",
"@splitsoftware/splitio-commons": "2.4.0",
"bloom-filters": "^3.0.4",
"ioredis": "^4.28.0",
"js-yaml": "^3.13.1",
Expand Down
3 changes: 1 addition & 2 deletions src/__tests__/browserSuites/evaluations-semver.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ const config = {

export default async function (fetchMock, assert) {

fetchMock.getOnce(config.urls.sdk + '/splitChanges?s=1.2&since=-1', { status: 200, body: splitChangesMock1 });
fetchMock.getOnce(config.urls.sdk + '/splitChanges?s=1.2&since=1675259356568', { status: 200, body: { splits: [], since: 1675259356568, till: 1675259356568 } });
fetchMock.getOnce(config.urls.sdk + '/splitChanges?s=1.3&since=-1&rbSince=-1', { status: 200, body: splitChangesMock1 });
fetchMock.getOnce(config.urls.sdk + '/memberships/emi%40split.io', { status: 200, body: { ms: {} } });
fetchMock.getOnce(config.urls.sdk + '/memberships/2nd', { status: 200, body: { ms: {} } });

Expand Down
50 changes: 44 additions & 6 deletions src/__tests__/browserSuites/evaluations.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,41 @@ export default function (config, fetchMock, assert) {

};

const evaluationsWithRuleBasedSegmentsAndPrerequisites = async (splitio) => {
fetchMock.getOnce('https://sdk.split.io/api/memberships/emi%40split.io', { status: 200, body: { ms: { k: [{ n: 'segment_excluded_by_rbs' }] } } });
fetchMock.getOnce('https://sdk.split.io/api/memberships/mauro%40split.io', { status: 200, body: { ms: {} } });
fetchMock.getOnce('https://sdk.split.io/api/memberships/bilal%40split.io', { status: 200, body: { ms: {} } });
fetchMock.getOnce('https://sdk.split.io/api/memberships/other_key', { status: 200, body: { ms: {} } });

const client1 = splitio.client('emi@split.io');
await client1.ready();
assert.equal(client1.getTreatment('rbs_test_flag'), 'v2', 'key in excluded segment');
assert.equal(client1.getTreatment('rbs_test_flag_negated'), 'v1', 'key in excluded segment');
assert.equal(client1.getTreatment('always_on_if_prerequisite'), 'off', 'prerequisite not satisfied (key in excluded segment)');
await client1.destroy();

const client2 = splitio.client('mauro@split.io');
await client2.ready();
assert.equal(client2.getTreatment('rbs_test_flag'), 'v2', 'excluded key');
assert.equal(client2.getTreatment('rbs_test_flag_negated'), 'v1', 'excluded key');
assert.equal(client2.getTreatment('always_on_if_prerequisite'), 'off', 'prerequisite not satisfied (excluded key)');
await client2.destroy();

const client3 = splitio.client('bilal@split.io');
await client3.ready();
assert.equal(client3.getTreatment('rbs_test_flag'), 'v1', 'key satisfies the rbs condition');
assert.equal(client3.getTreatment('rbs_test_flag_negated'), 'v2', 'key satisfies the rbs condition');
assert.equal(client3.getTreatment('always_on_if_prerequisite'), 'on', 'prerequisite satisfied (key satisfies the rbs condition)');
await client3.destroy();

const client4 = splitio.client('other_key');
await client4.ready();
assert.equal(client4.getTreatment('rbs_test_flag'), 'v2', 'key not in segment');
assert.equal(client4.getTreatment('rbs_test_flag_negated'), 'v1', 'key not in segment');
assert.equal(client4.getTreatment('always_on_if_prerequisite'), 'off', 'prerequisite not satisfied (key not in segment)');
await client4.destroy();
};

for (i; i < SDK_INSTANCES_TO_TEST; i++) {
let splitio = SplitFactory(config);

Expand All @@ -376,13 +411,16 @@ export default function (config, fetchMock, assert) {
getTreatmentsTests(client);
getTreatmentsWithConfigTests(client);
getTreatmentsWithInMemoryAttributes(client);
clientTABucket1.destroy();
client.destroy();
tested++;

if (tested === SDK_INSTANCES_TO_TEST) {
assert.end();
}
evaluationsWithRuleBasedSegmentsAndPrerequisites(splitio).then(() => {
clientTABucket1.destroy();
client.destroy();
tested++;

if (tested === SDK_INSTANCES_TO_TEST) {
assert.end();
}
});
});
}
}
12 changes: 6 additions & 6 deletions src/__tests__/browserSuites/fetch-specific-splits.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ export function fetchSpecificSplits(fetchMock, assert) {
const queryString = queryStrings[i] || '';
let factory;

fetchMock.getOnce(urls.sdk + '/splitChanges?s=1.2&since=-1' + queryString, { status: 200, body: { splits: [], since: -1, till: 1457552620999 } });
fetchMock.getOnce(urls.sdk + '/splitChanges?s=1.2&since=1457552620999' + queryString, { status: 200, body: { splits: [], since: 1457552620999, till: 1457552620999 } });
fetchMock.getOnce(urls.sdk + '/splitChanges?s=1.2&since=1457552620999' + queryString, function () {
fetchMock.getOnce(urls.sdk + '/splitChanges?s=1.3&since=-1&rbSince=-1' + queryString, { status: 200, body: { ff: { d: [], s: -1, t: 1457552620999 } } });
fetchMock.getOnce(urls.sdk + '/splitChanges?s=1.3&since=1457552620999&rbSince=-1' + queryString, { status: 200, body: { ff: { d: [], s: 1457552620999, t: 1457552620999 } } });
fetchMock.getOnce(urls.sdk + '/splitChanges?s=1.3&since=1457552620999&rbSince=-1' + queryString, function () {
factory.client().destroy().then(() => {
assert.pass(`splitFilters #${i}`);
});
return { status: 200, body: { splits: [], since: 1457552620999, till: 1457552620999 } };
return { status: 200, body: { ff: { d: [], s: 1457552620999, t: 1457552620999 } } };
});
fetchMock.get(urls.sdk + '/memberships/nicolas%40split.io', { status: 200, body: { 'ms': {} } });

Expand Down Expand Up @@ -70,8 +70,8 @@ export function fetchSpecificSplitsForFlagSets(fetchMock, assert) {
const queryString = '&sets=4_valid,set_2,set_3,set_ww,set_x';
fetchMock.get(baseUrls.sdk + '/memberships/nicolas%40split.io', { status: 200, body: { 'ms': {} } });

fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.2&since=-1' + queryString, { status: 200, body: { splits: [], since: 1457552620999, till: 1457552620999 }});
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.2&since=1457552620999' + queryString, async function () {
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.3&since=-1&rbSince=-1' + queryString, { status: 200, body: { ff: { d: [], s: 1457552620999, t: 1457552620999 } }});
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.3&since=1457552620999&rbSince=-1' + queryString, async function () {
t.pass('flag set query correctly formed');
t.true(logSpy.calledWithExactly('[WARN] splitio => settings: bySet filter value "set_x " has extra whitespace, trimming.'));
t.true(logSpy.calledWithExactly('[WARN] splitio => settings: you passed invalid+, flag set must adhere to the regular expressions /^[a-z0-9][_a-z0-9]{0,49}$/. This means a flag set must start with a letter or number, be in lowercase, alphanumeric and have a max length of 50 characters. invalid+ was discarded.'));
Expand Down
24 changes: 12 additions & 12 deletions src/__tests__/browserSuites/flag-sets.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ export default function flagSets(fetchMock, t) {
let manager;

// Receive split change with 1 split belonging to set_1 & set_2 and one belonging to set_3
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.2&since=-1&sets=set_1,set_2', function () {
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.3&since=-1&rbSince=-1&sets=set_1,set_2', function () {
return { status: 200, body: splitChange2};
});

// Receive split change with 1 split belonging to set_1 only
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.2&since=1602796638344&sets=set_1,set_2', function () {
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.3&since=1602796638344&rbSince=-1&sets=set_1,set_2', function () {
// stored feature flags before update
const storedFlags = manager.splits();
assert.true(storedFlags.length === 1, 'only one feature flag should be added');
Expand All @@ -41,7 +41,7 @@ export default function flagSets(fetchMock, t) {
});

// Receive split change with 1 split belonging to set_3 only
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.2&since=1602797638344&sets=set_1,set_2', function () {
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.3&since=1602797638344&rbSince=-1&sets=set_1,set_2', function () {
// stored feature flags before update
const storedFlags = manager.splits();
assert.true(storedFlags.length === 1);
Expand All @@ -52,7 +52,7 @@ export default function flagSets(fetchMock, t) {
return { status: 200, body: splitChange0};
});

fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.2&since=1602798638344&sets=set_1,set_2', async function () {
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.3&since=1602798638344&rbSince=-1&sets=set_1,set_2', async function () {
// stored feature flags before update
const storedFlags = manager.splits();
assert.true(storedFlags.length === 0, 'the feature flag should be removed');
Expand All @@ -75,12 +75,12 @@ export default function flagSets(fetchMock, t) {
let manager;

// Receive split change with 1 split belonging to set_1 & set_2 and one belonging to set_3
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.2&since=-1', function () {
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.3&since=-1&rbSince=-1', function () {
return { status: 200, body: splitChange2};
});

// Receive split change with 1 split belonging to set_1 only
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.2&since=1602796638344', function () {
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.3&since=1602796638344&rbSince=-1', function () {
// stored feature flags before update
const storedFlags = manager.splits();
assert.true(storedFlags.length === 2, 'every feature flag should be added');
Expand All @@ -94,7 +94,7 @@ export default function flagSets(fetchMock, t) {
});

// Receive split change with 1 split belonging to set_3 only
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.2&since=1602797638344', function () {
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.3&since=1602797638344&rbSince=-1', function () {
// stored feature flags before update
const storedFlags = manager.splits();
assert.true(storedFlags.length === 2);
Expand All @@ -107,7 +107,7 @@ export default function flagSets(fetchMock, t) {
return { status: 200, body: splitChange0};
});

fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.2&since=1602798638344', async function () {
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.3&since=1602798638344&rbSince=-1', async function () {
// stored feature flags before update
const storedFlags = manager.splits();
assert.true(storedFlags.length === 2);
Expand Down Expand Up @@ -137,11 +137,11 @@ export default function flagSets(fetchMock, t) {

fetchMock.get(baseUrls.sdk + '/memberships/nicolas%40split.io', { status: 200, body: { 'ms': {} } });
// Receive split change with 1 split belonging to set_1 & set_2 and one belonging to set_3
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.2&since=-1&sets=set_1', function () {
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.3&since=-1&rbSince=-1&sets=set_1', function () {
return { status: 200, body: splitChange2};
});

fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.2&since=1602796638344&sets=set_1', async function () {
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.3&since=1602796638344&rbSince=-1&sets=set_1', async function () {
// stored feature flags before update
assert.deepEqual(client.getTreatmentsByFlagSet('set_1'), {workm: 'on'}, 'only the flag in set_1 can be evaluated');
assert.deepEqual(client.getTreatmentsByFlagSet('set_2'), {}, 'only the flag in set_1 can be evaluated');
Expand Down Expand Up @@ -174,11 +174,11 @@ export default function flagSets(fetchMock, t) {

fetchMock.get(baseUrls.sdk + '/memberships/nicolas%40split.io', { status: 200, body: { 'ms': {} } });
// Receive split change with 1 split belonging to set_1 & set_2 and one belonging to set_3
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.2&since=-1', function () {
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.3&since=-1&rbSince=-1', function () {
return { status: 200, body: splitChange2};
});

fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.2&since=1602796638344', async function () {
fetchMock.getOnce(baseUrls.sdk + '/splitChanges?s=1.3&since=1602796638344&rbSince=-1', async function () {
// stored feature flags before update
assert.deepEqual(client.getTreatmentsByFlagSet('set_1'), {workm: 'on'}, 'all flags can be evaluated');
assert.deepEqual(client.getTreatmentsByFlagSet('set_2'), {workm: 'on'}, 'all flags can be evaluated');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,7 @@ export default function (fetchMock, assert) {

// Mock GET endpoints before creating the client
const settings = settingsFactory(config);
fetchMock.getOnce(url(settings, '/splitChanges?s=1.2&since=-1'), { status: 200, body: splitChangesMock1 });
fetchMock.getOnce(url(settings, '/splitChanges?s=1.2&since=1457552620999'), { status: 200, body: { splits: [], since: 1457552620999, till: 1457552620999 } });
fetchMock.getOnce(url(settings, '/splitChanges?s=1.3&since=-1&rbSince=-1'), { status: 200, body: splitChangesMock1 });
fetchMock.getOnce(url(settings, `/memberships/${encodeURIComponent(config.core.key)}`), { status: 200, body: { ms: {} } });

// Init Split client
Expand Down
4 changes: 1 addition & 3 deletions src/__tests__/browserSuites/impressions.debug.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { SplitFactory } from '../../';
import { settingsFactory } from '../../settings';
import splitChangesMock1 from '../mocks/splitchanges.since.-1.json';
import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json';
import membershipsFacundo from '../mocks/memberships.facundo@split.io.json';
import { DEBUG } from '@splitsoftware/splitio-commons/src/utils/constants';
import { truncateTimeFrame } from '@splitsoftware/splitio-commons/src/utils/time';
Expand All @@ -24,8 +23,7 @@ let truncatedTimeFrame;

export default function (fetchMock, assert) {
// Mocking this specific route to make sure we only get the items we want to test from the handlers.
fetchMock.getOnce(url(settings, '/splitChanges?s=1.2&since=-1'), { status: 200, body: splitChangesMock1 });
fetchMock.get(url(settings, '/splitChanges?s=1.2&since=1457552620999'), { status: 200, body: splitChangesMock2 });
fetchMock.getOnce(url(settings, '/splitChanges?s=1.3&since=-1&rbSince=-1'), { status: 200, body: splitChangesMock1 });
fetchMock.get(url(settings, '/memberships/facundo%40split.io'), { status: 200, body: membershipsFacundo });

const splitio = SplitFactory({
Expand Down
4 changes: 1 addition & 3 deletions src/__tests__/browserSuites/impressions.none.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { SplitFactory } from '../..';
import { settingsFactory } from '../../settings/node';
import splitChangesMock1 from '../mocks/splitchanges.since.-1.json';
import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json';
import membershipsFacundo from '../mocks/memberships.facundo@split.io.json';
import { NONE } from '@splitsoftware/splitio-commons/src/utils/constants';
import { truncateTimeFrame } from '@splitsoftware/splitio-commons/src/utils/time';
Expand Down Expand Up @@ -41,8 +40,7 @@ const config = {

export default async function (fetchMock, assert) {
// Mocking this specific route to make sure we only get the items we want to test from the handlers.
fetchMock.getOnce(url(settings, '/splitChanges?s=1.2&since=-1'), { status: 200, body: splitChangesMock1 });
fetchMock.get(url(settings, '/splitChanges?s=1.2&since=1457552620999'), { status: 200, body: splitChangesMock2 });
fetchMock.getOnce(url(settings, '/splitChanges?s=1.3&since=-1&rbSince=-1'), { status: 200, body: splitChangesMock1 });
fetchMock.get(url(settings, '/memberships/facundo%40split.io'), { status: 200, body: membershipsFacundo });
fetchMock.get(url(settings, '/memberships/emma%40split.io'), { status: 200, body: membershipsFacundo });

Expand Down
4 changes: 2 additions & 2 deletions src/__tests__/browserSuites/impressions.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ let truncatedTimeFrame;

export default function (fetchMock, assert) {
// Mocking this specific route to make sure we only get the items we want to test from the handlers.
fetchMock.getOnce(url(settings, '/splitChanges?s=1.2&since=-1'), { status: 200, body: splitChangesMock1 });
fetchMock.get(url(settings, '/splitChanges?s=1.2&since=1457552620999'), { status: 200, body: splitChangesMock2 });
fetchMock.getOnce(url(settings, '/splitChanges?s=1.3&since=-1&rbSince=-1'), { status: 200, body: splitChangesMock1 });
fetchMock.get(url(settings, '/splitChanges?s=1.3&since=1457552620999&rbSince=100'), { status: 200, body: splitChangesMock2 });
fetchMock.get(url(settings, '/memberships/facundo%40split.io'), { status: 200, body: membershipsFacundo });

const splitio = SplitFactory({
Expand Down
Loading