From 42cf24dd0b0eb4414db46b1fc6cb761131cf5231 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 19 Dec 2024 13:39:12 -0300 Subject: [PATCH 01/21] Update tests to validate expirationDays config --- .../browserSuites/ready-from-cache.spec.js | 15 +++++++++------ src/settings/storage/browser.js | 6 +++++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/__tests__/browserSuites/ready-from-cache.spec.js b/src/__tests__/browserSuites/ready-from-cache.spec.js index 0e9cdd90f..a69dbccd4 100644 --- a/src/__tests__/browserSuites/ready-from-cache.spec.js +++ b/src/__tests__/browserSuites/ready-from-cache.spec.js @@ -247,7 +247,7 @@ export default function (fetchMock, assert) { }); }); - assert.test(t => { // Testing when we start with cached data and not expired (lastUpdate item higher than expirationTimestamp) + assert.test(t => { // Testing when we start with cached data and not expired (lastUpdate timestamp higher than default (10) expirationDays ago) const testUrls = { sdk: 'https://sdk.baseurl/readyFromCacheWithData3', events: 'https://events.baseurl/readyFromCacheWithData3' @@ -365,7 +365,7 @@ export default function (fetchMock, assert) { }); }); - assert.test(t => { // Testing when we start with cached data but expired (lastUpdate item lower than expirationTimestamp) + assert.test(t => { // Testing when we start with cached data but expired (lastUpdate timestamp lower than custom (1) expirationDays ago) const testUrls = { sdk: 'https://sdk.baseurl/readyFromCacheWithData4', events: 'https://events.baseurl/readyFromCacheWithData4' @@ -375,7 +375,8 @@ export default function (fetchMock, assert) { fetchMock.get(testUrls.sdk + '/splitChanges?s=1.2&since=-1', function () { t.equal(localStorage.getItem('some_user_item'), 'user_item', 'user items at localStorage must not be changed'); t.equal(localStorage.getItem('readyFromCache_4.SPLITIO.hash'), expectedHashNullFilter, 'storage hash must not be changed'); - t.equal(localStorage.length, 2, 'feature flags cache data must be cleaned from localStorage'); + t.true(nearlyEqual(parseInt(localStorage.getItem('readyFromCache_4.SPLITIO.lastClear'), 10), Date.now()), 'storage lastClear timestamp must be updated'); + t.equal(localStorage.length, 3, 'feature flags cache data must be cleaned from localStorage'); return { status: 200, body: splitChangesMock1 }; }); fetchMock.get(testUrls.sdk + '/splitChanges?s=1.2&since=1457552620999', { status: 200, body: splitChangesMock2 }); @@ -393,7 +394,7 @@ export default function (fetchMock, assert) { localStorage.setItem('some_user_item', 'user_item'); localStorage.setItem('readyFromCache_4.SPLITIO.splits.till', 25); - localStorage.setItem('readyFromCache_4.SPLITIO.splits.lastUpdated', Date.now() - DEFAULT_CACHE_EXPIRATION_IN_MILLIS - 1); // -1 to ensure having an expired lastUpdated item + localStorage.setItem('readyFromCache_4.SPLITIO.splits.lastUpdated', Date.now() - DEFAULT_CACHE_EXPIRATION_IN_MILLIS / 10 - 1); // -1 to ensure having an expired lastUpdated item localStorage.setItem('readyFromCache_4.SPLITIO.split.always_on', alwaysOnSplitInverted); localStorage.setItem('readyFromCache_4.SPLITIO.hash', expectedHashNullFilter); @@ -402,7 +403,8 @@ export default function (fetchMock, assert) { ...baseConfig, storage: { type: 'LOCALSTORAGE', - prefix: 'readyFromCache_4' + prefix: 'readyFromCache_4', + expirationDays: 1, }, startup: { readyTimeout: 0.85 @@ -650,7 +652,8 @@ export default function (fetchMock, assert) { ...baseConfig, storage: { type: 'LOCALSTORAGE', - prefix: 'readyFromCache_7' + prefix: 'readyFromCache_7', + expirationDays: 0, // invalid value, will use default (10) }, urls: testUrls, sync: { diff --git a/src/settings/storage/browser.js b/src/settings/storage/browser.js index 10a9e3eea..0165d45e3 100644 --- a/src/settings/storage/browser.js +++ b/src/settings/storage/browser.js @@ -10,7 +10,9 @@ export function validateStorage(settings) { storage: { type, options = {}, - prefix + prefix, + expirationDays, + clearOnInit } = { type: STORAGE_MEMORY }, } = settings; let __originalType; @@ -38,6 +40,8 @@ export function validateStorage(settings) { type, options, prefix, + expirationDays, + clearOnInit, __originalType }; } From 2dd7820a18726a521fdf2a1ffb5429c9b04abb15 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 19 Dec 2024 15:34:54 -0300 Subject: [PATCH 02/21] Add test to validate clearOnInit config --- .../browserSuites/ready-from-cache.spec.js | 96 +++++++++++++++++-- 1 file changed, 86 insertions(+), 10 deletions(-) diff --git a/src/__tests__/browserSuites/ready-from-cache.spec.js b/src/__tests__/browserSuites/ready-from-cache.spec.js index a69dbccd4..601f34216 100644 --- a/src/__tests__/browserSuites/ready-from-cache.spec.js +++ b/src/__tests__/browserSuites/ready-from-cache.spec.js @@ -1,3 +1,5 @@ +import sinon from 'sinon'; +import { nearlyEqual } from '../testUtils'; import { getStorageHash } from '@splitsoftware/splitio-commons/src/storages/KeyBuilder'; import { SplitFactory } from '../../'; @@ -5,7 +7,6 @@ import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json'; import membershipsNicolas from '../mocks/memberships.nicolas@split.io.json'; -import { nearlyEqual } from '../testUtils'; const DEFAULT_CACHE_EXPIRATION_IN_MILLIS = 864000000; // 10 days @@ -179,7 +180,6 @@ export default function (fetchMock, assert) { readyTimeout: 0.85 }, urls: testUrls, - debug: true }); const client = splitio.client(); const client2 = splitio.client('nicolas2@split.io'); @@ -290,7 +290,6 @@ export default function (fetchMock, assert) { readyTimeout: 0.85 }, urls: testUrls, - debug: true }); const client = splitio.client(); const client2 = splitio.client('nicolas2@split.io'); @@ -410,7 +409,6 @@ export default function (fetchMock, assert) { readyTimeout: 0.85 }, urls: testUrls, - debug: true }); const client = splitio.client(); const client2 = splitio.client('nicolas2@split.io'); @@ -509,7 +507,6 @@ export default function (fetchMock, assert) { sync: { splitFilters: [{ type: 'byName', values: ['p2__split', 'p1__split'] }, { type: 'byName', values: ['p2__split', null] }] }, - debug: true }); const client = splitio.client(); const manager = splitio.manager(); @@ -555,7 +552,6 @@ export default function (fetchMock, assert) { sync: { splitFilters: [{ type: 'byName', values: ['p2__split', 'p1__split'] }, { type: 'byName', values: ['p2__split', null] }] }, - debug: true }); const client = splitio.client(); const manager = splitio.manager(); @@ -606,7 +602,6 @@ export default function (fetchMock, assert) { sync: { splitFilters: [{ type: 'byName', values: [undefined, true, 'p2__split'] }, { type: 'byPrefix', values: ['p1'] }, { type: 'byName', values: ['p2__split'] }] }, - debug: true }); const client = splitio.client(); const manager = splitio.manager(); @@ -659,7 +654,6 @@ export default function (fetchMock, assert) { sync: { splitFilters: [{ type: 'byPrefix', values: ['p2'] }, { type: 'byPrefix', values: ['p1', ''] }, { type: '', values: [] }, {}, { type: 'byPrefix' }] }, - debug: true }); const client = splitio.client(); const manager = splitio.manager(); @@ -722,7 +716,6 @@ export default function (fetchMock, assert) { }, urls: testUrls, sync: syncParam, - debug: true }); const client = splitio.client(); const manager = splitio.manager(); @@ -777,7 +770,6 @@ export default function (fetchMock, assert) { sync: { splitFilters: [{ type: 'byName', values: ['p3__split'] }, { type: 'byPrefix', values: [' p2', ' p2', ' p2', ' p2', 'no exist trim '] }, { type: 'byName', values: ['no_exist', ' no exist trim '] }] }, - debug: true }); const client = splitio.client(); const manager = splitio.manager(); @@ -796,4 +788,88 @@ export default function (fetchMock, assert) { }); }); + assert.test(async t => { // Testing clearOnInit config true + sinon.spy(console, 'log'); + + const testUrls = { + sdk: 'https://sdk.baseurl/readyFromCache_10', + events: 'https://events.baseurl/readyFromCache_10' + }; + const clearOnInitConfig = { + ...baseConfig, + storage: { + type: 'LOCALSTORAGE', + prefix: 'readyFromCache_10', + clearOnInit: true + }, + urls: testUrls, + debug: true + }; + + // Start with cached data but without lastClear item (JS SDK below 11.1.0) -> cache cleanup + localStorage.clear(); + localStorage.setItem('readyFromCache_10.SPLITIO.splits.till', 25); + localStorage.setItem('readyFromCache_10.SPLITIO.split.p1__split', JSON.stringify(splitDeclarations.p1__split)); + localStorage.setItem('readyFromCache_10.SPLITIO.split.p2__split', JSON.stringify(splitDeclarations.p2__split)); + localStorage.setItem('readyFromCache_10.SPLITIO.hash', expectedHashNullFilter); + + fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.2&since=-1', { status: 200, body: splitChangesMock1 }); + fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.2&since=1457552620999', { status: 200, body: splitChangesMock2 }); + fetchMock.get(testUrls.sdk + '/memberships/nicolas%40split.io', { status: 200, body: { ms: {} } }); + + let splitio = SplitFactory(clearOnInitConfig); + let client = splitio.client(); + let manager = splitio.manager(); + + t.true(console.log.calledWithMatch('clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache'), 'It should log a message about cleaning up cache'); + + client.once(client.Event.SDK_READY_FROM_CACHE, () => t.fail('It should not emit SDK_READY_FROM_CACHE because clearOnInit is true.')); + + await client.ready(); + t.equal(manager.names().sort().length, 32, 'active splits should be present for evaluation'); + + await splitio.destroy(); + t.equal(localStorage.getItem('readyFromCache_10.SPLITIO.splits.till'), '1457552620999', 'splits.till must correspond to the till of the last successfully fetched Splits'); + t.equal(localStorage.getItem('readyFromCache_10.SPLITIO.hash'), expectedHashNullFilter, 'Storage hash must not be changed'); + t.true(nearlyEqual(parseInt(localStorage.getItem('readyFromCache_10.SPLITIO.lastClear')), Date.now()), 'lastClear timestamp must be set'); + + // Start again with cached data and lastClear item within the last 24 hours -> no cache cleanup + console.log.resetHistory(); + fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.2&since=1457552620999', { status: 200, body: splitChangesMock2 }); + + splitio = SplitFactory(clearOnInitConfig); + client = splitio.client(); + manager = splitio.manager(); + + await new Promise(res => client.once(client.Event.SDK_READY_FROM_CACHE, res)); + + t.equal(manager.names().sort().length, 32, 'active splits should be present for evaluation'); + t.false(console.log.calledWithMatch('clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache'), 'It should log a message about cleaning up cache'); + + await splitio.destroy(); + + + // Start again with cached data and lastClear item older than 24 hours -> cache cleanup + console.log.resetHistory(); + localStorage.setItem('readyFromCache_10.SPLITIO.lastClear', Date.now() - 25 * 60 * 60 * 1000); // 25 hours ago + fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.2&since=-1', { status: 200, body: splitChangesMock1 }); + fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.2&since=1457552620999', { status: 200, body: splitChangesMock2 }); + + splitio = SplitFactory(clearOnInitConfig); + client = splitio.client(); + manager = splitio.manager(); + + client.once(client.Event.SDK_READY_FROM_CACHE, () => t.fail('It should not emit SDK_READY_FROM_CACHE because clearOnInit is true.')); + + await new Promise(res => client.once(client.Event.SDK_READY, res)); + + t.equal(manager.names().sort().length, 32, 'active splits should be present for evaluation'); + t.true(console.log.calledWithMatch('clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache'), 'It should log a message about cleaning up cache'); + + await splitio.destroy(); + + console.log.restore(); + t.end(); + }); + } From d97a03f26ab987736347a2241b1716f9d6d1dc09 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 19 Dec 2024 18:31:55 -0300 Subject: [PATCH 03/21] Prepare rc and update changelog entry --- .github/workflows/ci-cd.yml | 4 ++-- CHANGES.txt | 5 +++++ package-lock.json | 18 +++++++++--------- package.json | 4 ++-- src/settings/defaults/version.js | 2 +- ts-tests/index.ts | 4 +++- 6 files changed, 22 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index d28295fdb..352be03cc 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -58,7 +58,7 @@ jobs: run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") npm run build - name: Store assets - if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/development' || github.ref == 'refs/heads/master') }} + if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/cache_expiration' || github.ref == 'refs/heads/master') }} uses: actions/upload-artifact@v3 with: name: assets @@ -69,7 +69,7 @@ jobs: name: Upload assets runs-on: ubuntu-20.04 needs: build - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/cache_expiration' }} strategy: matrix: environment: diff --git a/CHANGES.txt b/CHANGES.txt index 7cd078dd3..a70e65d72 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,8 @@ +11.1.0 (January XX, 2025) + - Added two new configuration options for the SDK storage in browsers when using storage type `LOCALSTORAGE`: + - `storage.expirationDays` to specify the validity period of the rollout cache. + - `storage.clearOnInit` to clear the rollout cache on SDK initialization. + 11.0.3 (December 4, 2024) - Bugfixing - Updated @splitsoftware/splitio-commons package to version 2.0.2 that sanitizes the `SplitSDKMachineName` header value to avoid exceptions on HTTP/S requests when it contains non ISO-8859-1 characters (Related to issue https://github.com/splitio/javascript-client/issues/847). diff --git a/package-lock.json b/package-lock.json index a6959f97e..7da1d6319 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@splitsoftware/splitio", - "version": "11.0.3", + "version": "11.1.0-rc.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "11.0.3", + "version": "11.1.0-rc.0", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.0.2", + "@splitsoftware/splitio-commons": "2.1.0-rc.0", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", @@ -351,9 +351,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.2.tgz", - "integrity": "sha512-r2m3kwWnSuROT+7zTzhWBrM0DMRBGJNQcTyvXw8zLPPmBs/PnmAnxCy7uRpfMHOGbP9Q3Iju0bU/H5dG8svyiw==", + "version": "2.1.0-rc.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.0-rc.0.tgz", + "integrity": "sha512-5JJs9ZlJ0to15Azk243wNL22sU7U9quZDcC+8o9NHRBwnrya8euFjuzznqXmGAyyj/Gklrbohwfg+1SOmXXfQg==", "dependencies": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" @@ -7537,9 +7537,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.2.tgz", - "integrity": "sha512-r2m3kwWnSuROT+7zTzhWBrM0DMRBGJNQcTyvXw8zLPPmBs/PnmAnxCy7uRpfMHOGbP9Q3Iju0bU/H5dG8svyiw==", + "version": "2.1.0-rc.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.0-rc.0.tgz", + "integrity": "sha512-5JJs9ZlJ0to15Azk243wNL22sU7U9quZDcC+8o9NHRBwnrya8euFjuzznqXmGAyyj/Gklrbohwfg+1SOmXXfQg==", "requires": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" diff --git a/package.json b/package.json index d62fd35b1..e7953ff34 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "11.0.3", + "version": "11.1.0-rc.0", "description": "Split SDK", "files": [ "README.md", @@ -38,7 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.0.2", + "@splitsoftware/splitio-commons": "2.1.0-rc.0", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index c1fb40805..1b39f9eee 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '11.0.3'; +export const packageVersion = '11.1.0-rc.0'; diff --git a/ts-tests/index.ts b/ts-tests/index.ts index 9e9a2c32a..6e238f7d1 100644 --- a/ts-tests/index.ts +++ b/ts-tests/index.ts @@ -530,7 +530,9 @@ let fullBrowserSettings: SplitIO.IBrowserSettings = { features: mockedFeaturesMap, storage: { type: 'LOCALSTORAGE', - prefix: 'PREFIX' + prefix: 'PREFIX', + expirationDays: 1, + clearOnInit: true }, impressionListener: impressionListener, debug: true, From 7c4fc2d102902a7587244100a56ec7d5ff69563e Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 20 Dec 2024 13:25:10 -0300 Subject: [PATCH 04/21] Polishing --- .github/workflows/ci-cd.yml | 4 ++-- CHANGES.txt | 7 ++++--- src/__tests__/browserSuites/ready-from-cache.spec.js | 1 - 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 352be03cc..d28295fdb 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -58,7 +58,7 @@ jobs: run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") npm run build - name: Store assets - if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/cache_expiration' || github.ref == 'refs/heads/master') }} + if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/development' || github.ref == 'refs/heads/master') }} uses: actions/upload-artifact@v3 with: name: assets @@ -69,7 +69,7 @@ jobs: name: Upload assets runs-on: ubuntu-20.04 needs: build - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/cache_expiration' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} strategy: matrix: environment: diff --git a/CHANGES.txt b/CHANGES.txt index a70e65d72..80e117cba 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,7 +1,8 @@ 11.1.0 (January XX, 2025) - - Added two new configuration options for the SDK storage in browsers when using storage type `LOCALSTORAGE`: - - `storage.expirationDays` to specify the validity period of the rollout cache. - - `storage.clearOnInit` to clear the rollout cache on SDK initialization. + - Added two new configuration options for the SDK's `LOCALSTORAGE` storage type to control the behavior of the persisted rollout plan cache in the browser: + - `storage.expirationDays` to specify the validity period of the rollout plan cache in days. + - `storage.clearOnInit` to clear the rollout plan cache on SDK initialization. + - Updated @splitsoftware/splitio-commons package to version 2.1.0. 11.0.3 (December 4, 2024) - Bugfixing - Updated @splitsoftware/splitio-commons package to version 2.0.2 that sanitizes the `SplitSDKMachineName` header value to avoid exceptions on HTTP/S requests when it contains non ISO-8859-1 characters (Related to issue https://github.com/splitio/javascript-client/issues/847). diff --git a/src/__tests__/browserSuites/ready-from-cache.spec.js b/src/__tests__/browserSuites/ready-from-cache.spec.js index 601f34216..02fe71326 100644 --- a/src/__tests__/browserSuites/ready-from-cache.spec.js +++ b/src/__tests__/browserSuites/ready-from-cache.spec.js @@ -848,7 +848,6 @@ export default function (fetchMock, assert) { await splitio.destroy(); - // Start again with cached data and lastClear item older than 24 hours -> cache cleanup console.log.resetHistory(); localStorage.setItem('readyFromCache_10.SPLITIO.lastClear', Date.now() - 25 * 60 * 60 * 1000); // 25 hours ago From 0ab2752af9f4a5f327c543646f8341d9085cdd5f Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 2 Jan 2025 14:41:03 -0300 Subject: [PATCH 05/21] Updated SDK_READY_FROM_CACHE event when using the `LOCALSTORAGE` storage type to be emitted alongside the SDK_READY event --- CHANGES.txt | 1 + package-lock.json | 14 +-- package.json | 2 +- .../browserSuites/ready-from-cache.spec.js | 90 +++++++++---------- 4 files changed, 53 insertions(+), 54 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 80e117cba..26940fabc 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,7 @@ - Added two new configuration options for the SDK's `LOCALSTORAGE` storage type to control the behavior of the persisted rollout plan cache in the browser: - `storage.expirationDays` to specify the validity period of the rollout plan cache in days. - `storage.clearOnInit` to clear the rollout plan cache on SDK initialization. + - Updated SDK_READY_FROM_CACHE event when using the `LOCALSTORAGE` storage type to be emitted alongside the SDK_READY event if it has not already been emitted. - Updated @splitsoftware/splitio-commons package to version 2.1.0. 11.0.3 (December 4, 2024) diff --git a/package-lock.json b/package-lock.json index 7da1d6319..3a93d8d8c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "11.1.0-rc.0", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.1.0-rc.0", + "@splitsoftware/splitio-commons": "2.1.0-rc.1", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", @@ -351,9 +351,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.1.0-rc.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.0-rc.0.tgz", - "integrity": "sha512-5JJs9ZlJ0to15Azk243wNL22sU7U9quZDcC+8o9NHRBwnrya8euFjuzznqXmGAyyj/Gklrbohwfg+1SOmXXfQg==", + "version": "2.1.0-rc.1", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.0-rc.1.tgz", + "integrity": "sha512-IMNbgldnCQMJpWqkJbkhtC3ZIiAC3MNhpj+vVAWTJgvf3Fwz5Wk4aJAHGIAqhi5Mka86rflTC7uxmBTBXfECxw==", "dependencies": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" @@ -7537,9 +7537,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.1.0-rc.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.0-rc.0.tgz", - "integrity": "sha512-5JJs9ZlJ0to15Azk243wNL22sU7U9quZDcC+8o9NHRBwnrya8euFjuzznqXmGAyyj/Gklrbohwfg+1SOmXXfQg==", + "version": "2.1.0-rc.1", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.0-rc.1.tgz", + "integrity": "sha512-IMNbgldnCQMJpWqkJbkhtC3ZIiAC3MNhpj+vVAWTJgvf3Fwz5Wk4aJAHGIAqhi5Mka86rflTC7uxmBTBXfECxw==", "requires": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" diff --git a/package.json b/package.json index e7953ff34..d0db02a75 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.1.0-rc.0", + "@splitsoftware/splitio-commons": "2.1.0-rc.1", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", diff --git a/src/__tests__/browserSuites/ready-from-cache.spec.js b/src/__tests__/browserSuites/ready-from-cache.spec.js index 02fe71326..97b3ce8c6 100644 --- a/src/__tests__/browserSuites/ready-from-cache.spec.js +++ b/src/__tests__/browserSuites/ready-from-cache.spec.js @@ -95,7 +95,7 @@ export default function (fetchMock, assert) { events: 'https://events.baseurl/readyFromCacheEmpty' }; localStorage.clear(); - t.plan(3); + t.plan(4); fetchMock.get(testUrls.sdk + '/splitChanges?s=1.2&since=-1', { status: 200, body: splitChangesMock1 }); fetchMock.get(testUrls.sdk + '/splitChanges?s=1.2&since=1457552620999', { status: 200, body: splitChangesMock2 }); @@ -124,18 +124,17 @@ export default function (fetchMock, assert) { t.end(); }); client.once(client.Event.SDK_READY_FROM_CACHE, () => { - t.fail('It should not emit SDK_READY_FROM_CACHE if there is no cache.'); - t.end(); + t.true(client.__getStatus().isReady, 'Client should emit SDK_READY_FROM_CACHE alongside SDK_READY'); }); client.on(client.Event.SDK_READY, () => { - t.pass('It should emit SDK_READY alone, since there was no cache.'); + t.true(client.__getStatus().isReadyFromCache, 'Client should emit SDK_READY and it should be ready from cache'); }); client2.on(client.Event.SDK_READY, () => { - t.pass('It should emit SDK_READY alone, since there was no cache.'); + t.true(client2.__getStatus().isReadyFromCache, 'Non-default client should emit SDK_READY and it should be ready from cache'); }); client3.on(client.Event.SDK_READY, () => { - t.pass('It should emit SDK_READY alone, since there was no cache.'); + t.true(client2.__getStatus().isReadyFromCache, 'Non-default client should emit SDK_READY and it should be ready from cache'); }); }); @@ -148,17 +147,17 @@ export default function (fetchMock, assert) { localStorage.clear(); t.plan(12 * 2 + 3); - fetchMock.get(testUrls.sdk + '/splitChanges?s=1.2&since=25', function () { + fetchMock.get(testUrls.sdk + '/splitChanges?s=1.2&since=25', () => { return new Promise(res => { setTimeout(() => res({ status: 200, body: { ...splitChangesMock1, since: 25 }, headers: {} }), 200); }); // 400ms is how long it'll take to reply with Splits, no SDK_READY should be emitted before that. }); fetchMock.get(testUrls.sdk + '/splitChanges?s=1.2&since=1457552620999', { status: 200, body: splitChangesMock2 }); - fetchMock.get(testUrls.sdk + '/memberships/nicolas%40split.io', function () { + fetchMock.get(testUrls.sdk + '/memberships/nicolas%40split.io', () => { return new Promise(res => { setTimeout(() => res({ status: 200, body: membershipsNicolas, headers: {} }), 400); }); // First client gets segments before splits. No segment cache loading (yet) }); - fetchMock.get(testUrls.sdk + '/memberships/nicolas2%40split.io', function () { + fetchMock.get(testUrls.sdk + '/memberships/nicolas2%40split.io', () => { return new Promise(res => { setTimeout(() => res({ status: 200, body: { 'ms': {} }, headers: {} }), 700); }); // Second client gets segments after 700ms }); - fetchMock.get(testUrls.sdk + '/memberships/nicolas3%40split.io', function () { + fetchMock.get(testUrls.sdk + '/memberships/nicolas3%40split.io', () => { return new Promise(res => { setTimeout(() => res({ status: 200, body: { 'ms': {} }, headers: {} }), 1000); }); // Third client memberships will come after 1s }); fetchMock.postOnce(testUrls.events + '/testImpressions/bulk', 200); @@ -255,18 +254,18 @@ export default function (fetchMock, assert) { localStorage.clear(); t.plan(12 * 2 + 5); - fetchMock.get(testUrls.sdk + '/splitChanges?s=1.2&since=25', function () { + fetchMock.get(testUrls.sdk + '/splitChanges?s=1.2&since=25', () => { t.equal(localStorage.getItem('readyFromCache_3.SPLITIO.split.always_on'), alwaysOnSplitInverted, 'feature flags must not be cleaned from cache'); return new Promise(res => { setTimeout(() => res({ status: 200, body: { ...splitChangesMock1, since: 25 }, headers: {} }), 200); }); // 400ms is how long it'll take to reply with Splits, no SDK_READY should be emitted before that. }); fetchMock.get(testUrls.sdk + '/splitChanges?s=1.2&since=1457552620999', { status: 200, body: splitChangesMock2 }); - fetchMock.get(testUrls.sdk + '/memberships/nicolas%40split.io', function () { + fetchMock.get(testUrls.sdk + '/memberships/nicolas%40split.io', () => { return new Promise(res => { setTimeout(() => res({ status: 200, body: membershipsNicolas, headers: {} }), 400); }); // First client gets segments before splits. No segment cache loading (yet) }); - fetchMock.get(testUrls.sdk + '/memberships/nicolas2%40split.io', function () { + fetchMock.get(testUrls.sdk + '/memberships/nicolas2%40split.io', () => { return new Promise(res => { setTimeout(() => res({ status: 200, body: { 'ms': {} }, headers: {} }), 700); }); // Second client gets segments after 700ms }); - fetchMock.get(testUrls.sdk + '/memberships/nicolas3%40split.io', function () { + fetchMock.get(testUrls.sdk + '/memberships/nicolas3%40split.io', () => { return new Promise(res => { setTimeout(() => res({ status: 200, body: { 'ms': {} }, headers: {} }), 1000); }); // Third client memberships will come after 1s }); fetchMock.get(testUrls.sdk + '/memberships/nicolas4%40split.io', { 'ms': {} }); @@ -365,13 +364,15 @@ export default function (fetchMock, assert) { }); assert.test(t => { // Testing when we start with cached data but expired (lastUpdate timestamp lower than custom (1) expirationDays ago) + const CLIENT_READY_MS = 400, CLIENT2_READY_MS = 700, CLIENT3_READY_MS = 1000; + const testUrls = { sdk: 'https://sdk.baseurl/readyFromCacheWithData4', events: 'https://events.baseurl/readyFromCacheWithData4' }; localStorage.clear(); - fetchMock.get(testUrls.sdk + '/splitChanges?s=1.2&since=-1', function () { + fetchMock.get(testUrls.sdk + '/splitChanges?s=1.2&since=-1', () => { t.equal(localStorage.getItem('some_user_item'), 'user_item', 'user items at localStorage must not be changed'); t.equal(localStorage.getItem('readyFromCache_4.SPLITIO.hash'), expectedHashNullFilter, 'storage hash must not be changed'); t.true(nearlyEqual(parseInt(localStorage.getItem('readyFromCache_4.SPLITIO.lastClear'), 10), Date.now()), 'storage lastClear timestamp must be updated'); @@ -379,14 +380,14 @@ export default function (fetchMock, assert) { return { status: 200, body: splitChangesMock1 }; }); fetchMock.get(testUrls.sdk + '/splitChanges?s=1.2&since=1457552620999', { status: 200, body: splitChangesMock2 }); - fetchMock.get(testUrls.sdk + '/memberships/nicolas%40split.io', function () { - return new Promise(res => { setTimeout(() => res({ status: 200, body: membershipsNicolas, headers: {} }), 400); }); // First client gets segments before splits. No segment cache loading (yet) + fetchMock.get(testUrls.sdk + '/memberships/nicolas%40split.io', () => { + return new Promise(res => { setTimeout(() => res({ status: 200, body: membershipsNicolas, headers: {} }), CLIENT_READY_MS); }); // First client gets segments before splits. No segment cache loading (yet) }); - fetchMock.get(testUrls.sdk + '/memberships/nicolas2%40split.io', function () { - return new Promise(res => { setTimeout(() => res({ status: 200, body: { 'ms': {} }, headers: {} }), 700); }); // Second client gets segments after 700ms + fetchMock.get(testUrls.sdk + '/memberships/nicolas2%40split.io', () => { + return new Promise(res => { setTimeout(() => res({ status: 200, body: { 'ms': {} }, headers: {} }), CLIENT2_READY_MS); }); // Second client gets segments after 700ms }); - fetchMock.get(testUrls.sdk + '/memberships/nicolas3%40split.io', function () { - return new Promise(res => { setTimeout(() => res({ status: 200, body: { 'ms': {} }, headers: {} }), 1000); }); // Third client memberships will come after 1s + fetchMock.get(testUrls.sdk + '/memberships/nicolas3%40split.io', () => { + return new Promise(res => { setTimeout(() => res({ status: 200, body: { 'ms': {} }, headers: {} }), CLIENT3_READY_MS); }); // Third client memberships will come after 1s }); fetchMock.postOnce(testUrls.events + '/testImpressions/bulk', 200); fetchMock.postOnce(testUrls.events + '/testImpressions/count', 200); @@ -423,37 +424,34 @@ export default function (fetchMock, assert) { }); client.once(client.Event.SDK_READY_FROM_CACHE, () => { - t.fail('It should not emit SDK_READY_FROM_CACHE if there is expired cache.'); - t.end(); + t.true(nearlyEqual(Date.now() - startTime, CLIENT_READY_MS), 'It should emit SDK_READY_FROM_CACHE alongside SDK_READY'); }); client2.once(client2.Event.SDK_READY_FROM_CACHE, () => { - t.fail('It should not emit SDK_READY_FROM_CACHE if there is expired cache.'); - t.end(); + t.true(nearlyEqual(Date.now() - startTime, CLIENT2_READY_MS), 'It should emit SDK_READY_FROM_CACHE alongside SDK_READY'); }); client3.once(client3.Event.SDK_READY_FROM_CACHE, () => { - t.fail('It should not emit SDK_READY_FROM_CACHE if there is expired cache.'); - t.end(); + t.true(nearlyEqual(Date.now() - startTime, CLIENT3_READY_MS), 'It should emit SDK_READY_FROM_CACHE alongside SDK_READY'); }); client.on(client.Event.SDK_READY, () => { - t.true(Date.now() - startTime >= 400, 'It should emit SDK_READY after syncing with the cloud.'); + t.true(nearlyEqual(Date.now() - startTime, CLIENT_READY_MS), 'It should emit SDK_READY after syncing with the cloud.'); t.equal(client.getTreatment('always_on'), 'on', 'It should evaluate treatments with updated data after syncing with the cloud.'); }); client.ready().then(() => { - t.true(Date.now() - startTime >= 400, 'It should resolve ready promise after syncing with the cloud.'); + t.true(nearlyEqual(Date.now() - startTime, CLIENT_READY_MS), 'It should resolve ready promise after syncing with the cloud.'); t.equal(client.getTreatment('always_on'), 'on', 'It should evaluate treatments with updated data after syncing with the cloud.'); }); client2.on(client2.Event.SDK_READY, () => { - t.true(Date.now() - startTime >= 700, 'It should emit SDK_READY after syncing with the cloud.'); + t.true(nearlyEqual(Date.now() - startTime, CLIENT2_READY_MS), 'It should emit SDK_READY after syncing with the cloud.'); t.equal(client2.getTreatment('always_on'), 'on', 'It should evaluate treatments with updated data after syncing with the cloud.'); }); client2.ready().then(() => { - t.true(Date.now() - startTime >= 700, 'It should resolve ready promise after syncing with the cloud.'); + t.true(nearlyEqual(Date.now() - startTime, CLIENT2_READY_MS), 'It should resolve ready promise after syncing with the cloud.'); t.equal(client2.getTreatment('always_on'), 'on', 'It should evaluate treatments with updated data after syncing with the cloud.'); }); client3.on(client3.Event.SDK_READY, () => { client3.ready().then(() => { - t.true(Date.now() - startTime >= 1000, 'It should resolve ready promise after syncing with the cloud.'); + t.true(nearlyEqual(Date.now() - startTime, CLIENT3_READY_MS), 'It should resolve ready promise after syncing with the cloud.'); t.equal(client3.getTreatment('always_on'), 'on', 'It should evaluate treatments with updated data after syncing with the cloud.'); // Last cb: destroy clients and check that localstorage has the expected items @@ -486,7 +484,7 @@ export default function (fetchMock, assert) { events: 'https://events.baseurl/readyFromCache_5' }; localStorage.clear(); - t.plan(7); + t.plan(8); fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.2&since=-1&names=p1__split,p2__split', { status: 200, body: { splits: [splitDeclarations.p1__split, splitDeclarations.p2__split], since: -1, till: 1457552620999 } }, { delay: 10 }); // short delay to let emit SDK_READY_FROM_CACHE fetchMock.getOnce(testUrls.sdk + '/memberships/nicolas%40split.io', { status: 200, body: { ms: {} } }); @@ -512,8 +510,7 @@ export default function (fetchMock, assert) { const manager = splitio.manager(); client.once(client.Event.SDK_READY_FROM_CACHE, () => { - t.fail('It should not emit SDK_READY_FROM_CACHE because localStorage is cleaned and there isn\'t cached feature flags'); - t.end(); + t.true(client.__getStatus().isReady, 'Client should emit SDK_READY_FROM_CACHE alongside SDK_READY'); }); client.once(client.Event.SDK_READY, () => { @@ -537,7 +534,7 @@ export default function (fetchMock, assert) { events: 'https://events.baseurl/readyFromCache_5B' }; localStorage.clear(); - t.plan(5); + t.plan(6); fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.2&since=-1&names=p1__split,p2__split', { status: 200, body: { splits: [splitDeclarations.p1__split, splitDeclarations.p2__split], since: -1, till: 1457552620999 } }, { delay: 10 }); // short delay to let emit SDK_READY_FROM_CACHE fetchMock.getOnce(testUrls.sdk + '/memberships/nicolas%40split.io', { status: 200, body: { ms: {} } }); @@ -557,8 +554,7 @@ export default function (fetchMock, assert) { const manager = splitio.manager(); client.once(client.Event.SDK_READY_FROM_CACHE, () => { - t.fail('It should not emit SDK_READY_FROM_CACHE if cache is empty.'); - t.end(); + t.true(client.__getStatus().isReady, 'Client should emit SDK_READY_FROM_CACHE alongside SDK_READY'); }); client.once(client.Event.SDK_READY, () => { @@ -630,7 +626,7 @@ export default function (fetchMock, assert) { events: 'https://events.baseurl/readyFromCache_7' }; localStorage.clear(); - t.plan(6); + t.plan(7); fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.2&since=-1&prefixes=p1,p2', { status: 200, body: { splits: [splitDeclarations.p1__split, splitDeclarations.p2__split], since: -1, till: 1457552620999 } }, { delay: 10 }); // short delay to let emit SDK_READY_FROM_CACHE fetchMock.getOnce(testUrls.sdk + '/memberships/nicolas%40split.io', { status: 200, body: { ms: {} } }); @@ -659,8 +655,7 @@ export default function (fetchMock, assert) { const manager = splitio.manager(); client.once(client.Event.SDK_READY_FROM_CACHE, () => { - t.fail('It should not emit SDK_READY_FROM_CACHE if cache has expired.'); - t.end(); + t.true(client.__getStatus().isReady, 'Client should emit SDK_READY_FROM_CACHE alongside SDK_READY'); }); client.once(client.Event.SDK_READY, () => { @@ -696,7 +691,7 @@ export default function (fetchMock, assert) { events: 'https://events.baseurl/readyFromCache_8' }; localStorage.clear(); - t.plan(7); + t.plan(8); fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.2&since=-1', { status: 200, body: { splits: [splitDeclarations.p1__split, splitDeclarations.p2__split, splitDeclarations.p3__split], since: -1, till: 1457552620999 } }, { delay: 10 }); // short delay to let emit SDK_READY_FROM_CACHE fetchMock.getOnce(testUrls.sdk + '/memberships/nicolas%40split.io', { status: 200, body: { ms: {} } }); @@ -721,8 +716,7 @@ export default function (fetchMock, assert) { const manager = splitio.manager(); client.once(client.Event.SDK_READY_FROM_CACHE, () => { - t.fail('It should not emit SDK_READY_FROM_CACHE because all feature flags were removed from cache since the filter query changed.'); - t.end(); + t.true(client.__getStatus().isReady, 'Client should emit SDK_READY_FROM_CACHE alongside SDK_READY'); }); client.once(client.Event.SDK_READY, () => { @@ -823,7 +817,9 @@ export default function (fetchMock, assert) { t.true(console.log.calledWithMatch('clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache'), 'It should log a message about cleaning up cache'); - client.once(client.Event.SDK_READY_FROM_CACHE, () => t.fail('It should not emit SDK_READY_FROM_CACHE because clearOnInit is true.')); + client.once(client.Event.SDK_READY_FROM_CACHE, () => { + t.true(client.__getStatus().isReady, 'Client should emit SDK_READY_FROM_CACHE alongside SDK_READY, because clearOnInit is true'); + }); await client.ready(); t.equal(manager.names().sort().length, 32, 'active splits should be present for evaluation'); @@ -858,7 +854,9 @@ export default function (fetchMock, assert) { client = splitio.client(); manager = splitio.manager(); - client.once(client.Event.SDK_READY_FROM_CACHE, () => t.fail('It should not emit SDK_READY_FROM_CACHE because clearOnInit is true.')); + client.once(client.Event.SDK_READY_FROM_CACHE, () => { + t.true(client.__getStatus().isReady, 'Client should emit SDK_READY_FROM_CACHE alongside SDK_READY, because clearOnInit is true'); + }); await new Promise(res => client.once(client.Event.SDK_READY, res)); From 957cbdc8383386f7549b204e2c480c48a75a5c30 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 3 Jan 2025 15:26:42 -0300 Subject: [PATCH 06/21] rc --- .github/workflows/ci-cd.yml | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- src/settings/defaults/version.js | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index d28295fdb..ff8b69e67 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -58,7 +58,7 @@ jobs: run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") npm run build - name: Store assets - if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/development' || github.ref == 'refs/heads/master') }} + if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/SDKS-9171_sdk_ready_from_cache' || github.ref == 'refs/heads/master') }} uses: actions/upload-artifact@v3 with: name: assets @@ -69,7 +69,7 @@ jobs: name: Upload assets runs-on: ubuntu-20.04 needs: build - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/SDKS-9171_sdk_ready_from_cache' }} strategy: matrix: environment: diff --git a/package-lock.json b/package-lock.json index 3a93d8d8c..948862062 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@splitsoftware/splitio", - "version": "11.1.0-rc.0", + "version": "11.1.0-rc.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "11.1.0-rc.0", + "version": "11.1.0-rc.1", "license": "Apache-2.0", "dependencies": { "@splitsoftware/splitio-commons": "2.1.0-rc.1", diff --git a/package.json b/package.json index d0db02a75..91b55e7f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "11.1.0-rc.0", + "version": "11.1.0-rc.1", "description": "Split SDK", "files": [ "README.md", diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index 1b39f9eee..9dba11199 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '11.1.0-rc.0'; +export const packageVersion = '11.1.0-rc.1'; From b463726113b13d63ea06f3dae0da41fdada04687 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Mon, 13 Jan 2025 14:28:47 -0300 Subject: [PATCH 07/21] Fix tests --- package-lock.json | 14 ++++++------- package.json | 2 +- .../browserSuites/impressions.spec.js | 2 +- src/__tests__/browserSuites/manager.spec.js | 2 +- src/__tests__/consumer/node_redis.spec.js | 2 +- src/__tests__/mocks/redis-commands.txt | 4 ++-- .../mocks/splitchanges.since.-1.json | 6 +++--- src/__tests__/nodeSuites/impressions.spec.js | 2 +- src/__tests__/nodeSuites/manager.spec.js | 2 +- src/__tests__/offline/browser.spec.js | 6 +++--- src/__tests__/offline/node.spec.js | 20 +++++++++---------- ts-tests/index.ts | 2 +- 12 files changed, 32 insertions(+), 32 deletions(-) diff --git a/package-lock.json b/package-lock.json index 597797e60..fc0d34e51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "11.1.0-rc.1", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.0.3-rc.0", + "@splitsoftware/splitio-commons": "2.1.0-rc.2", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", @@ -351,9 +351,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.0.3-rc.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.3-rc.0.tgz", - "integrity": "sha512-18Zpm5rXH+Cn3lR4K6Np9os3XK6cH9KUsM7a3MOdBVoVMZPr6PzVuIf4Eet6vbVDGKbk9h0aYrAA2Tm7DU4dWg==", + "version": "2.1.0-rc.2", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.0-rc.2.tgz", + "integrity": "sha512-5zn+w6bw9CdXnx3chMzcLqpZ7rghNJ1iYdwKTwYPUD5NvCac7og+A3aKdvbxFG+zm773e3hffJd4EharfoWwog==", "dependencies": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" @@ -7537,9 +7537,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.0.3-rc.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.3-rc.0.tgz", - "integrity": "sha512-18Zpm5rXH+Cn3lR4K6Np9os3XK6cH9KUsM7a3MOdBVoVMZPr6PzVuIf4Eet6vbVDGKbk9h0aYrAA2Tm7DU4dWg==", + "version": "2.1.0-rc.2", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.0-rc.2.tgz", + "integrity": "sha512-5zn+w6bw9CdXnx3chMzcLqpZ7rghNJ1iYdwKTwYPUD5NvCac7og+A3aKdvbxFG+zm773e3hffJd4EharfoWwog==", "requires": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" diff --git a/package.json b/package.json index b45c21e09..3c776cc02 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.0.3-rc.0", + "@splitsoftware/splitio-commons": "2.1.0-rc.2", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", diff --git a/src/__tests__/browserSuites/impressions.spec.js b/src/__tests__/browserSuites/impressions.spec.js index 7c72df87d..33e60106a 100644 --- a/src/__tests__/browserSuites/impressions.spec.js +++ b/src/__tests__/browserSuites/impressions.spec.js @@ -49,7 +49,7 @@ export default function (fetchMock, assert) { const assertPayload = req => { const resp = JSON.parse(req.body); - assert.equal(resp.length, 2, 'We performed evaluations for 3 features, but one with `trackImpressions` false, so we should have 2 items total'); + assert.equal(resp.length, 2, 'We performed evaluations for 3 features, but one with `impressionsDisabled` true, so we should have 2 items total'); const dependencyChildImpr = resp.filter(e => e.f === 'hierarchical_splits_test')[0]; const splitWithConfigImpr = resp.filter(e => e.f === 'split_with_config')[0]; diff --git a/src/__tests__/browserSuites/manager.spec.js b/src/__tests__/browserSuites/manager.spec.js index c31aebeeb..9c64cc52c 100644 --- a/src/__tests__/browserSuites/manager.spec.js +++ b/src/__tests__/browserSuites/manager.spec.js @@ -42,7 +42,7 @@ export default async function (settings, fetchMock, assert) { 'configs': mockSplits.splits[index].configurations || {}, 'sets': mockSplits.splits[index].sets || [], 'defaultTreatment': mockSplits.splits[index].defaultTreatment, - 'trackImpressions': true + 'impressionsDisabled': false }); assert.equal(manager.split('non_existent'), null, 'Trying to get a manager.split() of a Split that does not exist returns null.'); diff --git a/src/__tests__/consumer/node_redis.spec.js b/src/__tests__/consumer/node_redis.spec.js index 081c1dcdb..25f1809fb 100644 --- a/src/__tests__/consumer/node_redis.spec.js +++ b/src/__tests__/consumer/node_redis.spec.js @@ -61,7 +61,7 @@ const expectedImpressionCount = [ ]; const expectedSplitName = 'hierarchical_splits_testing_on'; -const expectedSplitView = { name: 'hierarchical_splits_testing_on', trafficType: 'user', killed: false, changeNumber: 1487277320548, treatments: ['on', 'off'], configs: {}, sets: [], defaultTreatment: 'off', trackImpressions: true }; +const expectedSplitView = { name: 'hierarchical_splits_testing_on', trafficType: 'user', killed: false, changeNumber: 1487277320548, treatments: ['on', 'off'], configs: {}, sets: [], defaultTreatment: 'off', impressionsDisabled: false }; const MOCKS = { '': 'redis-commands', diff --git a/src/__tests__/mocks/redis-commands.txt b/src/__tests__/mocks/redis-commands.txt index a1e68b7e8..9c87b56e0 100644 --- a/src/__tests__/mocks/redis-commands.txt +++ b/src/__tests__/mocks/redis-commands.txt @@ -21,7 +21,7 @@ SET 'REDIS_NODE_UT.SPLITIO.split.always-off' '{"changeNumber":1491519038393, SET 'REDIS_NODE_UT.SPLITIO.split.always-on' '{"changeNumber":1487277320548,"trafficTypeName":"user","name":"always-on","seed":1684183541,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}' SET 'REDIS_NODE_UT.SPLITIO.split.always-o.n-with-config' '{"changeNumber":1487277320548,"trafficTypeName":"user","name":"always-o.n-with-config","seed":1684183541,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"o.n","size":100},{"treatment":"off","size":0}],"label":"in segment all"}],"configurations":{"o.n":"{\"color\":\"brown\"}"}}' SET 'REDIS_NODE_UT.SPLITIO.split.hierarchical_splits_testing_off' '{"changeNumber":1487277320548,"trafficTypeName":"user","name":"hierarchical_splits_testing_off","seed":1684183541,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}},{"keySelector":{"trafficType":"user","attribute":""},"dependencyMatcherData":{"split":"always-on","treatments":["off"]},"matcherType":"IN_SPLIT_TREATMENT","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":null,"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}' -SET 'REDIS_NODE_UT.SPLITIO.split.hierarchical_splits_testing_on' '{"changeNumber":1487277320548,"trafficTypeName":"user","name":"hierarchical_splits_testing_on","trackImpressions":true,"seed":1684183541,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}},{"keySelector":{"trafficType":"user","attribute":""},"dependencyMatcherData":{"split":"always-on","treatments":["on"]},"matcherType":"IN_SPLIT_TREATMENT","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":null,"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}' +SET 'REDIS_NODE_UT.SPLITIO.split.hierarchical_splits_testing_on' '{"changeNumber":1487277320548,"trafficTypeName":"user","name":"hierarchical_splits_testing_on","impressionsDisabled":false,"seed":1684183541,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}},{"keySelector":{"trafficType":"user","attribute":""},"dependencyMatcherData":{"split":"always-on","treatments":["on"]},"matcherType":"IN_SPLIT_TREATMENT","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":null,"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}' SET 'REDIS_NODE_UT.SPLITIO.split.hierarchical_splits_testing_on_negated' '{"changeNumber":1487277320548,"trafficTypeName":"user","name":"hierarchical_splits_testing_on","seed":1684183541,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":true,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}},{"keySelector":{"trafficType":"user","attribute":""},"dependencyMatcherData":{"split":"always-on","treatments":["on"]},"matcherType":"IN_SPLIT_TREATMENT","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":null,"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}' SET 'REDIS_NODE_UT.SPLITIO.split.labels' '{"changeNumber":1492023661334,"trafficTypeName":"user","name":"labels","seed":-1240661267,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}},{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"IN_SEGMENT","negate":false,"userDefinedSegmentMatcherData":{"segmentName":"demo"},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}},{"keySelector":{"trafficType":"user","attribute":"n"},"matcherType":"EQUAL_TO","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"NUMBER","value":123},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":0},{"treatment":"off","size":100}],"label":"in segment all and in segment demo and n = 123"}]}' SET 'REDIS_NODE_UT.SPLITIO.split.nico_not' '{"changeNumber":1489412422181,"trafficTypeName":"user","name":"nico_not","seed":-788702424,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"IN_SEGMENT","negate":false,"userDefinedSegmentMatcherData":{"segmentName":"qa"},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":0},{"treatment":"off","size":100}],"label":"in segment qa"}]}' @@ -39,4 +39,4 @@ SET 'REDIS_NODE_UT.SPLITIO.split.testing_traffic_type' '{"changeNumber":1489 SET 'REDIS_NODE_UT.SPLITIO.split.testing_traffic_types' '{"changeNumber":1490974465415,"trafficTypeName":"machine","name":"testing_traffic_types","seed":475616886,"status":"ACTIVE","killed":false,"defaultTreatment":"on","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"","attribute":""},"matcherType":"WHITELIST","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":["sarasa"]},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100}],"label":"whitelisted"},{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"","attribute":""},"matcherType":"WHITELIST","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":["excluded"]},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"off","size":100}],"label":"whitelisted"},{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}},{"keySelector":{"trafficType":"machine","attribute":""},"matcherType":"IN_SEGMENT","negate":false,"userDefinedSegmentMatcherData":{"segmentName":"testing_traffic_type"},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":0},{"treatment":"off","size":100}],"label":"in segment all and in segment testing_traffic_type"}]}' SET 'REDIS_NODE_UT.SPLITIO.split.traffic_allocation_testing' '{"changeNumber":1490974123779,"trafficTypeName":"user","name":"traffic_allocation_testing","seed":1716284102,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}' SET 'REDIS_NODE_UT.SPLITIO.splits.till' 1492723024413 -SET 'REDIS_NODE_UT.SPLITIO.split.always-on-track-impressions-false' '{"changeNumber":1487277320548,"trafficTypeName":"user","name":"always-on-track-impressions-false","trackImpressions":false,"seed":1684183541,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}' +SET 'REDIS_NODE_UT.SPLITIO.split.always-on-track-impressions-false' '{"changeNumber":1487277320548,"trafficTypeName":"user","name":"always-on-track-impressions-false","impressionsDisabled":true,"seed":1684183541,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}' diff --git a/src/__tests__/mocks/splitchanges.since.-1.json b/src/__tests__/mocks/splitchanges.since.-1.json index c31ac7e8b..372b030b8 100644 --- a/src/__tests__/mocks/splitchanges.since.-1.json +++ b/src/__tests__/mocks/splitchanges.since.-1.json @@ -1265,7 +1265,7 @@ "trafficTypeId": null, "trafficTypeName": null, "name": "hierarchical_splits_test", - "trackImpressions": true, + "impressionsDisabled": false, "seed": 1276793945, "changeNumber": 2828282828, "status": "ACTIVE", @@ -1388,7 +1388,7 @@ "trafficTypeId": null, "trafficTypeName": null, "name": "always_on_track_impressions_false", - "trackImpressions": false, + "impressionsDisabled": true, "seed": -790401604, "status": "ACTIVE", "killed": false, @@ -1466,7 +1466,7 @@ { "trafficTypeName": null, "name": "split_with_config", - "trackImpressions": true, + "impressionsDisabled": false, "algo": 2, "seed": -1222652064, "trafficAllocation": 100, diff --git a/src/__tests__/nodeSuites/impressions.spec.js b/src/__tests__/nodeSuites/impressions.spec.js index ef96a537b..e7615140c 100644 --- a/src/__tests__/nodeSuites/impressions.spec.js +++ b/src/__tests__/nodeSuites/impressions.spec.js @@ -49,7 +49,7 @@ export default async function (key, fetchMock, assert) { assert.equal(opts.headers.SplitSDKImpressionsMode, OPTIMIZED); const data = JSON.parse(opts.body); - assert.equal(data.length, 3, 'We performed evaluations for 4 features, but one with `trackImpressions` false, so we should have 3 items total.'); + assert.equal(data.length, 3, 'We performed evaluations for 4 features, but one with `impressionsDisabled` true, so we should have 3 items total.'); // finding these validate the feature names collection too const dependencyChildImpr = data.filter(e => e.f === 'hierarchical_splits_test')[0]; diff --git a/src/__tests__/nodeSuites/manager.spec.js b/src/__tests__/nodeSuites/manager.spec.js index 82588949c..869d65e3b 100644 --- a/src/__tests__/nodeSuites/manager.spec.js +++ b/src/__tests__/nodeSuites/manager.spec.js @@ -41,7 +41,7 @@ export default async function (settings, fetchMock, assert) { 'configs': mockSplits.splits[index].configurations || {}, 'sets': mockSplits.splits[index].sets || [], 'defaultTreatment': mockSplits.splits[index].defaultTreatment, - 'trackImpressions': true + 'impressionsDisabled': false }); assert.equal(manager.split('non_existent'), null, 'Trying to get a manager.split() of a Split that does not exist returns null.'); diff --git a/src/__tests__/offline/browser.spec.js b/src/__tests__/offline/browser.spec.js index 81bc3efd3..4411914cf 100644 --- a/src/__tests__/offline/browser.spec.js +++ b/src/__tests__/offline/browser.spec.js @@ -168,10 +168,10 @@ tape('Browser offline mode', function (assert) { // Manager tests const expectedSplitView1 = { - name: 'testing_split', trafficType: 'localhost', killed: false, changeNumber: 0, treatments: ['on'], configs: {}, defaultTreatment: 'control', sets: [], trackImpressions: true + name: 'testing_split', trafficType: 'localhost', killed: false, changeNumber: 0, treatments: ['on'], configs: {}, defaultTreatment: 'control', sets: [], impressionsDisabled: false }; const expectedSplitView2 = { - name: 'testing_split_with_config', trafficType: 'localhost', killed: false, changeNumber: 0, treatments: ['off'], configs: { off: '{ "color": "blue" }' }, defaultTreatment: 'control', sets: [], trackImpressions: true + name: 'testing_split_with_config', trafficType: 'localhost', killed: false, changeNumber: 0, treatments: ['off'], configs: { off: '{ "color": "blue" }' }, defaultTreatment: 'control', sets: [], impressionsDisabled: false }; assert.deepEqual(manager.names(), ['testing_split', 'testing_split_with_config']); assert.deepEqual(manager.split('testing_split'), expectedSplitView1); @@ -282,7 +282,7 @@ tape('Browser offline mode', function (assert) { // Manager tests const expectedSplitView3 = { - name: 'testing_split_with_config', trafficType: 'localhost', killed: false, changeNumber: 0, treatments: ['nope'], configs: {}, defaultTreatment: 'control', sets: [], trackImpressions: true + name: 'testing_split_with_config', trafficType: 'localhost', killed: false, changeNumber: 0, treatments: ['nope'], configs: {}, defaultTreatment: 'control', sets: [], impressionsDisabled: false }; assert.deepEqual(manager.names(), ['testing_split', 'testing_split_2', 'testing_split_3', 'testing_split_with_config']); assert.deepEqual(manager.split('testing_split'), expectedSplitView1); diff --git a/src/__tests__/offline/node.spec.js b/src/__tests__/offline/node.spec.js index 3e3166b6c..cbc6e40d3 100644 --- a/src/__tests__/offline/node.spec.js +++ b/src/__tests__/offline/node.spec.js @@ -250,17 +250,17 @@ function ManagerDotSplitTests(assert) { const expectedView1 = { name: 'testing_split', changeNumber: 0, killed: false, trafficType: 'localhost', treatments: ['on'], configs: {}, defaultTreatment: 'control', - sets: [], trackImpressions: true + sets: [], impressionsDisabled: false }; const expectedView2 = { name: 'testing_split2', changeNumber: 0, killed: false, trafficType: 'localhost', treatments: ['off'], configs: {}, defaultTreatment: 'control', - sets: [], trackImpressions: true + sets: [], impressionsDisabled: false }; const expectedView3 = { name: 'testing_split3', changeNumber: 0, killed: false, trafficType: 'localhost', treatments: ['custom_treatment'], configs: {}, defaultTreatment: 'control', - sets: [], trackImpressions: true + sets: [], impressionsDisabled: false }; assert.deepEqual(manager.split('testing_split'), expectedView1); @@ -295,7 +295,7 @@ function ManagerDotYamlTests(mockFileName, assert) { configs: {}, sets: [], defaultTreatment: 'control', - trackImpressions: true + impressionsDisabled: false }; const expectedView2 = { name: 'testing_split_only_wl', @@ -306,7 +306,7 @@ function ManagerDotYamlTests(mockFileName, assert) { configs: {}, sets: [], defaultTreatment: 'control', - trackImpressions: true + impressionsDisabled: false }; const expectedView3 = { name: 'testing_split_with_wl', @@ -320,7 +320,7 @@ function ManagerDotYamlTests(mockFileName, assert) { }, sets: [], defaultTreatment: 'control', - trackImpressions: true + impressionsDisabled: false }; const expectedView4 = { name: 'testing_split_off_with_config', @@ -333,7 +333,7 @@ function ManagerDotYamlTests(mockFileName, assert) { }, sets: [], defaultTreatment: 'control', - trackImpressions: true + impressionsDisabled: false }; assert.deepEqual(manager.split('testing_split_on'), expectedView1); @@ -414,15 +414,15 @@ function MultipleInstancesTests(assert) { const expectedView1 = { name: 'testing_split', changeNumber: 0, killed: false, trafficType: 'localhost', - treatments: ['on'], configs: {}, sets: [], trackImpressions: true + treatments: ['on'], configs: {}, sets: [], impressionsDisabled: false }; const expectedView2 = { name: 'testing_split2', changeNumber: 0, killed: false, trafficType: 'localhost', - treatments: ['off'], configs: {}, sets: [], trackImpressions: true + treatments: ['off'], configs: {}, sets: [], impressionsDisabled: false }; const expectedView3 = { name: 'testing_split3', changeNumber: 0, killed: false, trafficType: 'localhost', - treatments: ['custom_treatment'], configs: {}, sets: [], trackImpressions: true + treatments: ['custom_treatment'], configs: {}, sets: [], impressionsDisabled: false }; assert.deepEqual(manager.split('testing_split'), expectedView1); diff --git a/ts-tests/index.ts b/ts-tests/index.ts index b86d8563d..cc6421447 100644 --- a/ts-tests/index.ts +++ b/ts-tests/index.ts @@ -135,7 +135,7 @@ splitView = { }, sets: ['set_a', 'set_b'], defaultTreatment: 'off', - trackImpressions: true + impressionsDisabled: false }; splitViews = [splitView]; From aafd396d7b44fa4d1140bdbbfd1bb4cf1105d509 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Mon, 13 Jan 2025 14:30:07 -0300 Subject: [PATCH 08/21] rc --- .github/workflows/ci-cd.yml | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- src/settings/defaults/version.js | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 57a5464ff..b4ebab8b9 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -58,7 +58,7 @@ jobs: run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") npm run build - name: Store assets - if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/development' || github.ref == 'refs/heads/master') }} + if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/release_v11.1.0' || github.ref == 'refs/heads/master') }} uses: actions/upload-artifact@v4 with: name: assets @@ -69,7 +69,7 @@ jobs: name: Upload assets runs-on: ubuntu-20.04 needs: build - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/release_v11.1.0' }} strategy: matrix: environment: diff --git a/package-lock.json b/package-lock.json index fc0d34e51..e83cc3c3d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@splitsoftware/splitio", - "version": "11.1.0-rc.1", + "version": "11.1.0-rc.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "11.1.0-rc.1", + "version": "11.1.0-rc.2", "license": "Apache-2.0", "dependencies": { "@splitsoftware/splitio-commons": "2.1.0-rc.2", diff --git a/package.json b/package.json index 3c776cc02..13f377737 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "11.1.0-rc.1", + "version": "11.1.0-rc.2", "description": "Split SDK", "files": [ "README.md", diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index 9dba11199..d103d31be 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '11.1.0-rc.1'; +export const packageVersion = '11.1.0-rc.2'; From 833ba1d1d95c5f24cfa59e4c9dfe0f551c3f91d9 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Mon, 13 Jan 2025 14:40:09 -0300 Subject: [PATCH 09/21] Fix test --- src/__tests__/browserSuites/ready-from-cache.spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/__tests__/browserSuites/ready-from-cache.spec.js b/src/__tests__/browserSuites/ready-from-cache.spec.js index 97b3ce8c6..289b34809 100644 --- a/src/__tests__/browserSuites/ready-from-cache.spec.js +++ b/src/__tests__/browserSuites/ready-from-cache.spec.js @@ -822,7 +822,7 @@ export default function (fetchMock, assert) { }); await client.ready(); - t.equal(manager.names().sort().length, 32, 'active splits should be present for evaluation'); + t.equal(manager.names().sort().length, 33, 'active splits should be present for evaluation'); await splitio.destroy(); t.equal(localStorage.getItem('readyFromCache_10.SPLITIO.splits.till'), '1457552620999', 'splits.till must correspond to the till of the last successfully fetched Splits'); @@ -839,7 +839,7 @@ export default function (fetchMock, assert) { await new Promise(res => client.once(client.Event.SDK_READY_FROM_CACHE, res)); - t.equal(manager.names().sort().length, 32, 'active splits should be present for evaluation'); + t.equal(manager.names().sort().length, 33, 'active splits should be present for evaluation'); t.false(console.log.calledWithMatch('clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache'), 'It should log a message about cleaning up cache'); await splitio.destroy(); @@ -860,7 +860,7 @@ export default function (fetchMock, assert) { await new Promise(res => client.once(client.Event.SDK_READY, res)); - t.equal(manager.names().sort().length, 32, 'active splits should be present for evaluation'); + t.equal(manager.names().sort().length, 33, 'active splits should be present for evaluation'); t.true(console.log.calledWithMatch('clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache'), 'It should log a message about cleaning up cache'); await splitio.destroy(); From 75df407229968d86d59585d7d52c4efd43f8c18f Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Mon, 13 Jan 2025 14:46:22 -0300 Subject: [PATCH 10/21] rollback ci-cd --- .github/workflows/ci-cd.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index b4ebab8b9..57a5464ff 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -58,7 +58,7 @@ jobs: run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") npm run build - name: Store assets - if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/release_v11.1.0' || github.ref == 'refs/heads/master') }} + if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/development' || github.ref == 'refs/heads/master') }} uses: actions/upload-artifact@v4 with: name: assets @@ -69,7 +69,7 @@ jobs: name: Upload assets runs-on: ubuntu-20.04 needs: build - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/release_v11.1.0' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} strategy: matrix: environment: From 409727797d98048f2ab70e634fc3bff832212ab2 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 28 Feb 2025 16:21:28 -0300 Subject: [PATCH 11/21] Deps vulnerability fixes, README update and CI-CD image update --- .github/workflows/ci-cd.yml | 3 +-- .github/workflows/sonar-scan.yml | 2 +- .github/workflows/update-license-year.yml | 2 +- README.md | 1 + package-lock.json | 12 ++++++------ 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 57a5464ff..7621d4b33 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -19,8 +19,7 @@ permissions: jobs: build: name: Build - # @TODO rollback to ubuntu-latest eventually. ATM, `npm run test-browser` fails when using ubuntu-latest (ubuntu-22.04) with "ERROR [launcher]: Cannot start ChromeHeadless" - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml index 57497ea78..a38349dbf 100644 --- a/.github/workflows/sonar-scan.yml +++ b/.github/workflows/sonar-scan.yml @@ -12,7 +12,7 @@ on: jobs: build: name: Build - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 diff --git a/.github/workflows/update-license-year.yml b/.github/workflows/update-license-year.yml index 199a0ef78..7e0a945f9 100644 --- a/.github/workflows/update-license-year.yml +++ b/.github/workflows/update-license-year.yml @@ -10,7 +10,7 @@ permissions: jobs: test: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 diff --git a/README.md b/README.md index 77ad5b5fa..10a4f8e21 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ Split has built and maintains SDKs for: * .NET [Github](https://github.com/splitio/dotnet-client) [Docs](https://help.split.io/hc/en-us/articles/360020240172--NET-SDK) * Android [Github](https://github.com/splitio/android-client) [Docs](https://help.split.io/hc/en-us/articles/360020343291-Android-SDK) * Angular [Github](https://github.com/splitio/angular-sdk-plugin) [Docs](https://help.split.io/hc/en-us/articles/6495326064397-Angular-utilities) +* Elixir thin-client [Github](https://github.com/splitio/elixir-thin-client) [Docs](https://help.split.io/hc/en-us/articles/26988707417869-Elixir-Thin-Client-SDK) * Flutter [Github](https://github.com/splitio/flutter-sdk-plugin) [Docs](https://help.split.io/hc/en-us/articles/8096158017165-Flutter-plugin) * GO [Github](https://github.com/splitio/go-client) [Docs](https://help.split.io/hc/en-us/articles/360020093652-Go-SDK) * iOS [Github](https://github.com/splitio/ios-client) [Docs](https://help.split.io/hc/en-us/articles/360020401491-iOS-SDK) diff --git a/package-lock.json b/package-lock.json index 9c46f2f66..4e32e9351 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2087,9 +2087,9 @@ "dev": true }, "node_modules/elliptic": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz", - "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", "dev": true, "dependencies": { "bn.js": "^4.11.9", @@ -8965,9 +8965,9 @@ "dev": true }, "elliptic": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz", - "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", "dev": true, "requires": { "bn.js": "^4.11.9", From b8c091084acf30bcf3c9593dd142067f8ec18114 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 28 Feb 2025 16:36:49 -0300 Subject: [PATCH 12/21] Update Karma configuration to use a custom ChromeHeadless launcher for ubuntu-latest --- karma/config.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/karma/config.js b/karma/config.js index fd7aea269..6789fbd1f 100644 --- a/karma/config.js +++ b/karma/config.js @@ -15,9 +15,14 @@ module.exports = { ], // Run on Chrome Headless - browsers: [ - 'ChromeHeadless' - ], + customLaunchers: { + ChromeHeadlessNoSandbox: { + base: 'ChromeHeadless', + // Flags required to run in ubuntu-22.04 or above (https://chromium.googlesource.com/chromium/src/+/master/docs/linux/suid_sandbox_development.md) + flags: ['--no-sandbox', '--disable-setuid-sandbox'] + } + }, + browsers: ['ChromeHeadlessNoSandbox'], // list of files / patterns to load in the browser files: [ From afb1ae8c60747683c71de24bb2c6d43529c8fdc3 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 26 Mar 2025 16:07:42 -0300 Subject: [PATCH 13/21] Rename some variables in test suite for readability --- .../browserSuites/impressions.debug.spec.js | 6 +++--- .../browserSuites/impressions.none.spec.js | 6 +++--- src/__tests__/browserSuites/impressions.spec.js | 16 ++++++++-------- src/__tests__/mocks/splitchanges.since.-1.json | 2 +- .../nodeSuites/impressions.debug.spec.js | 6 +++--- .../nodeSuites/impressions.none.spec.js | 6 +++--- src/__tests__/nodeSuites/impressions.spec.js | 16 ++++++++-------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/__tests__/browserSuites/impressions.debug.spec.js b/src/__tests__/browserSuites/impressions.debug.spec.js index 5f90b7004..ce40a0fbb 100644 --- a/src/__tests__/browserSuites/impressions.debug.spec.js +++ b/src/__tests__/browserSuites/impressions.debug.spec.js @@ -75,7 +75,7 @@ export default function (fetchMock, assert) { fetchMock.postOnce(url(settings, '/testImpressions/count'), (url, opts) => { assert.deepEqual(JSON.parse(opts.body), { - pf: [{ f: 'always_on_track_impressions_false', m: truncatedTimeFrame, rc: 1 }] + pf: [{ f: 'always_on_impressions_disabled_true', m: truncatedTimeFrame, rc: 1 }] }, 'We should generate impression count for the feature with track impressions disabled.'); return 200; @@ -83,7 +83,7 @@ export default function (fetchMock, assert) { fetchMock.postOnce(url(settings, '/v1/keys/cs'), (url, opts) => { assert.deepEqual(JSON.parse(opts.body), { - keys: [{ fs: ['always_on_track_impressions_false'], k: 'facundo@split.io' }] + keys: [{ fs: ['always_on_impressions_disabled_true'], k: 'facundo@split.io' }] }, 'We should track unique keys for the feature with track impressions disabled.'); return 200; @@ -95,6 +95,6 @@ export default function (fetchMock, assert) { client.getTreatment('split_with_config'); client.getTreatment('split_with_config'); client.getTreatment('split_with_config'); - assert.equal(client.getTreatment('always_on_track_impressions_false'), 'on'); + assert.equal(client.getTreatment('always_on_impressions_disabled_true'), 'on'); }); } diff --git a/src/__tests__/browserSuites/impressions.none.spec.js b/src/__tests__/browserSuites/impressions.none.spec.js index 2294c9695..e75a9ea87 100644 --- a/src/__tests__/browserSuites/impressions.none.spec.js +++ b/src/__tests__/browserSuites/impressions.none.spec.js @@ -59,7 +59,7 @@ export default async function (fetchMock, assert) { { f: 'split_with_config', m: truncatedTimeFrame, rc: 2 }, { f: 'always_off', m: truncatedTimeFrame, rc: 4 }, { f: 'always_on', m: truncatedTimeFrame, rc: 2 }, - { f: 'always_on_track_impressions_false', m: truncatedTimeFrame, rc: 1 } + { f: 'always_on_impressions_disabled_true', m: truncatedTimeFrame, rc: 1 } ] }); return 200; @@ -76,7 +76,7 @@ export default async function (fetchMock, assert) { }, { k: 'emma@split.io', - fs: ['always_off', 'always_on', 'always_on_track_impressions_false'] + fs: ['always_off', 'always_on', 'always_on_impressions_disabled_true'] } ] }, 'We performed evaluations for two keys, so we should have 2 item total.'); @@ -94,7 +94,7 @@ export default async function (fetchMock, assert) { client.getTreatment('always_on'); client.getTreatment('always_off'); client.getTreatment('split_with_config'); - sharedClient.getTreatment('always_on_track_impressions_false'); + sharedClient.getTreatment('always_on_impressions_disabled_true'); client.destroy().then(() => { assert.end(); diff --git a/src/__tests__/browserSuites/impressions.spec.js b/src/__tests__/browserSuites/impressions.spec.js index 33e60106a..d271beb40 100644 --- a/src/__tests__/browserSuites/impressions.spec.js +++ b/src/__tests__/browserSuites/impressions.spec.js @@ -53,7 +53,7 @@ export default function (fetchMock, assert) { const dependencyChildImpr = resp.filter(e => e.f === 'hierarchical_splits_test')[0]; const splitWithConfigImpr = resp.filter(e => e.f === 'split_with_config')[0]; - const alwaysOnWithTrackImpressionsFalse = resp.filter(e => e.f === 'always_on_track_impressions_false'); + const alwaysOnWithImpressionsDisabledTrue = resp.filter(e => e.f === 'always_on_impressions_disabled_true'); assert.true(dependencyChildImpr, 'Split we wanted to evaluate should be present on the impressions.'); assert.false(resp.some(e => e.f === 'hierarchical_dep_always_on'), 'Parent split evaluations should not result in impressions.'); @@ -61,7 +61,7 @@ export default function (fetchMock, assert) { assert.true(splitWithConfigImpr, 'Split evaluated with config should have generated an impression too.'); assert.false(Object.prototype.hasOwnProperty.call(splitWithConfigImpr.i[0], 'configuration'), 'Impressions do not change with configuration evaluations.'); assert.false(Object.prototype.hasOwnProperty.call(splitWithConfigImpr.i[0], 'config'), 'Impressions do not change with configuration evaluations.'); - assert.equal(alwaysOnWithTrackImpressionsFalse.length, 0); + assert.equal(alwaysOnWithImpressionsDisabledTrue.length, 0); const { k, @@ -100,21 +100,21 @@ export default function (fetchMock, assert) { // finding these validate the feature names collection too const splitWithConfigImpr = data.pf.filter(e => e.f === 'split_with_config')[0]; - const alwaysOnWithTrackImpressionsFalse = data.pf.filter(e => e.f === 'always_on_track_impressions_false')[0]; + const alwaysOnWithImpressionsDisabledTrue = data.pf.filter(e => e.f === 'always_on_impressions_disabled_true')[0]; assert.equal(splitWithConfigImpr.rc, 2); assert.equal(typeof splitWithConfigImpr.m, 'number'); assert.equal(splitWithConfigImpr.m, truncatedTimeFrame); - assert.equal(alwaysOnWithTrackImpressionsFalse.rc, 1); - assert.equal(typeof alwaysOnWithTrackImpressionsFalse.m, 'number'); - assert.equal(alwaysOnWithTrackImpressionsFalse.m, truncatedTimeFrame); + assert.equal(alwaysOnWithImpressionsDisabledTrue.rc, 1); + assert.equal(typeof alwaysOnWithImpressionsDisabledTrue.m, 'number'); + assert.equal(alwaysOnWithImpressionsDisabledTrue.m, truncatedTimeFrame); return 200; }); fetchMock.postOnce(url(settings, '/v1/keys/cs'), (url, opts) => { assert.deepEqual(JSON.parse(opts.body), { - keys: [{ fs: [ 'always_on_track_impressions_false' ], k: 'facundo@split.io' }] + keys: [{ fs: [ 'always_on_impressions_disabled_true' ], k: 'facundo@split.io' }] }, 'We should only track unique keys for features flags with track impressions disabled.'); return 200; @@ -132,6 +132,6 @@ export default function (fetchMock, assert) { client.getTreatmentWithConfig('split_with_config'); // Impression should not be tracked - assert.equal(client.getTreatment('always_on_track_impressions_false'), 'on'); + assert.equal(client.getTreatment('always_on_impressions_disabled_true'), 'on'); }); } diff --git a/src/__tests__/mocks/splitchanges.since.-1.json b/src/__tests__/mocks/splitchanges.since.-1.json index 372b030b8..c479eae1d 100644 --- a/src/__tests__/mocks/splitchanges.since.-1.json +++ b/src/__tests__/mocks/splitchanges.since.-1.json @@ -1387,7 +1387,7 @@ "environment": null, "trafficTypeId": null, "trafficTypeName": null, - "name": "always_on_track_impressions_false", + "name": "always_on_impressions_disabled_true", "impressionsDisabled": true, "seed": -790401604, "status": "ACTIVE", diff --git a/src/__tests__/nodeSuites/impressions.debug.spec.js b/src/__tests__/nodeSuites/impressions.debug.spec.js index 08faa13e3..baea95185 100644 --- a/src/__tests__/nodeSuites/impressions.debug.spec.js +++ b/src/__tests__/nodeSuites/impressions.debug.spec.js @@ -75,7 +75,7 @@ export default async function (key, fetchMock, assert) { fetchMock.postOnce(url(settings, '/testImpressions/count'), (url, opts) => { assert.deepEqual(JSON.parse(opts.body), { - pf: [{ f: 'always_on_track_impressions_false', m: truncatedTimeFrame, rc: 1 }] + pf: [{ f: 'always_on_impressions_disabled_true', m: truncatedTimeFrame, rc: 1 }] }, 'We should generate impression count for the feature with track impressions disabled.'); return 200; @@ -83,7 +83,7 @@ export default async function (key, fetchMock, assert) { fetchMock.postOnce(url(settings, '/v1/keys/ss'), (url, opts) => { assert.deepEqual(JSON.parse(opts.body), { - keys: [{ f: 'always_on_track_impressions_false', ks: ['other_key'] }] + keys: [{ f: 'always_on_impressions_disabled_true', ks: ['other_key'] }] }, 'We should track unique keys for the feature with track impressions disabled.'); return 200; @@ -97,5 +97,5 @@ export default async function (key, fetchMock, assert) { assert.equal(client.getTreatment({ matchingKey: key, bucketingKey: 'test_buck_key' }, 'split_with_config'), 'o.n'); assert.equal(client.getTreatment({ matchingKey: key, bucketingKey: 'test_buck_key' }, 'split_with_config'), 'o.n'); assert.equal(client.getTreatment({ matchingKey: key, bucketingKey: 'test_buck_key' }, 'split_with_config'), 'o.n'); - assert.equal(client.getTreatment({ matchingKey: 'other_key', bucketingKey: 'test_buck_key' }, 'always_on_track_impressions_false'), 'on'); + assert.equal(client.getTreatment({ matchingKey: 'other_key', bucketingKey: 'test_buck_key' }, 'always_on_impressions_disabled_true'), 'on'); } diff --git a/src/__tests__/nodeSuites/impressions.none.spec.js b/src/__tests__/nodeSuites/impressions.none.spec.js index 2e47f32e1..004748e3b 100644 --- a/src/__tests__/nodeSuites/impressions.none.spec.js +++ b/src/__tests__/nodeSuites/impressions.none.spec.js @@ -55,7 +55,7 @@ export default async function (key, fetchMock, assert) { { f: 'split_with_config', m: truncatedTimeFrame, rc: 3 }, { f: 'always_off', m: truncatedTimeFrame, rc: 3 }, { f: 'always_on', m: truncatedTimeFrame, rc: 5 }, - { f: 'always_on_track_impressions_false', m: truncatedTimeFrame, rc: 1 } + { f: 'always_on_impressions_disabled_true', m: truncatedTimeFrame, rc: 1 } ] }); return 200; @@ -79,7 +79,7 @@ export default async function (key, fetchMock, assert) { ks: ['emma@split.io', 'emi@split.io', 'nico@split.io'] }, { - f: 'always_on_track_impressions_false', + f: 'always_on_impressions_disabled_true', ks: ['emi@split.io'] } ] @@ -100,7 +100,7 @@ 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.getTreatment('emi@split.io', 'always_on_track_impressions_false'); + client.getTreatment('emi@split.io', 'always_on_impressions_disabled_true'); client.destroy().then(() => { assert.end(); diff --git a/src/__tests__/nodeSuites/impressions.spec.js b/src/__tests__/nodeSuites/impressions.spec.js index e7615140c..325a24257 100644 --- a/src/__tests__/nodeSuites/impressions.spec.js +++ b/src/__tests__/nodeSuites/impressions.spec.js @@ -55,12 +55,12 @@ export default async function (key, fetchMock, assert) { const dependencyChildImpr = data.filter(e => e.f === 'hierarchical_splits_test')[0]; const splitWithConfigImpr = data.filter(e => e.f === 'split_with_config')[0]; const notExistentSplitImpr = data.filter(e => e.f === 'not_existent_split')[0]; - const alwaysOnWithTrackImpressionsFalse = data.filter(e => e.f === 'always_on_track_impressions_false'); + const alwaysOnWithImpressionsDisabledTrue = data.filter(e => e.f === 'always_on_impressions_disabled_true'); assert.equal(notExistentSplitImpr.i.length, 1); // Only one, the split not found is filtered by the non existent Split check. assert.equal(splitWithConfigImpr.i.length, 2); assert.equal(dependencyChildImpr.i.length, 1); - assert.equal(alwaysOnWithTrackImpressionsFalse.length, 0); + assert.equal(alwaysOnWithImpressionsDisabledTrue.length, 0); assert.true(dependencyChildImpr, 'Split we wanted to evaluate should be present on the impressions.'); assert.false(data.some(e => e.f === 'hierarchical_dep_always_on'), 'Parent split evaluations should not result in impressions.'); @@ -111,21 +111,21 @@ export default async function (key, fetchMock, assert) { // finding these validate the feature names collection too const splitWithConfigImpr = data.pf.filter(e => e.f === 'split_with_config')[0]; - const alwaysOnWithTrackImpressionsFalse = data.pf.filter(e => e.f === 'always_on_track_impressions_false')[0]; + const alwaysOnWithImpressionsDisabledTrue = data.pf.filter(e => e.f === 'always_on_impressions_disabled_true')[0]; assert.equal(splitWithConfigImpr.rc, 1); assert.equal(typeof splitWithConfigImpr.m, 'number'); assert.equal(splitWithConfigImpr.m, truncatedTimeFrame); - assert.equal(alwaysOnWithTrackImpressionsFalse.rc, 1); - assert.equal(typeof alwaysOnWithTrackImpressionsFalse.m, 'number'); - assert.equal(alwaysOnWithTrackImpressionsFalse.m, truncatedTimeFrame); + assert.equal(alwaysOnWithImpressionsDisabledTrue.rc, 1); + assert.equal(typeof alwaysOnWithImpressionsDisabledTrue.m, 'number'); + assert.equal(alwaysOnWithImpressionsDisabledTrue.m, truncatedTimeFrame); return 200; }); fetchMock.postOnce(url(settings, '/v1/keys/ss'), (url, opts) => { assert.deepEqual(JSON.parse(opts.body), { - keys: [{ f: 'always_on_track_impressions_false', ks: ['other_key'] }] + keys: [{ f: 'always_on_impressions_disabled_true', ks: ['other_key'] }] }, 'We should only track unique keys for features flags with track impressions disabled.'); return 200; @@ -154,7 +154,7 @@ export default async function (key, fetchMock, assert) { client.getTreatmentWithConfig({ matchingKey: 'different', bucketingKey: 'test_buck_key' }, 'split_with_config'); // Impression should not be tracked - assert.equal(client.getTreatment('other_key', 'always_on_track_impressions_false'), 'on'); + assert.equal(client.getTreatment('other_key', 'always_on_impressions_disabled_true'), 'on'); evaluationsEnd = Date.now(); } From 303a7ec2a0478825f30b58f0caf9b6c560b392f1 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 26 Mar 2025 22:07:52 -0300 Subject: [PATCH 14/21] E2E tests for standalone mode --- .../impressions-listener.spec.js | 7 +- .../browserSuites/impressions.debug.spec.js | 14 ++++ .../browserSuites/impressions.spec.js | 75 ++++++++----------- .../nodeSuites/impressions-listener.spec.js | 6 +- .../nodeSuites/impressions.debug.spec.js | 13 ++++ src/__tests__/nodeSuites/impressions.spec.js | 14 +++- 6 files changed, 76 insertions(+), 53 deletions(-) diff --git a/src/__tests__/browserSuites/impressions-listener.spec.js b/src/__tests__/browserSuites/impressions-listener.spec.js index ca47995c2..9907eab87 100644 --- a/src/__tests__/browserSuites/impressions-listener.spec.js +++ b/src/__tests__/browserSuites/impressions-listener.spec.js @@ -46,7 +46,7 @@ export default function (assert) { const testAttrs = { is_test: true }; // Impression listener is shared across all client instances and does not get affected by configurations. - client.getTreatment('hierarchical_splits_test'); + client.getTreatment('hierarchical_splits_test', undefined, { properties: { prop1: 'prop-value' } }); client2.getTreatment('qc_team'); client2.getTreatmentWithConfig('qc_team'); // Validate that the impression is the same. client3.getTreatment('qc_team', testAttrs); @@ -58,7 +58,8 @@ export default function (assert) { treatment: 'no', bucketingKey: 'impr_bucketing_2', label: 'default rule', - pt: undefined + pt: undefined, + properties: undefined }; assert.equal(listener.logImpression.callCount, 4, 'Impression listener logImpression method should be called after we call client.getTreatment, once per each impression generated.'); @@ -71,7 +72,7 @@ export default function (assert) { bucketingKey: undefined, label: 'expected label', changeNumber: 2828282828, - pt: undefined + properties: '{"prop1":"prop-value"}' }, attributes: undefined, ...metaData diff --git a/src/__tests__/browserSuites/impressions.debug.spec.js b/src/__tests__/browserSuites/impressions.debug.spec.js index ce40a0fbb..73515531b 100644 --- a/src/__tests__/browserSuites/impressions.debug.spec.js +++ b/src/__tests__/browserSuites/impressions.debug.spec.js @@ -63,6 +63,14 @@ export default function (fetchMock, assert) { k: 'facundo@split.io', t: 'o.n', m: data[0].i[1].m, c: 828282828282, r: 'another expected label', pt: data[0].i[0].m, }, { k: 'facundo@split.io', t: 'o.n', m: data[0].i[2].m, c: 828282828282, r: 'another expected label', pt: data[0].i[1].m + }, { + k: 'facundo@split.io', t: 'o.n', m: data[0].i[3].m, c: 828282828282, r: 'another expected label', pt: data[0].i[2].m, properties: '{"prop1":"value1"}' + }, { + k: 'facundo@split.io', t: 'o.n', m: data[0].i[4].m, c: 828282828282, r: 'another expected label', pt: data[0].i[3].m, properties: '{"prop1":"value2"}' + }, { + k: 'facundo@split.io', t: 'o.n', m: data[0].i[5].m, c: 828282828282, r: 'another expected label', pt: data[0].i[4].m, properties: '{"prop1":"value3"}' + }, { + k: 'facundo@split.io', t: 'o.n', m: data[0].i[6].m, c: 828282828282, r: 'another expected label', pt: data[0].i[5].m, properties: '{"prop1":"value4"}' }] }]); @@ -96,5 +104,11 @@ export default function (fetchMock, assert) { client.getTreatment('split_with_config'); client.getTreatment('split_with_config'); assert.equal(client.getTreatment('always_on_impressions_disabled_true'), 'on'); + + // with properties + assert.equal(client.getTreatment('split_with_config', undefined, { properties: { prop1: 'value1' } }), 'o.n'); + assert.equal(client.getTreatments(['split_with_config'], undefined, { properties: { prop1: 'value2' } }).split_with_config, 'o.n'); + assert.equal(client.getTreatmentWithConfig('split_with_config', undefined, { properties: { prop1: 'value3' } }).treatment, 'o.n'); + assert.equal(client.getTreatmentsWithConfig(['split_with_config'], undefined, { properties: { prop1: 'value4' } }).split_with_config.treatment, 'o.n'); }); } diff --git a/src/__tests__/browserSuites/impressions.spec.js b/src/__tests__/browserSuites/impressions.spec.js index d271beb40..f4c800468 100644 --- a/src/__tests__/browserSuites/impressions.spec.js +++ b/src/__tests__/browserSuites/impressions.spec.js @@ -47,32 +47,21 @@ export default function (fetchMock, assert) { const client = splitio.client(); const assertPayload = req => { - const resp = JSON.parse(req.body); - - assert.equal(resp.length, 2, 'We performed evaluations for 3 features, but one with `impressionsDisabled` true, so we should have 2 items total'); - - const dependencyChildImpr = resp.filter(e => e.f === 'hierarchical_splits_test')[0]; - const splitWithConfigImpr = resp.filter(e => e.f === 'split_with_config')[0]; - const alwaysOnWithImpressionsDisabledTrue = resp.filter(e => e.f === 'always_on_impressions_disabled_true'); - - assert.true(dependencyChildImpr, 'Split we wanted to evaluate should be present on the impressions.'); - assert.false(resp.some(e => e.f === 'hierarchical_dep_always_on'), 'Parent split evaluations should not result in impressions.'); - assert.false(resp.some(e => e.f === 'hierarchical_dep_hierarchical'), 'No matter how deep is the chain.'); - assert.true(splitWithConfigImpr, 'Split evaluated with config should have generated an impression too.'); - assert.false(Object.prototype.hasOwnProperty.call(splitWithConfigImpr.i[0], 'configuration'), 'Impressions do not change with configuration evaluations.'); - assert.false(Object.prototype.hasOwnProperty.call(splitWithConfigImpr.i[0], 'config'), 'Impressions do not change with configuration evaluations.'); - assert.equal(alwaysOnWithImpressionsDisabledTrue.length, 0); - - const { - k, - r, - t - } = dependencyChildImpr.i[0]; - - assert.equal(k, 'facundo@split.io', 'Present impression should have the correct key.'); - // The label present on the mock. - assert.equal(r, 'expected label', 'Present impression should have the correct label.'); - assert.equal(t, 'on', 'Present impression should have the correct treatment.'); + const reqBody = JSON.parse(req.body); + + assert.deepEqual(reqBody, [{ + f: 'hierarchical_splits_test', + i: [{ + k: 'facundo@split.io', t: 'on', m: reqBody[0].i[0].m, c: 2828282828, r: 'expected label' + }] + }, { + f: 'split_with_config', + i: [{ + k: 'facundo@split.io', t: 'o.n', m: reqBody[1].i[0].m, c: 828282828282, r: 'another expected label' + }, { + k: 'facundo@split.io', t: 'o.n', m: reqBody[1].i[1].m, c: 828282828282, r: 'another expected label', properties: '{"some":"value2"}' + }] + }], 'We performed evaluations for 3 features, but one with `impressionsDisabled` true, so we should have 2 items total'); }; fetchMock.postOnce(url(settings, '/testImpressions/bulk'), (url, req) => { @@ -93,28 +82,23 @@ export default function (fetchMock, assert) { return 200; }); - fetchMock.postOnce(url(settings, '/testImpressions/count'), (url, opts) => { - const data = JSON.parse(opts.body); + fetchMock.postOnce(url(settings, '/testImpressions/count'), (url, req) => { + const reqBody = JSON.parse(req.body); - assert.equal(data.pf.length, 2, 'We should generate impressions count for 2 features.'); - - // finding these validate the feature names collection too - const splitWithConfigImpr = data.pf.filter(e => e.f === 'split_with_config')[0]; - const alwaysOnWithImpressionsDisabledTrue = data.pf.filter(e => e.f === 'always_on_impressions_disabled_true')[0]; - - assert.equal(splitWithConfigImpr.rc, 2); - assert.equal(typeof splitWithConfigImpr.m, 'number'); - assert.equal(splitWithConfigImpr.m, truncatedTimeFrame); - assert.equal(alwaysOnWithImpressionsDisabledTrue.rc, 1); - assert.equal(typeof alwaysOnWithImpressionsDisabledTrue.m, 'number'); - assert.equal(alwaysOnWithImpressionsDisabledTrue.m, truncatedTimeFrame); + assert.deepEqual(reqBody, { + pf: [{ + f: 'split_with_config', m: truncatedTimeFrame, rc: 2 + }, { + f: 'always_on_impressions_disabled_true', m: truncatedTimeFrame, rc: 1 + }] + }, 'We should generate impressions count for 2 features.'); return 200; }); fetchMock.postOnce(url(settings, '/v1/keys/cs'), (url, opts) => { assert.deepEqual(JSON.parse(opts.body), { - keys: [{ fs: [ 'always_on_impressions_disabled_true' ], k: 'facundo@split.io' }] + keys: [{ fs: ['always_on_impressions_disabled_true'], k: 'facundo@split.io' }] }, 'We should only track unique keys for features flags with track impressions disabled.'); return 200; @@ -129,9 +113,12 @@ export default function (fetchMock, assert) { config: '{"color":"brown","dimensions":{"height":12,"width":14},"text":{"inner":"click me"}}' }, 'We should get an evaluation as always.'); client.getTreatmentWithConfig('split_with_config'); - client.getTreatmentWithConfig('split_with_config'); + client.getTreatmentWithConfig('split_with_config', undefined, { properties: { /* empty properties are ignored */ } }); + + // Impression should not be tracked (passed properties will not be submitted) + assert.equal(client.getTreatment('always_on_impressions_disabled_true'), 'on', undefined, { properties: { some: 'value1' } }); - // Impression should not be tracked - assert.equal(client.getTreatment('always_on_impressions_disabled_true'), 'on'); + // Tracked impression with properties should be handled in DEBUG mode (doesn't increase `rc` count but adds an impression) + assert.equal(client.getTreatment('split_with_config', undefined, { properties: { some: 'value2' } }), 'o.n'); }); } diff --git a/src/__tests__/nodeSuites/impressions-listener.spec.js b/src/__tests__/nodeSuites/impressions-listener.spec.js index 984c36d1e..5a09d532c 100644 --- a/src/__tests__/nodeSuites/impressions-listener.spec.js +++ b/src/__tests__/nodeSuites/impressions-listener.spec.js @@ -39,13 +39,13 @@ export default function (assert) { const testAttrs = { is_test: true }; // Generate one impression, depends on hierarchical_dep_hierarchical which depends on hierarchical_dep_always_on - client.getTreatment('nicolas@split.io', 'hierarchical_splits_test'); + client.getTreatment('nicolas@split.io', 'hierarchical_splits_test', undefined, { properties: { prop1: 'prop-value' } }); client.getTreatment({ matchingKey: 'marcio@split.io', bucketingKey: 'impr_bucketing_2' }, 'qc_team'); client.getTreatment('facundo@split.io', 'qc_team', testAttrs); client.getTreatment('facundo@split.io', 'qc_team', testAttrs); setTimeout(() => { - assert.true(listener.logImpression.callCount, 4, 'Impression listener logImpression method should be called after we call client.getTreatment, once per each impression generated.'); + assert.equal(listener.logImpression.callCount, 4, 'Impression listener logImpression method should be called after we call client.getTreatment, once per each impression generated.'); assert.true(listener.logImpression.getCall(0).calledWithExactly({ impression: { feature: 'hierarchical_splits_test', @@ -55,7 +55,7 @@ export default function (assert) { bucketingKey: undefined, label: 'expected label', changeNumber: 2828282828, - pt: undefined + properties: '{"prop1":"prop-value"}' }, attributes: undefined, ...metaData diff --git a/src/__tests__/nodeSuites/impressions.debug.spec.js b/src/__tests__/nodeSuites/impressions.debug.spec.js index baea95185..5cffc7ba5 100644 --- a/src/__tests__/nodeSuites/impressions.debug.spec.js +++ b/src/__tests__/nodeSuites/impressions.debug.spec.js @@ -63,6 +63,14 @@ export default async function (key, fetchMock, assert) { k: 'facundo@split.io', t: 'o.n', m: data[0].i[1].m, c: 828282828282, r: 'another expected label', b: 'test_buck_key', pt: data[0].i[0].m }, { k: 'facundo@split.io', t: 'o.n', m: data[0].i[2].m, c: 828282828282, r: 'another expected label', b: 'test_buck_key', pt: data[0].i[1].m + }, { + k: 'emi@split.io', t: 'o.n', m: data[0].i[3].m, c: 828282828282, r: 'another expected label', properties: '{"prop1":"value1"}' + }, { + k: 'emi@split.io', t: 'o.n', m: data[0].i[4].m, c: 828282828282, r: 'another expected label', pt: data[0].i[3].m, properties: '{"prop1":"value2"}' + }, { + k: 'emi@split.io', t: 'o.n', m: data[0].i[5].m, c: 828282828282, r: 'another expected label', pt: data[0].i[4].m, properties: '{"prop1":"value3"}' + }, { + k: 'emi@split.io', t: 'o.n', m: data[0].i[6].m, c: 828282828282, r: 'another expected label', pt: data[0].i[5].m, properties: '{"prop1":"value4"}' }] }], 'We performed evaluations for one split, so we should have 1 item total.'); @@ -98,4 +106,9 @@ export default async function (key, fetchMock, assert) { assert.equal(client.getTreatment({ matchingKey: key, bucketingKey: 'test_buck_key' }, 'split_with_config'), 'o.n'); assert.equal(client.getTreatment({ matchingKey: key, bucketingKey: 'test_buck_key' }, 'split_with_config'), 'o.n'); assert.equal(client.getTreatment({ matchingKey: 'other_key', bucketingKey: 'test_buck_key' }, 'always_on_impressions_disabled_true'), 'on'); + + assert.equal(client.getTreatment('emi@split.io', 'split_with_config', undefined, { properties: { prop1: 'value1' } }), 'o.n'); + assert.equal(client.getTreatments('emi@split.io', ['split_with_config'], undefined, { properties: { prop1: 'value2' } }).split_with_config, 'o.n'); + assert.equal(client.getTreatmentWithConfig('emi@split.io', 'split_with_config', undefined, { properties: { prop1: 'value3' } }).treatment, 'o.n'); + assert.equal(client.getTreatmentsWithConfig('emi@split.io', ['split_with_config'], undefined, { properties: { prop1: 'value4' } }).split_with_config.treatment, 'o.n'); } diff --git a/src/__tests__/nodeSuites/impressions.spec.js b/src/__tests__/nodeSuites/impressions.spec.js index 325a24257..6489f3c99 100644 --- a/src/__tests__/nodeSuites/impressions.spec.js +++ b/src/__tests__/nodeSuites/impressions.spec.js @@ -58,7 +58,7 @@ export default async function (key, fetchMock, assert) { const alwaysOnWithImpressionsDisabledTrue = data.filter(e => e.f === 'always_on_impressions_disabled_true'); assert.equal(notExistentSplitImpr.i.length, 1); // Only one, the split not found is filtered by the non existent Split check. - assert.equal(splitWithConfigImpr.i.length, 2); + assert.equal(splitWithConfigImpr.i.length, 3); assert.equal(dependencyChildImpr.i.length, 1); assert.equal(alwaysOnWithImpressionsDisabledTrue.length, 0); @@ -75,6 +75,7 @@ export default async function (key, fetchMock, assert) { assert.equal(output.t, expected.treatment, 'Present impressions should have the correct treatment.'); assert.equal(output.r, expected.label, 'Present impressions should have the correct label.'); assert.equal(output.c, expected.changeNumber, 'Present impressions should have the correct changeNumber.'); + assert.equal(output.properties, expected.properties, 'Present impressions should have the correct properties.'); assert.true(output.m >= (performedWhenReady ? readyEvaluationsStart : evaluationsStart) && output.m <= evaluationsEnd, 'Present impressions should have the correct timestamp (test with error margin).'); } @@ -90,6 +91,10 @@ export default async function (key, fetchMock, assert) { keyName: 'facundo@split.io', label: 'another expected label', treatment: 'o.n', bucketingKey: 'test_buck_key', changeNumber: 828282828282 }); + validateImpressionData(splitWithConfigImpr.i[2], { + keyName: 'other_key', label: 'another expected label', treatment: 'o.n', + changeNumber: 828282828282, properties: '{"some":"value2"}' + }); // Not push impressions with a invalid key (aka matching key) assert.true( @@ -153,8 +158,11 @@ export default async function (key, fetchMock, assert) { client.getTreatmentWithConfig({ matchingKey: key, bucketingKey: 'test_buck_key' }, 'split_with_config'); client.getTreatmentWithConfig({ matchingKey: 'different', bucketingKey: 'test_buck_key' }, 'split_with_config'); - // Impression should not be tracked - assert.equal(client.getTreatment('other_key', 'always_on_impressions_disabled_true'), 'on'); + // Impression should not be tracked (passed properties will not be submitted) + assert.equal(client.getTreatment('other_key', 'always_on_impressions_disabled_true'), 'on', undefined, { properties: { some: 'value1' } }); + + // Tracked impression with properties should be handled in DEBUG mode + assert.equal(client.getTreatment('other_key', 'split_with_config', undefined, { properties: { some: 'value2' } }), 'o.n'); evaluationsEnd = Date.now(); } From 158aafade6054bced081920e249377171598727d Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 26 Mar 2025 23:00:08 -0300 Subject: [PATCH 15/21] E2E tests for consumer mode --- src/__tests__/consumer/node_redis.spec.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/__tests__/consumer/node_redis.spec.js b/src/__tests__/consumer/node_redis.spec.js index a2317ce48..7bc0c93b1 100644 --- a/src/__tests__/consumer/node_redis.spec.js +++ b/src/__tests__/consumer/node_redis.spec.js @@ -23,7 +23,7 @@ const NA = 'NA'; const redisPort = '6385'; -const TOTAL_RAW_IMPRESSIONS = 16; +const TOTAL_RAW_IMPRESSIONS = 17; const TOTAL_EVENTS = 2; const DEDUPED_IMPRESSIONS = 3; @@ -118,7 +118,8 @@ tape('Node.js Redis', function (t) { /** Evaluation, track and manager methods on SDK_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('UT_Segment_member', 'UT_IN_SEGMENT', undefined, { properties: { /* empty properties are ignored */ } }), 'on', 'Evaluations using Redis storage should be correct.'); + assert.equal(await client.getTreatment('UT_Segment_member', 'UT_IN_SEGMENT', undefined, { properties: { some: 'value1' } }), '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.'); assert.equal(await client.getTreatment('UT_Segment_member', 'UT_NOT_IN_SEGMENT'), 'off', 'Evaluations using Redis storage should be correct.'); @@ -223,7 +224,9 @@ tape('Node.js Redis', function (t) { // this should be deduped assert.equal(await client.getTreatment('other', 'UT_IN_SEGMENT'), 'off', 'Evaluations using Redis storage should be correct.'); // this should be deduped - assert.equal(await client.getTreatment('other', 'UT_IN_SEGMENT'), 'off', 'Evaluations using Redis storage should be correct.'); + assert.equal(await client.getTreatment('other', 'UT_IN_SEGMENT', undefined, { properties: { /* empty properties are ignored */ } }), 'off', 'Evaluations using Redis storage should be correct.'); + // this should not be deduped because of properties + assert.equal(await client.getTreatment('other', 'UT_IN_SEGMENT', undefined, { properties: { some: 'value1' } }), 'off', 'Evaluations using Redis storage should be correct.'); assert.equal(await client.getTreatment('UT_Segment_member', 'UT_NOT_IN_SEGMENT'), 'off', 'Evaluations using Redis storage should be correct.'); assert.equal(await client.getTreatment('other', 'UT_NOT_IN_SEGMENT'), 'on', 'Evaluations using Redis storage should be correct.'); From aa0f7ca2e4738c9fe57b080816fac35c87e2d150 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 27 Mar 2025 13:28:03 -0300 Subject: [PATCH 16/21] rc --- CHANGES.txt | 3 +++ package-lock.json | 18 +++++++++--------- package.json | 4 ++-- src/settings/defaults/version.js | 2 +- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 070dc76c4..f988a347d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,6 @@ +11.2.0 (March 28, 2025) + - Added new optional argument to the client `getTreatment` methods to allow passing additional evaluation options, such as a map of properties to append to the generated impression object sent to Split's backend. Read more in our docs. + 11.1.0 (January 17, 2025) - Added support for the new impressions tracking toggle available on feature flags, both respecting the setting and including the new field being returned on `SplitView` type objects. Read more in our docs. - Updated @splitsoftware/splitio-commons package to version 2.1.0. diff --git a/package-lock.json b/package-lock.json index 4e32e9351..1a846b344 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@splitsoftware/splitio", - "version": "11.1.0", + "version": "11.1.1-rc.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "11.1.0", + "version": "11.1.1-rc.0", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.1.0", + "@splitsoftware/splitio-commons": "2.1.1-rc.1", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", @@ -351,9 +351,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.0.tgz", - "integrity": "sha512-7SJRBia0Pi72s76drH8kG2cVnCqkjMHMJQWJSFnG+rE/UOx9AROmuviOkY6tv6qYPJFqFQQGHGX6lXjxZhYzkw==", + "version": "2.1.1-rc.1", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.1-rc.1.tgz", + "integrity": "sha512-+I5K5qmF8YyJlac4g4DFSijWXbtSoq4neVt/hCBFL5c5cPMZ1OnHvbEuU8uXzoJct7o7RSaXS5ystkLarqEeCA==", "dependencies": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" @@ -7537,9 +7537,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.0.tgz", - "integrity": "sha512-7SJRBia0Pi72s76drH8kG2cVnCqkjMHMJQWJSFnG+rE/UOx9AROmuviOkY6tv6qYPJFqFQQGHGX6lXjxZhYzkw==", + "version": "2.1.1-rc.1", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.1-rc.1.tgz", + "integrity": "sha512-+I5K5qmF8YyJlac4g4DFSijWXbtSoq4neVt/hCBFL5c5cPMZ1OnHvbEuU8uXzoJct7o7RSaXS5ystkLarqEeCA==", "requires": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" diff --git a/package.json b/package.json index efc19f4d8..12807311e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "11.1.0", + "version": "11.1.1-rc.0", "description": "Split SDK", "files": [ "README.md", @@ -38,7 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.1.0", + "@splitsoftware/splitio-commons": "2.1.1-rc.1", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index eb209ae90..547cb690c 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '11.1.0'; +export const packageVersion = '11.1.1-rc.0'; From 4c6821b4ef321e24443a14d8bd972dcdb0f3484c Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 27 Mar 2025 13:50:46 -0300 Subject: [PATCH 17/21] upload CDN rc --- .github/workflows/ci-cd.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 7621d4b33..ce52a701e 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -57,7 +57,7 @@ jobs: run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") npm run build - name: Store assets - if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/development' || github.ref == 'refs/heads/master') }} + if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/impression_properties' || github.ref == 'refs/heads/master') }} uses: actions/upload-artifact@v4 with: name: assets @@ -68,7 +68,7 @@ jobs: name: Upload assets runs-on: ubuntu-20.04 needs: build - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/impression_properties' }} strategy: matrix: environment: From 8d08048a4d1cd05aee514aab11b2b0deca1c29d9 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 28 Mar 2025 12:51:58 -0300 Subject: [PATCH 18/21] Revert "upload CDN rc" --- .github/workflows/ci-cd.yml | 4 ++-- src/factory/browser.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index ce52a701e..7621d4b33 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -57,7 +57,7 @@ jobs: run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") npm run build - name: Store assets - if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/impression_properties' || github.ref == 'refs/heads/master') }} + if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/development' || github.ref == 'refs/heads/master') }} uses: actions/upload-artifact@v4 with: name: assets @@ -68,7 +68,7 @@ jobs: name: Upload assets runs-on: ubuntu-20.04 needs: build - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/impression_properties' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} strategy: matrix: environment: diff --git a/src/factory/browser.js b/src/factory/browser.js index 8b71ed235..da9ca826c 100644 --- a/src/factory/browser.js +++ b/src/factory/browser.js @@ -20,10 +20,10 @@ const syncManagerOnlineCSFactory = syncManagerOnlineFactory(pollingManagerCSFact function getStorage(settings) { return settings.storage.type === STORAGE_LOCALSTORAGE ? - InLocalStorage(settings.storage) - : settings.storage.__originalType === STORAGE_LOCALSTORAGE ? - __InLocalStorageMockFactory - : InMemoryStorageCSFactory; + InLocalStorage(settings.storage) : + settings.storage.__originalType === STORAGE_LOCALSTORAGE ? + __InLocalStorageMockFactory : + InMemoryStorageCSFactory; } /** From 8eb73ab09b0803241e712fab71900b67faed08c8 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 28 Mar 2025 13:29:25 -0300 Subject: [PATCH 19/21] rc --- package-lock.json | 18 +++++++++--------- package.json | 4 ++-- .../browserSuites/impressions.debug.spec.js | 8 ++++---- .../nodeSuites/impressions.debug.spec.js | 6 +++--- src/settings/defaults/version.js | 2 +- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1a846b344..780926432 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@splitsoftware/splitio", - "version": "11.1.1-rc.0", + "version": "11.1.1-rc.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "11.1.1-rc.0", + "version": "11.1.1-rc.1", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.1.1-rc.1", + "@splitsoftware/splitio-commons": "2.1.1-rc.2", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", @@ -351,9 +351,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.1.1-rc.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.1-rc.1.tgz", - "integrity": "sha512-+I5K5qmF8YyJlac4g4DFSijWXbtSoq4neVt/hCBFL5c5cPMZ1OnHvbEuU8uXzoJct7o7RSaXS5ystkLarqEeCA==", + "version": "2.1.1-rc.2", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.1-rc.2.tgz", + "integrity": "sha512-BDC7bSeJVbpdmJNnL2+gsijc0E3AT/oPWFp4p8hR1CgpFjaekYhuoA+ZC0ha4jzjFlc6vXaJrczGK4LWKyTmnA==", "dependencies": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" @@ -7537,9 +7537,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.1.1-rc.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.1-rc.1.tgz", - "integrity": "sha512-+I5K5qmF8YyJlac4g4DFSijWXbtSoq4neVt/hCBFL5c5cPMZ1OnHvbEuU8uXzoJct7o7RSaXS5ystkLarqEeCA==", + "version": "2.1.1-rc.2", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.1-rc.2.tgz", + "integrity": "sha512-BDC7bSeJVbpdmJNnL2+gsijc0E3AT/oPWFp4p8hR1CgpFjaekYhuoA+ZC0ha4jzjFlc6vXaJrczGK4LWKyTmnA==", "requires": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" diff --git a/package.json b/package.json index 12807311e..79d987635 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "11.1.1-rc.0", + "version": "11.1.1-rc.1", "description": "Split SDK", "files": [ "README.md", @@ -38,7 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.1.1-rc.1", + "@splitsoftware/splitio-commons": "2.1.1-rc.2", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", diff --git a/src/__tests__/browserSuites/impressions.debug.spec.js b/src/__tests__/browserSuites/impressions.debug.spec.js index 73515531b..887d2f4fd 100644 --- a/src/__tests__/browserSuites/impressions.debug.spec.js +++ b/src/__tests__/browserSuites/impressions.debug.spec.js @@ -64,13 +64,13 @@ export default function (fetchMock, assert) { }, { k: 'facundo@split.io', t: 'o.n', m: data[0].i[2].m, c: 828282828282, r: 'another expected label', pt: data[0].i[1].m }, { - k: 'facundo@split.io', t: 'o.n', m: data[0].i[3].m, c: 828282828282, r: 'another expected label', pt: data[0].i[2].m, properties: '{"prop1":"value1"}' + k: 'facundo@split.io', t: 'o.n', m: data[0].i[3].m, c: 828282828282, r: 'another expected label', properties: '{"prop1":"value1"}' }, { - k: 'facundo@split.io', t: 'o.n', m: data[0].i[4].m, c: 828282828282, r: 'another expected label', pt: data[0].i[3].m, properties: '{"prop1":"value2"}' + k: 'facundo@split.io', t: 'o.n', m: data[0].i[4].m, c: 828282828282, r: 'another expected label', properties: '{"prop1":"value2"}' }, { - k: 'facundo@split.io', t: 'o.n', m: data[0].i[5].m, c: 828282828282, r: 'another expected label', pt: data[0].i[4].m, properties: '{"prop1":"value3"}' + k: 'facundo@split.io', t: 'o.n', m: data[0].i[5].m, c: 828282828282, r: 'another expected label', properties: '{"prop1":"value3"}' }, { - k: 'facundo@split.io', t: 'o.n', m: data[0].i[6].m, c: 828282828282, r: 'another expected label', pt: data[0].i[5].m, properties: '{"prop1":"value4"}' + k: 'facundo@split.io', t: 'o.n', m: data[0].i[6].m, c: 828282828282, r: 'another expected label', properties: '{"prop1":"value4"}' }] }]); diff --git a/src/__tests__/nodeSuites/impressions.debug.spec.js b/src/__tests__/nodeSuites/impressions.debug.spec.js index 5cffc7ba5..f0f194f9b 100644 --- a/src/__tests__/nodeSuites/impressions.debug.spec.js +++ b/src/__tests__/nodeSuites/impressions.debug.spec.js @@ -66,11 +66,11 @@ export default async function (key, fetchMock, assert) { }, { k: 'emi@split.io', t: 'o.n', m: data[0].i[3].m, c: 828282828282, r: 'another expected label', properties: '{"prop1":"value1"}' }, { - k: 'emi@split.io', t: 'o.n', m: data[0].i[4].m, c: 828282828282, r: 'another expected label', pt: data[0].i[3].m, properties: '{"prop1":"value2"}' + k: 'emi@split.io', t: 'o.n', m: data[0].i[4].m, c: 828282828282, r: 'another expected label', properties: '{"prop1":"value2"}' }, { - k: 'emi@split.io', t: 'o.n', m: data[0].i[5].m, c: 828282828282, r: 'another expected label', pt: data[0].i[4].m, properties: '{"prop1":"value3"}' + k: 'emi@split.io', t: 'o.n', m: data[0].i[5].m, c: 828282828282, r: 'another expected label', properties: '{"prop1":"value3"}' }, { - k: 'emi@split.io', t: 'o.n', m: data[0].i[6].m, c: 828282828282, r: 'another expected label', pt: data[0].i[5].m, properties: '{"prop1":"value4"}' + k: 'emi@split.io', t: 'o.n', m: data[0].i[6].m, c: 828282828282, r: 'another expected label', properties: '{"prop1":"value4"}' }] }], 'We performed evaluations for one split, so we should have 1 item total.'); diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index 547cb690c..905f95393 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '11.1.1-rc.0'; +export const packageVersion = '11.1.1-rc.1'; From 8ea9d826f75d9e9393047085825cb3f50ea784a2 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 28 Mar 2025 16:10:32 -0300 Subject: [PATCH 20/21] rc --- .github/workflows/ci-cd.yml | 4 ++-- CHANGES.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 7621d4b33..1d0089402 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -57,7 +57,7 @@ jobs: run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") npm run build - name: Store assets - if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/development' || github.ref == 'refs/heads/master') }} + if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/cache_expiration' || github.ref == 'refs/heads/master') }} uses: actions/upload-artifact@v4 with: name: assets @@ -68,7 +68,7 @@ jobs: name: Upload assets runs-on: ubuntu-20.04 needs: build - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/cache_expiration' }} strategy: matrix: environment: diff --git a/CHANGES.txt b/CHANGES.txt index 761ab36aa..fdbf0d362 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,5 @@ 11.2.0 (March 28, 2025) - - Added new optional argument to the client `getTreatment` methods to allow passing additional evaluation options, such as a map of properties to append to the generated impression object sent to Split's backend. Read more in our docs. + - Added a new optional argument to the client `getTreatment` methods to allow passing additional evaluation options, such as a map of properties to append to the generated impressions sent to Split backend. Read more in our docs. - Added two new configuration options for the SDK's `LOCALSTORAGE` storage type to control the behavior of the persisted rollout plan cache in the browser: - `storage.expirationDays` to specify the validity period of the rollout plan cache in days. - `storage.clearOnInit` to clear the rollout plan cache on SDK initialization. From 4466a55bf11742d5c61453acd5eb1ea6d7007936 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 28 Mar 2025 16:32:42 -0300 Subject: [PATCH 21/21] stable version --- .github/workflows/ci-cd.yml | 4 ++-- package-lock.json | 18 +++++++++--------- package.json | 4 ++-- src/settings/defaults/version.js | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 1d0089402..7621d4b33 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -57,7 +57,7 @@ jobs: run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") npm run build - name: Store assets - if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/cache_expiration' || github.ref == 'refs/heads/master') }} + if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/development' || github.ref == 'refs/heads/master') }} uses: actions/upload-artifact@v4 with: name: assets @@ -68,7 +68,7 @@ jobs: name: Upload assets runs-on: ubuntu-20.04 needs: build - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/cache_expiration' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} strategy: matrix: environment: diff --git a/package-lock.json b/package-lock.json index 780926432..a5142e979 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@splitsoftware/splitio", - "version": "11.1.1-rc.1", + "version": "11.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "11.1.1-rc.1", + "version": "11.2.0", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.1.1-rc.2", + "@splitsoftware/splitio-commons": "2.2.0", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", @@ -351,9 +351,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.1.1-rc.2", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.1-rc.2.tgz", - "integrity": "sha512-BDC7bSeJVbpdmJNnL2+gsijc0E3AT/oPWFp4p8hR1CgpFjaekYhuoA+ZC0ha4jzjFlc6vXaJrczGK4LWKyTmnA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.2.0.tgz", + "integrity": "sha512-ywWDh2fM4/EqJ1AByjXM13gAal+z/WSGiBQ5OZmjpL/iqFLENy3yo/GwsxR/ataOi27XbRQTeQbE/eD7HVnWiA==", "dependencies": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" @@ -7537,9 +7537,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.1.1-rc.2", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.1-rc.2.tgz", - "integrity": "sha512-BDC7bSeJVbpdmJNnL2+gsijc0E3AT/oPWFp4p8hR1CgpFjaekYhuoA+ZC0ha4jzjFlc6vXaJrczGK4LWKyTmnA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.2.0.tgz", + "integrity": "sha512-ywWDh2fM4/EqJ1AByjXM13gAal+z/WSGiBQ5OZmjpL/iqFLENy3yo/GwsxR/ataOi27XbRQTeQbE/eD7HVnWiA==", "requires": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" diff --git a/package.json b/package.json index 79d987635..c3ac42b76 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "11.1.1-rc.1", + "version": "11.2.0", "description": "Split SDK", "files": [ "README.md", @@ -38,7 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.1.1-rc.2", + "@splitsoftware/splitio-commons": "2.2.0", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index 905f95393..e116c4aa8 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '11.1.1-rc.1'; +export const packageVersion = '11.2.0';