Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"new-cap" : 0,
"no-mixed-requires": 0,
"camelcase": [2, {"properties": "never"}],
"no-use-before-define": [2, "nofunc"]
"no-use-before-define": [2, "nofunc"],
"no-trailing-spaces": "error"
},

"parserOptions": {
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

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

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@splitsoftware/splitio",
"version": "10.21.2-rc.4",
"version": "10.21.2-rc.6",
"description": "Split SDK",
"files": [
"README.md",
Expand Down Expand Up @@ -34,7 +34,7 @@
},
"dependencies": {
"@ably/bloomit": "^1.4.2",
"@splitsoftware/splitio-commons": "1.6.2-rc.10",
"@splitsoftware/splitio-commons": "1.6.2-rc.14",
"@types/google.analytics": "0.0.40",
"@types/ioredis": "^4.28.0",
"ioredis": "^4.28.0",
Expand Down Expand Up @@ -112,6 +112,7 @@
"test-ts-decls": "./scripts/ts-tests.sh",
"posttest-ts-decls": "npm unlink && npm install",
"test": "npm run test-node && npm run test-browser",
"all": "npm run check && npm run build && npm run test-ts-decls && npm run test",
"publish:rc": "npm run check && npm run build && npm publish --tag canary",
"publish:stable": "npm run check && npm run build && npm publish"
},
Expand Down
34 changes: 21 additions & 13 deletions src/__tests__/browserSuites/impressions.none.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import splitChangesMock1 from '../mocks/splitchanges.since.-1.json';
import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json';
import mySegmentsFacundo from '../mocks/mysegments.facundo@split.io.json';
import { NONE } from '@splitsoftware/splitio-commons/src/utils/constants';
import { truncateTimeFrame } from '@splitsoftware/splitio-commons/src/utils/time';
import { url } from '../testUtils';

const baseUrls = {
Expand All @@ -27,9 +28,6 @@ const config = {
scheduler: {
featuresRefreshRate: 1,
segmentsRefreshRate: 1,
impressionsRefreshRate: 3000,
impressionsQueueSize: 3, // flush impressions when 3 are queued
uniqueKeysCacheSize: 3 // flush impressions when 3 are queued
},
urls: baseUrls,
startup: {
Expand All @@ -47,37 +45,44 @@ export default async function (fetchMock, assert) {
fetchMock.get(url(settings, '/splitChanges?since=1457552620999'), { status: 200, body: splitChangesMock2 });
fetchMock.get(url(settings, '/mySegments/facundo%40split.io'), { status: 200, body: mySegmentsFacundo });
fetchMock.get(url(settings, '/mySegments/emma%40split.io'), { status: 200, body: mySegmentsFacundo });
fetchMock.postOnce(baseUrls.events + '/testImpressions/count', 200);

const splitio = SplitFactory(config);
const client = splitio.client();
const sharedClient = splitio.client('emma@split.io');

fetchMock.postOnce(baseUrls.events + '/testImpressions/count', (url, opts) => {
const data = JSON.parse(opts.body);
const truncatedTimeFrame = truncateTimeFrame(Date.now());

assert.deepEqual(data, {
pf: [
{ f: 'split_with_config', m: truncatedTimeFrame, rc: 2 },
{ f: 'always_off', m: truncatedTimeFrame, rc: 4 },
{ f: 'always_on', m: truncatedTimeFrame, rc: 2 }
]
});
return 200;
});

fetchMock.postOnce(url(settings, '/v1/keys/cs'), (url, opts) => {
const data = JSON.parse(opts.body);

assert.deepEqual(data, {
keys: [
{
k: 'facundo@split.io',
fs: ['split_with_config','always_off', 'always_on']
fs: ['split_with_config', 'always_off', 'always_on']
},
{
k: 'emma@split.io',
fs: ['always_off', 'always_on']
}
]
}, 'We performed evaluations for two keys, so we should have 2 item total.');

client.destroy().then(() => {
assert.end();

});

return 200;
});

splitio.Logger.enable();

await client.ready();

client.getTreatment('split_with_config');
Expand All @@ -88,5 +93,8 @@ export default async function (fetchMock, assert) {
client.getTreatment('always_on');
client.getTreatment('always_off');
client.getTreatment('split_with_config');


client.destroy().then(() => {
assert.end();
});
}
16 changes: 12 additions & 4 deletions src/__tests__/consumer/node_redis.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ tape('NodeJS Redis', function (t) {
const sdk = SplitFactory(config);
const client = sdk.client();

assert.equal(await client.getTreatment('UT_Segment_member', 'UT_IN_SEGMENT'), 'control', 'Evaluations using Redis storage should be control until connection is stablished.');
assert.equal(await client.getTreatment('other', 'UT_IN_SEGMENT'), 'control', 'Evaluations using Redis storage should be control until connection is stablished.');
await client.ready();

assert.equal(await client.getTreatment('UT_Segment_member', 'UT_IN_SEGMENT'), 'on', 'Evaluations using Redis storage should be correct.');
assert.equal(await client.getTreatment('other', 'UT_IN_SEGMENT'), 'off', 'Evaluations using Redis storage should be correct.');

Expand Down Expand Up @@ -142,7 +146,7 @@ tape('NodeJS Redis', function (t) {
if (error) assert.fail('Redis server should be reachable');

const trackedImpressionsAndEvents = stdout.split('\n').filter(line => line !== '').map(line => parseInt(line));
assert.deepEqual(trackedImpressionsAndEvents, [14, 2], 'Tracked impressions and events should be stored in Redis');
assert.deepEqual(trackedImpressionsAndEvents, [16, 2], 'Tracked impressions and events should be stored in Redis');

// Validate stored telemetry
exec(`echo "HLEN ${config.storage.prefix}.SPLITIO.telemetry.latencies \n HLEN ${config.storage.prefix}.SPLITIO.telemetry.exceptions \n HGET ${config.storage.prefix}.SPLITIO.telemetry.init nodejs-${version}/${HOSTNAME_VALUE}/${IP_VALUE}" | redis-cli -p ${redisPort}`, (error, stdout) => {
Expand All @@ -168,6 +172,8 @@ tape('NodeJS Redis', function (t) {
assert.equal(config.sync.impressionsMode, OPTIMIZED, 'impressionsMode should be OPTIMIZED');
const sdk = SplitFactory(config);
const client = sdk.client();
await client.ready();

assert.equal(await client.getTreatment('UT_Segment_member', 'UT_IN_SEGMENT'), 'on', 'Evaluations using Redis storage should be correct.');
assert.equal(await client.getTreatment('other', 'UT_IN_SEGMENT'), 'off', 'Evaluations using Redis storage should be correct.');
// this should be deduped
Expand Down Expand Up @@ -301,6 +307,8 @@ tape('NodeJS Redis', function (t) {
assert.equal(config.sync.impressionsMode, NONE, 'impressionsMode should be NONE');
const sdk = SplitFactory(config);
const client = sdk.client();
await client.ready();

assert.equal(await client.getTreatment('UT_Segment_member', 'UT_IN_SEGMENT'), 'on', 'Evaluations using Redis storage should be correct.');
assert.equal(await client.getTreatment('other', 'UT_IN_SEGMENT'), 'off', 'Evaluations using Redis storage should be correct.');

Expand Down Expand Up @@ -386,7 +394,6 @@ tape('NodeJS Redis', function (t) {
});
});


t.test('Connection timeout and then ready', assert => {
const readyTimeout = 0.1; // 100 millis
const configWithShortTimeout = { ...config, startup: { readyTimeout } };
Expand All @@ -399,7 +406,7 @@ tape('NodeJS Redis', function (t) {
assert.plan(18);

client.getTreatment('UT_Segment_member', 'always-on').then(treatment => {
assert.equal(treatment, 'on', 'Evaluations using Redis storage should be correct and resolved once Redis connection is stablished.');
assert.equal(treatment, 'control', 'Evaluations using Redis storage should be control until Redis connection is stablished.');
});
client.track('nicolas@split.io', 'user', 'test.redis.event', 18).then(result => {
assert.true(result, 'If the event was succesfully queued the promise will resolve to true once Redis connection is stablished');
Expand Down Expand Up @@ -585,7 +592,7 @@ tape('NodeJS Redis', function (t) {
// Redis client and keys required to check Redis store.
const setting = settingsFactory(config);
const connection = new RedisClient(setting.storage.options.url);
const keys = new KeyBuilderSS(validatePrefix(setting.storage.prefix));
const keys = new KeyBuilderSS(validatePrefix(setting.storage.prefix), { s: 'js_someversion', i: 'some_ip', n: 'some_hostname' });
const eventKey = keys.buildEventsKey();
const impressionsKey = keys.buildImpressionsKey();

Expand All @@ -596,6 +603,7 @@ tape('NodeJS Redis', function (t) {
// Init Split client for current config
const sdk = SplitFactory(config);
const client = sdk.client();
await client.ready();

// Perform client actions to store a single event and impression objects into Redis
await client.getTreatment('UT_Segment_member', 'UT_IN_SEGMENT');
Expand Down
2 changes: 0 additions & 2 deletions src/__tests__/nodeSuites/impressions.debug.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ export default async function (key, fetchMock, assert) {
return 200;
});

splitio.Logger.enable();
evaluationsStart = Date.now();

await client.ready();
Expand All @@ -99,7 +98,6 @@ export default async function (key, fetchMock, assert) {
client.getTreatment({ matchingKey: key, bucketingKey: 'test_buck_key' }, 'split_with_config');
client.getTreatment({ matchingKey: key, bucketingKey: 'test_buck_key' }, 'split_with_config');
client.getTreatment({ matchingKey: key, bucketingKey: 'test_buck_key' }, 'split_with_config');
splitio.Logger.disable();

evaluationsEnd = Date.now();
}
38 changes: 23 additions & 15 deletions src/__tests__/nodeSuites/impressions.none.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { settingsFactory } from '../../settings';
import splitChangesMock1 from '../mocks/splitchanges.since.-1.json';
import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json';
import { NONE } from '@splitsoftware/splitio-commons/src/utils/constants';
import { truncateTimeFrame } from '@splitsoftware/splitio-commons/src/utils/time';
import { url } from '../testUtils';

const baseUrls = {
Expand All @@ -25,9 +26,6 @@ const config = {
scheduler: {
featuresRefreshRate: 1,
segmentsRefreshRate: 1,
impressionsRefreshRate: 3000,
impressionsQueueSize: 3, // flush impressions when 3 are queued
uniqueKeysCacheSize: 7 // flush impressions when 7 are queued
},
urls: baseUrls,
startup: {
Expand All @@ -44,39 +42,46 @@ export default async function (key, fetchMock, assert) {
fetchMock.getOnce(url(settings, '/splitChanges?since=-1'), { status: 200, body: splitChangesMock1 });
fetchMock.get(url(settings, '/splitChanges?since=1457552620999'), { status: 200, body: splitChangesMock2 });
fetchMock.get(new RegExp(`${url(settings, '/segmentChanges/')}.*`), { status: 200, body: { since: 10, till: 10, name: 'segmentName', added: [], removed: [] } });
fetchMock.postOnce(baseUrls.events + '/testImpressions/count', 200);

const splitio = SplitFactory(config);
const client = splitio.client();

fetchMock.postOnce(baseUrls.events + '/testImpressions/count', (url, opts) => {
const data = JSON.parse(opts.body);
const truncatedTimeFrame = truncateTimeFrame(Date.now());

assert.deepEqual(data, {
pf: [
{ f: 'split_with_config', m: truncatedTimeFrame, rc: 3 },
{ f: 'always_off', m: truncatedTimeFrame, rc: 3 },
{ f: 'always_on', m: truncatedTimeFrame, rc: 5 }
]
});
return 200;
});

fetchMock.postOnce(url(settings, '/v1/keys/ss'), (url, opts) => {
const data = JSON.parse(opts.body);

assert.deepEqual(data, {
keys: [
{
f: 'split_with_config',
ks:['emma@split.io','emi@split.io']
ks: ['emma@split.io', 'emi@split.io']
},
{
f: 'always_off',
ks:['emma@split.io','emi@split.io']
ks: ['emma@split.io', 'emi@split.io']
},
{
f: 'always_on',
ks:['emma@split.io','emi@split.io','nico@split.io']
ks: ['emma@split.io', 'emi@split.io', 'nico@split.io']
}
]
}, 'We performed evaluations for three split, so we should have 3 item total.');

client.destroy().then(() => {
assert.end();
});

return 200;
});

splitio.Logger.enable();

await client.ready();

client.getTreatment('emma@split.io', 'split_with_config');
Expand All @@ -90,5 +95,8 @@ export default async function (key, fetchMock, assert) {
client.getTreatment('nico@split.io', 'always_on');
client.getTreatment('emi@split.io', 'split_with_config');
client.getTreatment('emma@split.io', 'split_with_config');


client.destroy().then(() => {
assert.end();
});
}
2 changes: 0 additions & 2 deletions src/__tests__/nodeSuites/impressions.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ export default async function(key, fetchMock, assert) {
return 200;
});

splitio.Logger.enable();
evaluationsStart = Date.now();

assert.equal(client.getTreatment(key, 'not_existent_split'), 'control', `If we try to get an evaluation BEFORE the client is ready, we expect ${SDK_NOT_READY} label on the impression.`);
Expand All @@ -147,7 +146,6 @@ export default async function(key, fetchMock, assert) {
}, 'We should get an evaluation as always.');
client.getTreatmentWithConfig({ matchingKey: key, bucketingKey: 'test_buck_key'}, 'split_with_config');
client.getTreatmentWithConfig({ matchingKey: 'different', bucketingKey: 'test_buck_key'}, 'split_with_config');
splitio.Logger.disable();

evaluationsEnd = Date.now();
}
2 changes: 1 addition & 1 deletion src/factory/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ function getModules(settings) {
SignalListener,

impressionsObserverFactory: impressionObserverSSFactory,

filterAdapterFactory: bloomFilterFactory
};

Expand Down
14 changes: 7 additions & 7 deletions src/platform/filter/__tests__/bloomFilter.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@ import tape from 'tape-catch';
import { bloomFilterFactory } from '../bloomFilter';

tape('Bloom filter', (assert) => {

const bloomFilter = bloomFilterFactory();

assert.true(bloomFilter.add('feature','key'));
assert.false(bloomFilter.contains('feature1','key'));
assert.true(bloomFilter.contains('feature','key'));

bloomFilter.clear();

assert.false(bloomFilter.contains('feature','key'));

assert.true(bloomFilter.add('feature2','key'));
assert.false(bloomFilter.contains('feature3','key'));
assert.true(bloomFilter.contains('feature2','key'));

assert.end();

});
Loading