From 19b30422be26717ad24076c8fe1d10eec9c30aed Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 8 Oct 2025 12:29:41 -0300 Subject: [PATCH 1/3] Use log level when logger is set --- CHANGES.txt | 3 +++ package-lock.json | 18 +++++++++--------- package.json | 4 ++-- src/__tests__/offline/node.spec.js | 10 +++++++--- src/settings/defaults/version.js | 2 +- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 61cd21f1c..ea434f8fc 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,6 @@ +11.7.1 (October 8, 2025) + - Bugfix - Updated @splitsoftware/splitio-commons package to version 2.7.1, which fixes the `debug` option to support log levels when the `logger` option is used. + 11.7.0 (October 7, 2025) - Added support for custom loggers: added `logger` configuration option and `factory.Logger.setLogger` method to allow the SDK to use a custom logger. - Updated @splitsoftware/splitio-commons package to version 2.7.0. diff --git a/package-lock.json b/package-lock.json index 23598221e..2cc7b9b9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@splitsoftware/splitio", - "version": "11.7.0", + "version": "11.7.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "11.7.0", + "version": "11.7.1", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.7.0", + "@splitsoftware/splitio-commons": "2.7.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.7.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.7.0.tgz", - "integrity": "sha512-w2aemu5HNVQXX/tbmSuFjpWa/AjS+EBiH6ltHMqfg2MZMWayTFJbfjjQcudAVLR+vLjDw2DuCTp/xj3kKlcf5g==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.7.1.tgz", + "integrity": "sha512-7a4VVMczh0YKVRi35EhD0FOAEwzqfJRcCiKqLLhZCxAvrZBpE2khpGn8pOP+y6TefdPVtblW8GIku4O4r0KRdQ==", "license": "Apache-2.0", "dependencies": { "@types/ioredis": "^4.28.0", @@ -7740,9 +7740,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.7.0.tgz", - "integrity": "sha512-w2aemu5HNVQXX/tbmSuFjpWa/AjS+EBiH6ltHMqfg2MZMWayTFJbfjjQcudAVLR+vLjDw2DuCTp/xj3kKlcf5g==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.7.1.tgz", + "integrity": "sha512-7a4VVMczh0YKVRi35EhD0FOAEwzqfJRcCiKqLLhZCxAvrZBpE2khpGn8pOP+y6TefdPVtblW8GIku4O4r0KRdQ==", "requires": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" diff --git a/package.json b/package.json index 8a88d9769..ea3ad14b7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "11.7.0", + "version": "11.7.1", "description": "Split SDK", "files": [ "README.md", @@ -38,7 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.7.0", + "@splitsoftware/splitio-commons": "2.7.1", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", diff --git a/src/__tests__/offline/node.spec.js b/src/__tests__/offline/node.spec.js index 48e9fd010..afbb495e0 100644 --- a/src/__tests__/offline/node.spec.js +++ b/src/__tests__/offline/node.spec.js @@ -77,7 +77,11 @@ tape('Node.js Offline Mode', function (t) { const factory = SplitFactory({ ...config, - debug: 'ERROR', // enable logs to check the message. If logger is provided, any log level different than 'NONE' will be overridden to 'DEBUG'. + core: { + ...config.core, + key: 'ignored' // just set to log a warning + }, + debug: 'INFO', // enable logs to check the message. logger: console // use console as custom logger. }); const client = factory.client(); @@ -92,9 +96,9 @@ tape('Node.js Offline Mode', function (t) { assert.pass('If tried to load a file with invalid extension, we should emit SDK_READY_TIMED_OUT.'); assert.ok(console.error.calledWithMatch(`splitio => sync:offline: There was an issue loading the mock feature flags data. No changes will be applied to the current cache. Error: Invalid extension specified for feature flags mock file. Accepted extensions are ".yml" and ".yaml". Your specified file is ${config.features}`)); - assert.notOk(console.warn.called, 'warn should not be called'); + assert.ok(console.warn.calledWithMatch('splitio => Provided `key` is ignored in server-side SDK.')); assert.ok(console.info.called, 'info should be called'); - assert.ok(console.debug.called, 'debug should be called'); + assert.notOk(console.debug.called, 'debug should not be called'); console.error.restore(); console.warn.restore(); diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index d51e26fdc..2a4a3206c 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '11.7.0'; +export const packageVersion = '11.7.1'; From 355cb94ef14f32542a82af768bc217263258e7cd Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 15 Oct 2025 15:42:01 -0300 Subject: [PATCH 2/3] Update tests --- .../ready-from-cache-async-wrapper.spec.js | 18 ++-- .../browserSuites/ready-from-cache.spec.js | 56 +++++++++---- .../browserSuites/ready-promise.spec.js | 82 +++++++++---------- src/__tests__/browserSuites/telemetry.spec.js | 4 +- src/__tests__/nodeSuites/lazy-init.spec.js | 12 +-- .../nodeSuites/ready-promise.spec.js | 65 +++++++-------- src/__tests__/nodeSuites/telemetry.spec.js | 4 +- src/__tests__/offline/browser.spec.js | 16 ++-- 8 files changed, 135 insertions(+), 122 deletions(-) diff --git a/src/__tests__/browserSuites/ready-from-cache-async-wrapper.spec.js b/src/__tests__/browserSuites/ready-from-cache-async-wrapper.spec.js index 73350b3c6..d4f37eed5 100644 --- a/src/__tests__/browserSuites/ready-from-cache-async-wrapper.spec.js +++ b/src/__tests__/browserSuites/ready-from-cache-async-wrapper.spec.js @@ -168,7 +168,7 @@ export default function (fetchMock, assert) { t.true(Date.now() - startTime >= 400, 'It should emit SDK_READY too but 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(() => { + client.whenReady().then(() => { t.true(Date.now() - startTime >= 400, '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.'); }); @@ -176,12 +176,12 @@ export default function (fetchMock, assert) { t.true(Date.now() - startTime >= 700, 'It should emit SDK_READY too but 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(() => { + client2.whenReady().then(() => { t.true(Date.now() - startTime >= 700, '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(() => { + client3.whenReady().then(() => { t.true(Date.now() - startTime >= 1000, '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.'); @@ -196,7 +196,7 @@ export default function (fetchMock, assert) { t.equal(client3.getTreatment('always_on'), 'on', 'It should evaluate treatments with updated data after syncing with the cloud.'); }); client3.on(client3.Event.SDK_READY_TIMED_OUT, () => { - client3.ready().catch(() => { + client3.whenReady().catch(() => { t.true(Date.now() - startTime >= 850, 'It should reject ready promise before syncing memberships data with the cloud.'); t.equal(client3.getTreatment('always_on'), 'on', 'It should evaluate treatments with memberships data from cache.'); }); @@ -280,7 +280,7 @@ export default function (fetchMock, assert) { 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(() => { + client.whenReady().then(() => { 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.'); }); @@ -288,12 +288,12 @@ export default function (fetchMock, assert) { 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(() => { + client2.whenReady().then(() => { 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(() => { + client3.whenReady().then(() => { 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.'); @@ -310,7 +310,7 @@ export default function (fetchMock, assert) { t.equal(client3.getTreatment('always_on'), 'on', 'It should evaluate treatments with updated data after syncing with the cloud.'); }); client3.on(client3.Event.SDK_READY_TIMED_OUT, () => { - client3.ready().catch(() => { + client3.whenReady().catch(() => { t.true(Date.now() - startTime >= 850, 'It should reject ready promise before syncing memberships data with the cloud.'); t.equal(client3.getTreatment('always_on'), 'control', 'It should not evaluate treatments with memberships data from cache.'); }); @@ -359,7 +359,7 @@ export default function (fetchMock, assert) { t.true(client.__getStatus().isReady, 'Client should emit SDK_READY_FROM_CACHE alongside SDK_READY, because clearOnInit is true'); }); - await client.ready(); + await client.whenReady(); 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'); diff --git a/src/__tests__/browserSuites/ready-from-cache.spec.js b/src/__tests__/browserSuites/ready-from-cache.spec.js index 23053b239..2ff9cc183 100644 --- a/src/__tests__/browserSuites/ready-from-cache.spec.js +++ b/src/__tests__/browserSuites/ready-from-cache.spec.js @@ -226,7 +226,7 @@ export default function (fetchMock, assert) { t.true(Date.now() - startTime >= 400, 'It should emit SDK_READY too but 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(() => { + client.whenReady().then(() => { t.true(Date.now() - startTime >= 400, '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.'); }); @@ -234,12 +234,12 @@ export default function (fetchMock, assert) { t.true(Date.now() - startTime >= 700, 'It should emit SDK_READY too but 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(() => { + client2.whenReady().then(() => { t.true(Date.now() - startTime >= 700, '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(() => { + client3.whenReady().then(() => { t.true(Date.now() - startTime >= 1000, '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.'); @@ -254,7 +254,7 @@ export default function (fetchMock, assert) { t.equal(client3.getTreatment('always_on'), 'on', 'It should evaluate treatments with updated data after syncing with the cloud.'); }); client3.on(client3.Event.SDK_READY_TIMED_OUT, () => { - client3.ready().catch(() => { + client3.whenReady().catch(() => { t.true(Date.now() - startTime >= 850, 'It should reject ready promise before syncing memberships data with the cloud.'); t.equal(client3.getTreatment('always_on'), 'on', 'It should evaluate treatments with memberships data from cache.'); }); @@ -269,7 +269,7 @@ export default function (fetchMock, assert) { events: 'https://events.baseurl/readyFromCacheWithData3' }; localStorage.clear(); - t.plan(12 * 2 + 5); + t.plan(12 * 2 + 14); fetchMock.get(testUrls.sdk + '/splitChanges?s=1.3&since=25&rbSince=-1', () => { t.equal(localStorage.getItem('readyFromCache_3.SPLITIO.split.always_on'), alwaysOnSplitInverted, 'feature flags must not be cleaned from cache'); @@ -285,8 +285,16 @@ export default function (fetchMock, assert) { 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': {} }); - fetchMock.postOnce(testUrls.events + '/testImpressions/bulk', 200); - fetchMock.postOnce(testUrls.events + '/testImpressions/count', 200); + fetchMock.postOnce(testUrls.events + '/testImpressions/bulk', (_, opts) => { + const payload = JSON.parse(opts.body); + t.equal(payload.length, 1, 'Only one flag was evaluated'); + t.equal(payload[0].i.length, 14, '14 impressions were queued, one per getTreatment call'); + t.equal(payload[0].i.filter((imp) => imp.t === 'control').length, 2, '2 impressions were queued for control (not ready from cache)'); + t.equal(payload[0].i.filter((imp) => imp.t === 'off').length, 4, '4 impressions were queued for off (ready from cache)'); + t.equal(payload[0].i.filter((imp) => imp.t === 'on').length, 8, '8 impressions were queued for on (ready)'); + + return 200; + }); localStorage.setItem('some_user_item', 'user_item'); localStorage.setItem('readyFromCache_3.SPLITIO.splits.till', 25); @@ -301,6 +309,9 @@ export default function (fetchMock, assert) { type: 'LOCALSTORAGE', prefix: 'readyFromCache_3' }, + sync: { + impressionsMode: 'DEBUG' + }, startup: { readyTimeout: 0.85 }, @@ -320,6 +331,8 @@ export default function (fetchMock, assert) { client.on(client.Event.SDK_READY_FROM_CACHE, () => { t.true(Date.now() - startTime < 400, 'It should emit SDK_READY_FROM_CACHE on every client if there was data in the cache and we subscribe on time. Should be considerably faster than actual readiness from the cloud.'); + t.false(client.__getStatus().isReady, 'It should not be ready yet'); + t.equal(client.getTreatment('always_on'), 'off', 'It should evaluate treatments with data from cache instead of control due to Input Validation'); const client4 = splitio.client('nicolas4@split.io'); @@ -342,7 +355,11 @@ export default function (fetchMock, assert) { t.true(Date.now() - startTime >= 400, 'It should emit SDK_READY too but 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(() => { + client.whenReadyFromCache().then((isReady) => { + t.false(isReady, 'It should be ready from cache before ready (syncing with the cloud).'); + t.true(Date.now() - startTime < 50, 'It should resolve ready from cache promise almost immediately.'); + }); + client.whenReady().then(() => { t.true(Date.now() - startTime >= 400, '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.'); }); @@ -350,12 +367,15 @@ export default function (fetchMock, assert) { t.true(Date.now() - startTime >= 700, 'It should emit SDK_READY too but 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(() => { + client2.whenReadyFromCache().then((isReady) => { + t.false(isReady, 'It should be ready from cache before ready (syncing with the cloud).'); + }); + client2.whenReady().then(() => { t.true(Date.now() - startTime >= 700, '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(() => { + client3.whenReady().then(() => { t.true(Date.now() - startTime >= 1000, '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.'); @@ -370,7 +390,7 @@ export default function (fetchMock, assert) { t.equal(client3.getTreatment('always_on'), 'on', 'It should evaluate treatments with updated data after syncing with the cloud.'); }); client3.on(client3.Event.SDK_READY_TIMED_OUT, () => { - client3.ready().catch(() => { + client3.whenReady().catch(() => { t.true(Date.now() - startTime >= 850, 'It should reject ready promise before syncing memberships data with the cloud.'); t.equal(client3.getTreatment('always_on'), 'on', 'It should evaluate treatments with memberships data from cache.'); }); @@ -452,7 +472,11 @@ export default function (fetchMock, assert) { 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(() => { + client.whenReadyFromCache().then((isReady) => { + t.true(isReady, 'It should be ready from cache and ready.'); + t.true(nearlyEqual(Date.now() - startTime, CLIENT_READY_MS), 'It should resolve ready from cache promise after syncing with the cloud.'); + }); + client.whenReady().then(() => { 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.'); }); @@ -460,12 +484,12 @@ export default function (fetchMock, assert) { 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(() => { + client2.whenReady().then(() => { 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(() => { + client3.whenReady().then(() => { 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.'); @@ -482,7 +506,7 @@ export default function (fetchMock, assert) { t.equal(client3.getTreatment('always_on'), 'on', 'It should evaluate treatments with updated data after syncing with the cloud.'); }); client3.on(client3.Event.SDK_READY_TIMED_OUT, () => { - client3.ready().catch(() => { + client3.whenReady().catch(() => { t.true(Date.now() - startTime >= 850, 'It should reject ready promise before syncing memberships data with the cloud.'); t.equal(client3.getTreatment('always_on'), 'control', 'It should not evaluate treatments with memberships data from cache.'); }); @@ -898,7 +922,7 @@ export default function (fetchMock, assert) { t.true(client.__getStatus().isReady, 'Client should emit SDK_READY_FROM_CACHE alongside SDK_READY, because clearOnInit is true'); }); - await client.ready(); + await client.whenReady(); 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'); diff --git a/src/__tests__/browserSuites/ready-promise.spec.js b/src/__tests__/browserSuites/ready-promise.spec.js index 3371d1618..f632a177c 100644 --- a/src/__tests__/browserSuites/ready-promise.spec.js +++ b/src/__tests__/browserSuites/ready-promise.spec.js @@ -31,7 +31,7 @@ function assertGetTreatmentWhenReady(assert, client) { function assertGetTreatmentControlNotReady(assert, client) { consoleSpy.log.resetHistory(); assert.equal(client.getTreatment('hierarchical_splits_test'), 'control', 'We should get control if client is not ready.'); - assert.true(consoleSpy.log.calledWithExactly('[WARN] splitio => getTreatment: the SDK is not ready, results may be incorrect for feature flag hierarchical_splits_test. Make sure to wait for SDK readiness before using this method.'), 'Telling us that calling getTreatment would return CONTROL since SDK is not ready at this point.'); + assert.true(consoleSpy.log.calledWithExactly('[WARN] splitio => getTreatment: the SDK is not ready to evaluate. Results may be incorrect for feature flag hierarchical_splits_test. Make sure to wait for SDK readiness before using this method.'), 'Telling us that calling getTreatment would return CONTROL since SDK is not ready at this point.'); } function assertGetTreatmentControlNotReadyOnDestroy(assert, client) { @@ -68,7 +68,7 @@ export default function readyPromiseAssertions(fetchMock, assert) { const splitio = SplitFactory(config); const client = splitio.client(); - client.ready() + client.whenReady() .then(() => { t.fail('### SDK IS READY - not TIMED OUT when it should.'); }) @@ -77,7 +77,7 @@ export default function readyPromiseAssertions(fetchMock, assert) { assertGetTreatmentControlNotReady(t, client); client.destroy().then(() => { - client.ready() + client.whenReady() .then(() => { t.fail('### SDK IS READY - It should not in this scenario.'); t.end(); @@ -118,13 +118,13 @@ export default function readyPromiseAssertions(fetchMock, assert) { // In this case, we use the manager instead of the client to get the ready promise const manager = splitio.manager(); - manager.ready() + manager.whenReady() .then(() => { t.pass('### SDK IS READY - the retry request is under the limits.'); assertGetTreatmentWhenReady(t, client); client.destroy().then(() => { - client.ready() + client.whenReady() .then(() => { t.pass('### SDK IS READY - the promise remains resolved after client destruction.'); assertGetTreatmentControlNotReadyOnDestroy(t, client); @@ -166,7 +166,7 @@ export default function readyPromiseAssertions(fetchMock, assert) { const splitio = SplitFactory(config); const client = splitio.client(); - client.ready() + client.whenReady() .then(() => { t.fail('### SDK IS READY - not TIMED OUT when it should.'); }) @@ -175,13 +175,13 @@ export default function readyPromiseAssertions(fetchMock, assert) { assertGetTreatmentControlNotReady(t, client); setTimeout(() => { - client.ready() + client.whenReady() .then(() => { t.pass('### SDK IS READY - retry attempt finishes before the requestTimeoutBeforeReady limit'); assertGetTreatmentWhenReady(t, client); client.destroy().then(() => { - client.ready() + client.whenReady() .then(() => { t.pass('### SDK IS READY - the promise remains resolved after client destruction.'); assertGetTreatmentControlNotReadyOnDestroy(t, client); @@ -244,7 +244,7 @@ export default function readyPromiseAssertions(fetchMock, assert) { const client = splitio.client(); const nicolasClient = splitio.client('nicolas@split.io'); - client.ready() + client.whenReady() .then(() => { t.fail('### SDK IS READY - not TIMED OUT when it should.'); }) @@ -253,25 +253,25 @@ export default function readyPromiseAssertions(fetchMock, assert) { assertGetTreatmentControlNotReady(t, client); client.on(client.Event.SDK_READY, () => { - client.ready().then(() => { + client.whenReady().then(() => { t.pass('### SDK IS READY - the scheduled refresh changes the client state into "ready"'); assertGetTreatmentWhenReady(t, client); const tStart = Date.now(); - nicolasClient.ready().then(() => { + nicolasClient.whenReady().then(() => { const delta = Date.now() - tStart; t.true(nearlyEqual(delta, 0), 'shared client is ready as soon as main client is ready (i.e., splits have arrived)'); const timeoutClient = splitio.client('emiliano@split.io'); - timeoutClient.ready().then(undefined, () => { // setting onRejected handler via `then` method + timeoutClient.whenReady().then(undefined, () => { // setting onRejected handler via `then` method t.pass('### Shared client TIMED OUT - promise rejected since memberships fetch took more time than readyTimeout'); - timeoutClient.ready().catch(() => { // setting onRejected handler via `catch` method + timeoutClient.whenReady().catch(() => { // setting onRejected handler via `catch` method t.pass('### Shared client TIMED OUT - promise keeps being rejected'); timeoutClient.on(timeoutClient.Event.SDK_READY, () => { - timeoutClient.ready().then(() => { + timeoutClient.whenReady().then(() => { t.pass('### Shared client READY - `ready` returns a new resolved promise'); Promise.all([timeoutClient.destroy(), nicolasClient.destroy(), client.destroy()]).then(() => { - client.ready() + client.whenReady() .then(() => { t.pass('### SDK IS READY - the promise remains resolved after client destruction.'); assertGetTreatmentControlNotReadyOnDestroy(t, client); @@ -318,7 +318,7 @@ export default function readyPromiseAssertions(fetchMock, assert) { const splitio = SplitFactory(config); const client = splitio.client(); - client.ready() + client.whenReady() .then(() => { t.fail('### SDK IS READY - not TIMED OUT when it should.'); client.destroy().then(() => { t.end(); }); @@ -330,7 +330,7 @@ export default function readyPromiseAssertions(fetchMock, assert) { .catch((error) => { t.equal(error, 'error', '### Handled thrown exception on onRejected callback.'); client.destroy().then(() => { - client.ready() + client.whenReady() .then(() => { t.fail('### SDK IS READY - It should not in this scenario.'); t.end(); @@ -368,7 +368,7 @@ export default function readyPromiseAssertions(fetchMock, assert) { const splitio = SplitFactory(config); const client = splitio.client(); - client.ready() + client.whenReady() .then(() => { t.pass('### SDK IS READY as it should, request is under the limits.'); assertGetTreatmentWhenReady(t, client); @@ -377,7 +377,7 @@ export default function readyPromiseAssertions(fetchMock, assert) { .catch((error) => { t.equal(error, 'error', '### Handled thrown exception on onRejected callback.'); client.destroy().then(() => { - client.ready() + client.whenReady() .then(() => { t.pass('### SDK IS READY - the promise remains resolved after client destruction.'); assertGetTreatmentControlNotReadyOnDestroy(t, client); @@ -421,7 +421,7 @@ export default function readyPromiseAssertions(fetchMock, assert) { // `ready` is called immediately. Thus, the 'reject' callback is expected to be called in 0.15 seconds aprox. setTimeout(() => { const tStart = Date.now(); - client.ready() + client.whenReady() .then(() => { t.fail('### SDK IS READY - not TIMED OUT when it should.'); }) @@ -436,7 +436,7 @@ export default function readyPromiseAssertions(fetchMock, assert) { // `ready` is called in 0.15 seconds, when the promise is just rejected. Thus, the 'reject' callback is expected to be called immediately (0 seconds aprox). setTimeout(() => { const tStart = Date.now(); - manager.ready() + manager.whenReady() .then(() => { t.fail('### SDK IS READY - not TIMED OUT when it should.'); }) @@ -451,7 +451,7 @@ export default function readyPromiseAssertions(fetchMock, assert) { // `ready` is called in 0.25 seconds, right after the promise is resolved (0.2 secs). Thus, the 'resolve' callback is expected to be called immediately (0 seconds aprox). setTimeout(() => { const tStart = Date.now(); - manager.ready() + manager.whenReady() .then(() => { t.pass('### SDK IS READY - retry attempt finishes before the requestTimeoutBeforeReady limit'); assertGetTreatmentWhenReady(t, client); @@ -465,7 +465,7 @@ export default function readyPromiseAssertions(fetchMock, assert) { }) .then(() => { client.destroy().then(() => { - client.ready() + client.whenReady() .then(() => { t.pass('### SDK IS READY - the promise remains resolved after client destruction.'); assertGetTreatmentControlNotReadyOnDestroy(t, client); @@ -506,26 +506,24 @@ export default function readyPromiseAssertions(fetchMock, assert) { const splitio = SplitFactory(config); - const onReadycallback = function () { }; + const onReadyCallback = function () { }; // We invoke the ready method and also add and remove SDK_READY event listeners using the client and manager instances const client = splitio.client(); - client.ready(); - client.on(client.Event.SDK_READY, onReadycallback); - client.off(client.Event.SDK_READY, onReadycallback); + client.whenReady().then(() => t.fail('SDK TIMED OUT - Should not resolve')).catch(() => t.pass('SDK TIMED OUT - Should reject')); + client.on(client.Event.SDK_READY, onReadyCallback); + client.off(client.Event.SDK_READY, onReadyCallback); const manager = splitio.manager(); - manager.ready(); - manager.on(manager.Event.SDK_READY, onReadycallback); - manager.off(manager.Event.SDK_READY, onReadycallback); + client.whenReadyFromCache().then(() => t.fail('SDK TIMED OUT - Should not resolve')).catch(() => t.pass('SDK TIMED OUT - Should reject')); + manager.on(manager.Event.SDK_READY, onReadyCallback); + manager.off(manager.Event.SDK_READY, onReadyCallback); consoleSpy.log.resetHistory(); setTimeout(() => { - client.ready(); + client.whenReadyFromCache().then((isReady) => t.true(isReady, 'SDK IS READY (& READY FROM CACHE) - Should resolve')).catch(() => t.fail('SDK TIMED OUT - Should not reject')); assertGetTreatmentWhenReady(t, client); - t.true(consoleSpy.log.calledWithExactly('[WARN] splitio => No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'), - 'Warning that there are not listeners for SDK_READY event'); // assert error messages when adding event listeners after SDK has already triggered them consoleSpy.log.resetHistory(); @@ -540,15 +538,15 @@ export default function readyPromiseAssertions(fetchMock, assert) { consoleSpy.log.resetHistory(); const sharedClientWithCb = splitio.client('nicolas@split.io'); sharedClientWithCb.on(client.Event.SDK_READY, () => { - t.false(consoleSpy.log.calledWithExactly('[WARN] splitio => No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'), + t.false(consoleSpy.log.calledWithExactly('[WARN] splitio => No listeners for SDK_READY event detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet synchronized with the backend.'), 'No warning logged'); const sharedClientWithoutCb = splitio.client('emiliano@split.io'); setTimeout(() => { - t.true(consoleSpy.log.calledWithExactly('[WARN] splitio => No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'), + t.true(consoleSpy.log.calledWithExactly('[WARN] splitio => No listeners for SDK_READY event detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet synchronized with the backend.'), 'Warning logged'); Promise.all([sharedClientWithoutCb.destroy(), client.destroy()]).then(() => { - client.ready() + client.whenReady() .then(() => { t.pass('### SDK IS READY - the promise remains resolved after client destruction.'); assertGetTreatmentControlNotReadyOnDestroy(t, client); @@ -594,18 +592,12 @@ export default function readyPromiseAssertions(fetchMock, assert) { // Assert getTreatment return CONTROL and trigger warning when SDK is not ready yet assertGetTreatmentControlNotReady(t, client); - client.ready() - .then(() => { - t.fail('### SDK IS READY - not TIMED OUT when it should.'); - }); - otherClient.ready() - .then(() => { - t.fail('### SDK IS READY - not TIMED OUT when it should.'); - }); + client.whenReady().then(() => t.fail('SDK TIMED OUT - Should not resolve')).catch(() => t.pass('SDK TIMED OUT - Should reject')); + otherClient.whenReady().then(() => t.fail('SDK TIMED OUT - Should not resolve')).catch(() => t.pass('SDK TIMED OUT - Should reject')); setTimeout(() => { Promise.all([client.destroy(), otherClient.destroy()]).then(() => { - client.ready() + client.whenReady() .then(() => { t.fail('### SDK IS READY - It should not in this scenario.'); t.end(); diff --git a/src/__tests__/browserSuites/telemetry.spec.js b/src/__tests__/browserSuites/telemetry.spec.js index 29facccf4..a1a64b4fd 100644 --- a/src/__tests__/browserSuites/telemetry.spec.js +++ b/src/__tests__/browserSuites/telemetry.spec.js @@ -105,14 +105,14 @@ export default async function telemetryBrowserSuite(fetchMock, t) { const data = JSON.parse(opts.body); assert.true(data.tR > 0, 'timeUntilReady is larger than 0'); - delete data.tR; // delete to validate other properties + assert.true(data.tC > 0, 'timeUntilReadyFromCache is larger than 0'); assert.deepEqual(data, { oM: 0, st: 'memory', aF: 1, rF: 0, sE: false, rR: { sp: 99999, ms: 60, im: 300, ev: 60, te: 1 } /* override featuresRefreshRate */, uO: { s: true, e: true, a: false, st: false, t: true } /* override sdk, events and telemetry URLs */, iQ: 30000, eQ: 500, iM: 0, iL: false, hP: false, nR: 1 /* 1 non ready usage */, t: [], uC: 2 /* Default GRANTED */, - fsT: 0, fsI: 0 + fsT: 0, fsI: 0, tR: data.tR, tC: data.tC }, 'metrics/config JSON payload should be the expected'); finish.next(); diff --git a/src/__tests__/nodeSuites/lazy-init.spec.js b/src/__tests__/nodeSuites/lazy-init.spec.js index c4d94c1d2..44bfacaa6 100644 --- a/src/__tests__/nodeSuites/lazy-init.spec.js +++ b/src/__tests__/nodeSuites/lazy-init.spec.js @@ -41,14 +41,14 @@ export default function (settings, fetchMock, t) { splitio.init(); await splitio.client().ready(); - assert.deepEqual(splitio.client().__getStatus(), { isReady: true, isReadyFromCache: false, isTimedout: false, hasTimedout: false, isDestroyed: false, isOperational: true, lastUpdate: splitio.client().__getStatus().lastUpdate }, 'Status'); + assert.deepEqual(splitio.client().__getStatus(), { isReady: true, isReadyFromCache: true, isTimedout: false, hasTimedout: false, isDestroyed: false, isOperational: true, lastUpdate: splitio.client().__getStatus().lastUpdate }, 'Status'); await splitio.destroy(); - assert.deepEqual(splitio.client().__getStatus(), { isReady: true, isReadyFromCache: false, isTimedout: false, hasTimedout: false, isDestroyed: true, isOperational: false, lastUpdate: splitio.client().__getStatus().lastUpdate }, 'Status'); + assert.deepEqual(splitio.client().__getStatus(), { isReady: true, isReadyFromCache: true, isTimedout: false, hasTimedout: false, isDestroyed: true, isOperational: false, lastUpdate: splitio.client().__getStatus().lastUpdate }, 'Status'); splitio.init(); - assert.deepEqual(splitio.client().__getStatus(), { isReady: true, isReadyFromCache: false, isTimedout: false, hasTimedout: false, isDestroyed: false, isOperational: true, lastUpdate: splitio.client().__getStatus().lastUpdate }, 'Status'); + assert.deepEqual(splitio.client().__getStatus(), { isReady: true, isReadyFromCache: true, isTimedout: false, hasTimedout: false, isDestroyed: false, isOperational: true, lastUpdate: splitio.client().__getStatus().lastUpdate }, 'Status'); await splitio.destroy(); @@ -99,14 +99,14 @@ export default function (settings, fetchMock, t) { splitio.init(); await splitio.client().ready(); - assert.deepEqual(splitio.client().__getStatus(), { isReady: true, isReadyFromCache: false, isTimedout: false, hasTimedout: false, isDestroyed: false, isOperational: true, lastUpdate: splitio.client().__getStatus().lastUpdate }, 'Status'); + assert.deepEqual(splitio.client().__getStatus(), { isReady: true, isReadyFromCache: true, isTimedout: false, hasTimedout: false, isDestroyed: false, isOperational: true, lastUpdate: splitio.client().__getStatus().lastUpdate }, 'Status'); await splitio.destroy(); - assert.deepEqual(splitio.client().__getStatus(), { isReady: true, isReadyFromCache: false, isTimedout: false, hasTimedout: false, isDestroyed: true, isOperational: false, lastUpdate: splitio.client().__getStatus().lastUpdate }, 'Status'); + assert.deepEqual(splitio.client().__getStatus(), { isReady: true, isReadyFromCache: true, isTimedout: false, hasTimedout: false, isDestroyed: true, isOperational: false, lastUpdate: splitio.client().__getStatus().lastUpdate }, 'Status'); splitio.init(); - assert.deepEqual(splitio.client().__getStatus(), { isReady: true, isReadyFromCache: false, isTimedout: false, hasTimedout: false, isDestroyed: false, isOperational: true, lastUpdate: splitio.client().__getStatus().lastUpdate }, 'Status'); + assert.deepEqual(splitio.client().__getStatus(), { isReady: true, isReadyFromCache: true, isTimedout: false, hasTimedout: false, isDestroyed: false, isOperational: true, lastUpdate: splitio.client().__getStatus().lastUpdate }, 'Status'); await splitio.destroy(); diff --git a/src/__tests__/nodeSuites/ready-promise.spec.js b/src/__tests__/nodeSuites/ready-promise.spec.js index 7d0f35619..b6b76c93e 100644 --- a/src/__tests__/nodeSuites/ready-promise.spec.js +++ b/src/__tests__/nodeSuites/ready-promise.spec.js @@ -28,7 +28,7 @@ function assertGetTreatmentWhenReady(assert, client, key) { function assertGetTreatmentControlNotReady(assert, client, key) { consoleSpy.log.resetHistory(); assert.equal(client.getTreatment(key, 'hierarchical_splits_test'), 'control', 'We should get control if client is not ready.'); - assert.true(consoleSpy.log.calledWithExactly('[WARN] splitio => getTreatment: the SDK is not ready, results may be incorrect for feature flag hierarchical_splits_test. Make sure to wait for SDK readiness before using this method.'), 'Telling us that calling getTreatment would return CONTROL since SDK is not ready at this point.'); + assert.true(consoleSpy.log.calledWithExactly('[WARN] splitio => getTreatment: the SDK is not ready to evaluate. Results may be incorrect for feature flag hierarchical_splits_test. Make sure to wait for SDK readiness before using this method.'), 'Telling us that calling getTreatment would return CONTROL since SDK is not ready at this point.'); } function assertGetTreatmentControlNotReadyOnDestroy(assert, client, key) { @@ -64,7 +64,7 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { const splitio = SplitFactory(config); const client = splitio.client(); - client.ready() + client.whenReady() .then(() => { t.fail('### SDK IS READY - not TIMED OUT when it should.'); }) @@ -73,7 +73,7 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { assertGetTreatmentControlNotReady(t, client, key); client.destroy().then(() => { - client.ready() + client.whenReady() .then(() => { t.fail('### SDK IS READY - It should not in this scenario.'); t.end(); @@ -114,13 +114,13 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { // In this case, we use the manager instead of the client to get the ready promise const manager = splitio.manager(); - manager.ready() + manager.whenReady() .then(() => { t.pass('### SDK IS READY - the retry request is under the limits.'); assertGetTreatmentWhenReady(t, client, key); client.destroy().then(() => { - client.ready() + client.whenReady() .then(() => { t.pass('### SDK IS READY - the promise remains resolved after client destruction.'); assertGetTreatmentControlNotReadyOnDestroy(t, client, key); @@ -162,7 +162,7 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { const splitio = SplitFactory(config); const client = splitio.client(); - client.ready() + client.whenReady() .then(() => { t.fail('### SDK IS READY - not TIMED OUT when it should.'); }) @@ -171,13 +171,13 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { assertGetTreatmentControlNotReady(t, client, key); setTimeout(() => { - client.ready() + client.whenReady() .then(() => { t.pass('### SDK IS READY - retry attempt finishes before the requestTimeoutBeforeReady limit'); assertGetTreatmentWhenReady(t, client, key); client.destroy().then(() => { - client.ready() + client.whenReady() .then(() => { t.pass('### SDK IS READY - the promise remains resolved after client destruction.'); assertGetTreatmentControlNotReadyOnDestroy(t, client, key); @@ -232,7 +232,7 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { const splitio = SplitFactory(config); const client = splitio.client(); - client.ready() + client.whenReady() .then(() => { t.fail('### SDK IS READY - not TIMED OUT when it should.'); }) @@ -241,13 +241,13 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { assertGetTreatmentControlNotReady(t, client, key); setTimeout(() => { - client.ready() + client.whenReady() .then(() => { t.pass('### SDK IS READY - the scheduled refresh changes the client state into "is ready"'); assertGetTreatmentWhenReady(t, client, key); client.destroy().then(() => { - client.ready() + client.whenReady() .then(() => { t.pass('### SDK IS READY - the promise remains resolved after client destruction.'); assertGetTreatmentControlNotReadyOnDestroy(t, client, key); @@ -289,7 +289,7 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { const splitio = SplitFactory(config); const client = splitio.client(); - client.ready() + client.whenReady() .then(() => { t.fail('### SDK IS READY - not TIMED OUT when it should.'); client.destroy().then(() => { t.end(); }); @@ -301,7 +301,7 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { .catch((error) => { t.equal(error, 'error', '### Handled thrown exception on onRejected callback.'); client.destroy().then(() => { - client.ready() + client.whenReady() .then(() => { t.fail('### SDK IS READY - It should not in this scenario.'); t.end(); @@ -339,7 +339,7 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { const splitio = SplitFactory(config); const client = splitio.client(); - client.ready() + client.whenReady() .then(() => { t.pass('### SDK IS READY as it should, request is under the limits.'); assertGetTreatmentWhenReady(t, client, key); @@ -348,7 +348,7 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { .catch((error) => { t.equal(error, 'error', '### Handled thrown exception on onRejected callback.'); client.destroy().then(() => { - client.ready() + client.whenReady() .then(() => { t.pass('### SDK IS READY - the promise remains resolved after client destruction.'); assertGetTreatmentControlNotReadyOnDestroy(t, client, key); @@ -392,7 +392,7 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { // `ready` is called immediately. Thus, the 'reject' callback is expected to be called in 0.15 seconds aprox. setTimeout(() => { const tStart = Date.now(); - client.ready() + client.whenReady() .then(() => { t.fail('### SDK IS READY - not TIMED OUT when it should.'); }) @@ -407,7 +407,7 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { // `ready` is called in 0.15 seconds, when the promise is just rejected. Thus, the 'reject' callback is expected to be called immediately (0 seconds aprox). setTimeout(() => { const tStart = Date.now(); - manager.ready() + manager.whenReady() .then(() => { t.fail('### SDK IS READY - not TIMED OUT when it should.'); }) @@ -422,7 +422,7 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { // `ready` is called in 0.25 seconds, right after the promise is resolved (0.2 secs). Thus, the 'resolve' callback is expected to be called immediately (0 seconds aprox). setTimeout(() => { const tStart = Date.now(); - manager.ready() + manager.whenReady() .then(() => { t.pass('### SDK IS READY - retry attempt finishes before the requestTimeoutBeforeReady limit'); assertGetTreatmentWhenReady(t, client, key); @@ -436,7 +436,7 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { }) .then(() => { client.destroy().then(() => { - client.ready() + client.whenReady() .then(() => { t.pass('### SDK IS READY - the promise remains resolved after client destruction.'); assertGetTreatmentControlNotReadyOnDestroy(t, client, key); @@ -475,26 +475,24 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { const splitio = SplitFactory(config); - const onReadycallback = function () { }; + const onReadyCallback = function () { }; // We invoke the ready method and also add and remove SDK_READY event listeners using the client and manager instances const client = splitio.client(); - client.ready(); - client.on(client.Event.SDK_READY, onReadycallback); - client.off(client.Event.SDK_READY, onReadycallback); + client.whenReady().then(() => t.fail('SDK TIMED OUT - Should not resolve')).catch(() => t.pass('SDK TIMED OUT - Should reject')); + client.on(client.Event.SDK_READY, onReadyCallback); + client.off(client.Event.SDK_READY, onReadyCallback); const manager = splitio.manager(); - manager.ready(); - manager.on(manager.Event.SDK_READY, onReadycallback); - manager.off(manager.Event.SDK_READY, onReadycallback); + client.whenReadyFromCache().then(() => t.fail('SDK TIMED OUT - Should not resolve')).catch(() => t.pass('SDK TIMED OUT - Should reject')); + manager.on(manager.Event.SDK_READY, onReadyCallback); + manager.off(manager.Event.SDK_READY, onReadyCallback); consoleSpy.log.resetHistory(); setTimeout(() => { - client.ready(); + client.whenReadyFromCache().then((isReady) => t.true(isReady, 'SDK IS READY (& READY FROM CACHE) - Should resolve')).catch(() => t.fail('SDK TIMED OUT - Should not reject')); assertGetTreatmentWhenReady(t, client, key); - t.true(consoleSpy.log.calledWithExactly('[WARN] splitio => No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'), - 'Warning that there are not listeners for SDK_READY event'); // assert error messages when adding event listeners after SDK has already triggered them consoleSpy.log.resetHistory(); @@ -506,7 +504,7 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { 'Logging error that a listeners for SDK_READY_TIMED_OUT event was added after triggered'); client.destroy().then(() => { - client.ready() + client.whenReady() .then(() => { t.pass('### SDK IS READY - the promise remains resolved after client destruction.'); assertGetTreatmentControlNotReadyOnDestroy(t, client, key); @@ -549,14 +547,11 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { // Assert getTreatment return CONTROL and trigger warning when SDK is not ready yet assertGetTreatmentControlNotReady(t, client, key); - client.ready() - .then(() => { - t.fail('### SDK IS READY - not TIMED OUT when it should.'); - }); + client.whenReady().then(() => t.fail('SDK TIMED OUT - Should not resolve')).catch(() => t.pass('SDK TIMED OUT - Should reject')); setTimeout(() => { client.destroy().then(() => { - client.ready() + client.whenReady() .then(() => { t.fail('### SDK IS READY - It should not in this scenario.'); t.end(); diff --git a/src/__tests__/nodeSuites/telemetry.spec.js b/src/__tests__/nodeSuites/telemetry.spec.js index 85f7cdf67..e73f8c4f1 100644 --- a/src/__tests__/nodeSuites/telemetry.spec.js +++ b/src/__tests__/nodeSuites/telemetry.spec.js @@ -94,14 +94,14 @@ export default async function telemetryNodejsSuite(key, fetchMock, assert) { const data = JSON.parse(opts.body); assert.true(data.tR > 0, 'timeUntilReady is larger than 0'); - delete data.tR; // delete to validate other properties + assert.true(data.tC > 0, 'timeUntilReadyFromCache is larger than 0'); assert.deepEqual(data, { oM: 0, st: 'memory', aF: 1, rF: 0, sE: false, rR: { sp: 99999, se: 60, im: 300, ev: 60, te: 1 } /* override featuresRefreshRate */, uO: { s: true, e: true, a: false, st: false, t: true } /* override sdk, events and telemetry URLs */, iQ: 30000, eQ: 500, iM: 0, iL: false, hP: false, nR: 1 /* 1 non ready usage */, t: [], uC: 0 /* NA */, - fsT: 0, fsI: 0 + fsT: 0, fsI: 0, tR: data.tR, tC: data.tC }, 'metrics/config JSON payload should be the expected'); finish.next(); diff --git a/src/__tests__/offline/browser.spec.js b/src/__tests__/offline/browser.spec.js index 8507e080b..f2cb8dac0 100644 --- a/src/__tests__/offline/browser.spec.js +++ b/src/__tests__/offline/browser.spec.js @@ -116,21 +116,23 @@ tape('Browser offline mode', function (assert) { const clientStatus = client.__getStatus(); assert.equal(clientStatus.isReadyFromCache, true, 'If ready from cache, READY_FROM_CACHE status must be true'); - assert.equal(clientStatus.isReady, false, 'READY status must not be set before READY_FROM_CACHE'); + assert.equal(clientStatus.isReady, configs[i].storage && configs[i].storage.type === 'LOCALSTORAGE' ? false : true, 'When not using LOCALSTORAGE, READY status is set together with READY_FROM_CACHE'); + if (!clientStatus.isReady) readyFromCacheCount++; assert.deepEqual(manager.names(), ['testing_split', 'testing_split_with_config']); assert.equal(client.getTreatment('testing_split_with_config'), 'off'); - readyFromCacheCount++; client.on(client.Event.SDK_READY_FROM_CACHE, () => { assert.fail('It should not emit SDK_READY_FROM_CACHE again'); }); - const newClient = factory.client('another'); - assert.equal(newClient.getTreatment('testing_split_with_config'), 'off', 'It should evaluate treatments with data from cache instead of control'); - newClient.on(newClient.Event.SDK_READY_FROM_CACHE, () => { - assert.fail('It should not emit SDK_READY_FROM_CACHE if already done.'); - }); + if (configs[i].storage && configs[i].storage.type === 'LOCALSTORAGE') { + const newClient = factory.client('another'); + assert.equal(newClient.getTreatment('testing_split_with_config'), 'off', 'It should evaluate treatments with data from cache instead of control'); + newClient.on(newClient.Event.SDK_READY_FROM_CACHE, () => { + assert.fail('It should not emit SDK_READY_FROM_CACHE if already done.'); + }); + } }; client.on(client.Event.SDK_READY_FROM_CACHE, sdkReadyFromCache(client)); From 5d621b1a00afd1306b65d65db8f66b97f7c4760a Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Mon, 27 Oct 2025 19:07:50 -0300 Subject: [PATCH 3/3] Update JS-commons --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2cc7b9b9a..02fc53b90 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "11.7.1", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.7.1", + "@splitsoftware/splitio-commons": "2.7.9-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.7.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.7.1.tgz", - "integrity": "sha512-7a4VVMczh0YKVRi35EhD0FOAEwzqfJRcCiKqLLhZCxAvrZBpE2khpGn8pOP+y6TefdPVtblW8GIku4O4r0KRdQ==", + "version": "2.7.9-rc.1", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.7.9-rc.1.tgz", + "integrity": "sha512-hmcekZebItAc67+AF3xGgKXIvnLybQhpaEtQKsqU3WbyRittUI9hN9HqA6qUiaLxFPwrsCxioihTYsnxxej/Rg==", "license": "Apache-2.0", "dependencies": { "@types/ioredis": "^4.28.0", @@ -7740,9 +7740,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.7.1.tgz", - "integrity": "sha512-7a4VVMczh0YKVRi35EhD0FOAEwzqfJRcCiKqLLhZCxAvrZBpE2khpGn8pOP+y6TefdPVtblW8GIku4O4r0KRdQ==", + "version": "2.7.9-rc.1", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.7.9-rc.1.tgz", + "integrity": "sha512-hmcekZebItAc67+AF3xGgKXIvnLybQhpaEtQKsqU3WbyRittUI9hN9HqA6qUiaLxFPwrsCxioihTYsnxxej/Rg==", "requires": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" diff --git a/package.json b/package.json index ea3ad14b7..f39ff2e23 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.7.1", + "@splitsoftware/splitio-commons": "2.7.9-rc.1", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1",