From 1f08e896c9bcc0dd12b8d46e02a2cc19ae07c73e Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 28 Jul 2022 13:25:23 -0300 Subject: [PATCH 01/23] rename files like in JS SDK --- .../evaluations.spec.js | 0 .../{online => browserSuites}/events.spec.js | 0 .../fetch-specific-splits.spec.js | 0 .../ignore-ip-addresses-setting.spec.js | 0 .../impressions-listener.spec.js | 0 .../impressions.debug.spec.js | 0 .../impressions.spec.js | 0 .../{online => browserSuites}/manager.spec.js | 0 .../push-corner-cases.spec.js | 2 +- .../push-fallbacking.spec.js | 0 .../push-initialization-nopush.spec.js | 0 .../push-initialization-retries.spec.js | 0 .../push-refresh-token.spec.js | 0 .../push-synchronization-retries.spec.js | 0 .../push-synchronization.spec.js | 0 .../readiness.spec.js | 0 .../ready-from-cache.spec.js | 0 .../ready-promise.spec.js | 0 .../shared-instantiation.spec.js | 0 .../telemetry.spec.js | 0 .../use-beacon-api.debug.spec.js | 0 .../use-beacon-api.spec.js | 0 .../user-consent.spec.js | 0 .../{errors => errorCatching}/browser.spec.js | 0 src/__tests__/offline/browser.spec.js | 2 -- src/__tests__/online/browser.spec.js | 32 +++++++++---------- src/__tests__/push/browser.spec.js | 14 ++++---- 27 files changed, 24 insertions(+), 26 deletions(-) rename src/__tests__/{online => browserSuites}/evaluations.spec.js (100%) rename src/__tests__/{online => browserSuites}/events.spec.js (100%) rename src/__tests__/{online => browserSuites}/fetch-specific-splits.spec.js (100%) rename src/__tests__/{online => browserSuites}/ignore-ip-addresses-setting.spec.js (100%) rename src/__tests__/{online => browserSuites}/impressions-listener.spec.js (100%) rename src/__tests__/{online => browserSuites}/impressions.debug.spec.js (100%) rename src/__tests__/{online => browserSuites}/impressions.spec.js (100%) rename src/__tests__/{online => browserSuites}/manager.spec.js (100%) rename src/__tests__/{push => browserSuites}/push-corner-cases.spec.js (98%) rename src/__tests__/{push => browserSuites}/push-fallbacking.spec.js (100%) rename src/__tests__/{push => browserSuites}/push-initialization-nopush.spec.js (100%) rename src/__tests__/{push => browserSuites}/push-initialization-retries.spec.js (100%) rename src/__tests__/{push => browserSuites}/push-refresh-token.spec.js (100%) rename src/__tests__/{push => browserSuites}/push-synchronization-retries.spec.js (100%) rename src/__tests__/{push => browserSuites}/push-synchronization.spec.js (100%) rename src/__tests__/{online => browserSuites}/readiness.spec.js (100%) rename src/__tests__/{online => browserSuites}/ready-from-cache.spec.js (100%) rename src/__tests__/{online => browserSuites}/ready-promise.spec.js (100%) rename src/__tests__/{online => browserSuites}/shared-instantiation.spec.js (100%) rename src/__tests__/{online => browserSuites}/telemetry.spec.js (100%) rename src/__tests__/{online => browserSuites}/use-beacon-api.debug.spec.js (100%) rename src/__tests__/{online => browserSuites}/use-beacon-api.spec.js (100%) rename src/__tests__/{online => browserSuites}/user-consent.spec.js (100%) rename src/__tests__/{errors => errorCatching}/browser.spec.js (100%) diff --git a/src/__tests__/online/evaluations.spec.js b/src/__tests__/browserSuites/evaluations.spec.js similarity index 100% rename from src/__tests__/online/evaluations.spec.js rename to src/__tests__/browserSuites/evaluations.spec.js diff --git a/src/__tests__/online/events.spec.js b/src/__tests__/browserSuites/events.spec.js similarity index 100% rename from src/__tests__/online/events.spec.js rename to src/__tests__/browserSuites/events.spec.js diff --git a/src/__tests__/online/fetch-specific-splits.spec.js b/src/__tests__/browserSuites/fetch-specific-splits.spec.js similarity index 100% rename from src/__tests__/online/fetch-specific-splits.spec.js rename to src/__tests__/browserSuites/fetch-specific-splits.spec.js diff --git a/src/__tests__/online/ignore-ip-addresses-setting.spec.js b/src/__tests__/browserSuites/ignore-ip-addresses-setting.spec.js similarity index 100% rename from src/__tests__/online/ignore-ip-addresses-setting.spec.js rename to src/__tests__/browserSuites/ignore-ip-addresses-setting.spec.js diff --git a/src/__tests__/online/impressions-listener.spec.js b/src/__tests__/browserSuites/impressions-listener.spec.js similarity index 100% rename from src/__tests__/online/impressions-listener.spec.js rename to src/__tests__/browserSuites/impressions-listener.spec.js diff --git a/src/__tests__/online/impressions.debug.spec.js b/src/__tests__/browserSuites/impressions.debug.spec.js similarity index 100% rename from src/__tests__/online/impressions.debug.spec.js rename to src/__tests__/browserSuites/impressions.debug.spec.js diff --git a/src/__tests__/online/impressions.spec.js b/src/__tests__/browserSuites/impressions.spec.js similarity index 100% rename from src/__tests__/online/impressions.spec.js rename to src/__tests__/browserSuites/impressions.spec.js diff --git a/src/__tests__/online/manager.spec.js b/src/__tests__/browserSuites/manager.spec.js similarity index 100% rename from src/__tests__/online/manager.spec.js rename to src/__tests__/browserSuites/manager.spec.js diff --git a/src/__tests__/push/push-corner-cases.spec.js b/src/__tests__/browserSuites/push-corner-cases.spec.js similarity index 98% rename from src/__tests__/push/push-corner-cases.spec.js rename to src/__tests__/browserSuites/push-corner-cases.spec.js index 25f38e7..e130c1d 100644 --- a/src/__tests__/push/push-corner-cases.spec.js +++ b/src/__tests__/browserSuites/push-corner-cases.spec.js @@ -7,7 +7,7 @@ import { nearlyEqual, url } from '../testUtils'; import EventSourceMock, { setMockListener } from '../testUtils/eventSourceMock'; window.EventSource = EventSourceMock; -import { SplitFactory, InLocalStorage } from '../../'; +import { SplitFactory, InLocalStorage } from '../..'; import { settingsValidator } from '../../settings'; const userKey = 'nicolas@split.io'; diff --git a/src/__tests__/push/push-fallbacking.spec.js b/src/__tests__/browserSuites/push-fallbacking.spec.js similarity index 100% rename from src/__tests__/push/push-fallbacking.spec.js rename to src/__tests__/browserSuites/push-fallbacking.spec.js diff --git a/src/__tests__/push/push-initialization-nopush.spec.js b/src/__tests__/browserSuites/push-initialization-nopush.spec.js similarity index 100% rename from src/__tests__/push/push-initialization-nopush.spec.js rename to src/__tests__/browserSuites/push-initialization-nopush.spec.js diff --git a/src/__tests__/push/push-initialization-retries.spec.js b/src/__tests__/browserSuites/push-initialization-retries.spec.js similarity index 100% rename from src/__tests__/push/push-initialization-retries.spec.js rename to src/__tests__/browserSuites/push-initialization-retries.spec.js diff --git a/src/__tests__/push/push-refresh-token.spec.js b/src/__tests__/browserSuites/push-refresh-token.spec.js similarity index 100% rename from src/__tests__/push/push-refresh-token.spec.js rename to src/__tests__/browserSuites/push-refresh-token.spec.js diff --git a/src/__tests__/push/push-synchronization-retries.spec.js b/src/__tests__/browserSuites/push-synchronization-retries.spec.js similarity index 100% rename from src/__tests__/push/push-synchronization-retries.spec.js rename to src/__tests__/browserSuites/push-synchronization-retries.spec.js diff --git a/src/__tests__/push/push-synchronization.spec.js b/src/__tests__/browserSuites/push-synchronization.spec.js similarity index 100% rename from src/__tests__/push/push-synchronization.spec.js rename to src/__tests__/browserSuites/push-synchronization.spec.js diff --git a/src/__tests__/online/readiness.spec.js b/src/__tests__/browserSuites/readiness.spec.js similarity index 100% rename from src/__tests__/online/readiness.spec.js rename to src/__tests__/browserSuites/readiness.spec.js diff --git a/src/__tests__/online/ready-from-cache.spec.js b/src/__tests__/browserSuites/ready-from-cache.spec.js similarity index 100% rename from src/__tests__/online/ready-from-cache.spec.js rename to src/__tests__/browserSuites/ready-from-cache.spec.js diff --git a/src/__tests__/online/ready-promise.spec.js b/src/__tests__/browserSuites/ready-promise.spec.js similarity index 100% rename from src/__tests__/online/ready-promise.spec.js rename to src/__tests__/browserSuites/ready-promise.spec.js diff --git a/src/__tests__/online/shared-instantiation.spec.js b/src/__tests__/browserSuites/shared-instantiation.spec.js similarity index 100% rename from src/__tests__/online/shared-instantiation.spec.js rename to src/__tests__/browserSuites/shared-instantiation.spec.js diff --git a/src/__tests__/online/telemetry.spec.js b/src/__tests__/browserSuites/telemetry.spec.js similarity index 100% rename from src/__tests__/online/telemetry.spec.js rename to src/__tests__/browserSuites/telemetry.spec.js diff --git a/src/__tests__/online/use-beacon-api.debug.spec.js b/src/__tests__/browserSuites/use-beacon-api.debug.spec.js similarity index 100% rename from src/__tests__/online/use-beacon-api.debug.spec.js rename to src/__tests__/browserSuites/use-beacon-api.debug.spec.js diff --git a/src/__tests__/online/use-beacon-api.spec.js b/src/__tests__/browserSuites/use-beacon-api.spec.js similarity index 100% rename from src/__tests__/online/use-beacon-api.spec.js rename to src/__tests__/browserSuites/use-beacon-api.spec.js diff --git a/src/__tests__/online/user-consent.spec.js b/src/__tests__/browserSuites/user-consent.spec.js similarity index 100% rename from src/__tests__/online/user-consent.spec.js rename to src/__tests__/browserSuites/user-consent.spec.js diff --git a/src/__tests__/errors/browser.spec.js b/src/__tests__/errorCatching/browser.spec.js similarity index 100% rename from src/__tests__/errors/browser.spec.js rename to src/__tests__/errorCatching/browser.spec.js diff --git a/src/__tests__/offline/browser.spec.js b/src/__tests__/offline/browser.spec.js index 892d277..05dabd6 100644 --- a/src/__tests__/offline/browser.spec.js +++ b/src/__tests__/offline/browser.spec.js @@ -32,8 +32,6 @@ const configMocks = () => { fetchMock.mock(url(settings, '/events/bulk'), () => replySpy(spyEventsBulk)); fetchMock.mock(url(settings, '/testImpressions/bulk'), () => replySpy(spyTestImpressionsBulk)); fetchMock.mock(url(settings, '/testImpressions/count'), () => replySpy(spyTestImpressionsCount)); - fetchMock.mock(url(settings, '/metrics/times'), () => replySpy(spyMetricsTimes)); - fetchMock.mock(url(settings, '/metrics/counters'), () => replySpy(spyMetricsCounters)); fetchMock.mock('*', () => replySpy(spyAny)); }; diff --git a/src/__tests__/online/browser.spec.js b/src/__tests__/online/browser.spec.js index 00a165c..8d2afd6 100644 --- a/src/__tests__/online/browser.spec.js +++ b/src/__tests__/online/browser.spec.js @@ -1,22 +1,22 @@ import tape from 'tape-catch'; import fetchMock from '../testUtils/fetchMock'; import { url } from '../testUtils'; -import evaluationsSuite from './evaluations.spec'; -import impressionsSuite from './impressions.spec'; -import impressionsSuiteDebug from './impressions.debug.spec'; -import telemetrySuite from './telemetry.spec'; -import impressionsListenerSuite from './impressions-listener.spec'; -import readinessSuite from './readiness.spec'; -import readyFromCache from './ready-from-cache.spec'; -import { withoutBindingTT /*, bindingTT */ } from './events.spec'; -import sharedInstantiationSuite from './shared-instantiation.spec'; -import managerSuite from './manager.spec'; -import ignoreIpAddressesSettingSuite from './ignore-ip-addresses-setting.spec'; -import useBeaconApiSuite from './use-beacon-api.spec'; -import useBeaconDebugApiSuite from './use-beacon-api.debug.spec'; -import readyPromiseSuite from './ready-promise.spec'; -import fetchSpecificSplits from './fetch-specific-splits.spec'; -import userConsent from './user-consent.spec'; +import evaluationsSuite from '../browserSuites/evaluations.spec'; +import impressionsSuite from '../browserSuites/impressions.spec'; +import impressionsSuiteDebug from '../browserSuites/impressions.debug.spec'; +import telemetrySuite from '../browserSuites/telemetry.spec'; +import impressionsListenerSuite from '../browserSuites/impressions-listener.spec'; +import readinessSuite from '../browserSuites/readiness.spec'; +import readyFromCache from '../browserSuites/ready-from-cache.spec'; +import { withoutBindingTT /*, bindingTT */ } from '../browserSuites/events.spec'; +import sharedInstantiationSuite from '../browserSuites/shared-instantiation.spec'; +import managerSuite from '../browserSuites/manager.spec'; +import ignoreIpAddressesSettingSuite from '../browserSuites/ignore-ip-addresses-setting.spec'; +import useBeaconApiSuite from '../browserSuites/use-beacon-api.spec'; +import useBeaconDebugApiSuite from '../browserSuites/use-beacon-api.debug.spec'; +import readyPromiseSuite from '../browserSuites/ready-promise.spec'; +import fetchSpecificSplits from '../browserSuites/fetch-specific-splits.spec'; +import userConsent from '../browserSuites/user-consent.spec'; import { settingsValidator } from '../../settings'; import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; diff --git a/src/__tests__/push/browser.spec.js b/src/__tests__/push/browser.spec.js index bcc033a..f4d5103 100644 --- a/src/__tests__/push/browser.spec.js +++ b/src/__tests__/push/browser.spec.js @@ -1,12 +1,12 @@ import tape from 'tape-catch'; import fetchMock from '../testUtils/fetchMock'; -import { testAuthWithPushDisabled, testAuthWith401, testNoEventSource, testSSEWithNonRetryableError } from './push-initialization-nopush.spec'; -import { testPushRetriesDueToAuthErrors, testPushRetriesDueToSseErrors, testSdkDestroyWhileAuthRetries, testSdkDestroyWhileAuthSuccess, testSdkDestroyWhileConnDelay } from './push-initialization-retries.spec'; -import { testSynchronization } from './push-synchronization.spec'; -import { testSynchronizationRetries } from './push-synchronization-retries.spec'; -import { testFallbacking } from './push-fallbacking.spec'; -import { testRefreshToken } from './push-refresh-token.spec'; -import { testSplitKillOnReadyFromCache } from './push-corner-cases.spec'; +import { testAuthWithPushDisabled, testAuthWith401, testNoEventSource, testSSEWithNonRetryableError } from '../browserSuites/push-initialization-nopush.spec'; +import { testPushRetriesDueToAuthErrors, testPushRetriesDueToSseErrors, testSdkDestroyWhileAuthRetries, testSdkDestroyWhileAuthSuccess, testSdkDestroyWhileConnDelay } from '../browserSuites/push-initialization-retries.spec'; +import { testSynchronization } from '../browserSuites/push-synchronization.spec'; +import { testSynchronizationRetries } from '../browserSuites/push-synchronization-retries.spec'; +import { testFallbacking } from '../browserSuites/push-fallbacking.spec'; +import { testRefreshToken } from '../browserSuites/push-refresh-token.spec'; +import { testSplitKillOnReadyFromCache } from '../browserSuites/push-corner-cases.spec'; fetchMock.config.overwriteRoutes = false; Math.random = () => 0.5; // SDKs without telemetry From bfc21e9251a927dc6b9d97328257242e09d1907e Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 28 Jul 2022 16:41:15 -0300 Subject: [PATCH 02/23] polishing and renames --- karma/e2e.consumer.karma.conf.js | 6 +- ...onf.js => e2e.errorCatching.karma.conf.js} | 4 +- ...onf.js => e2e.gaIntegration.karma.conf.js} | 0 package.json | 6 +- .../browserSuites/evaluations.spec.js | 1 - src/__tests__/browserSuites/events.spec.js | 1 + .../browserSuites/push-corner-cases.spec.js | 4 +- .../browserSuites/push-fallbacking.spec.js | 90 +++++++++++-------- .../browserSuites/push-refresh-token.spec.js | 2 +- .../push-synchronization.spec.js | 6 +- .../browserSuites/ready-from-cache.spec.js | 4 +- .../browserSuites/ready-promise.spec.js | 3 +- .../shared-instantiation.spec.js | 12 +-- .../browserSuites/single-sync.spec.js | 65 ++++++++++++++ .../use-beacon-api.debug.spec.js | 3 +- .../browserSuites/use-beacon-api.spec.js | 3 +- .../browserSuites/user-consent.spec.js | 3 +- .../browser_consumer.spec.js | 0 .../browser_consumer_partial.spec.js | 0 .../wrapper-commands.js | 0 .../gaIntegration/both-integrations.spec.js | 2 +- .../gaIntegration/ga-to-split.spec.js | 2 +- .../mocks/message.STREAMING_RESET.json | 2 +- src/__tests__/offline/browser.spec.js | 2 +- src/__tests__/online/browser.spec.js | 3 + src/__tests__/testUtils/browser.js | 19 ++++ src/__tests__/testUtils/index.js | 20 ----- 27 files changed, 176 insertions(+), 87 deletions(-) rename karma/{e2e.errors.karma.conf.js => e2e.errorCatching.karma.conf.js} (80%) rename karma/{e2e.gaintegration.karma.conf.js => e2e.gaIntegration.karma.conf.js} (100%) create mode 100644 src/__tests__/browserSuites/single-sync.spec.js rename src/__tests__/{consumerMode => consumer}/browser_consumer.spec.js (100%) rename src/__tests__/{consumerMode => consumer}/browser_consumer_partial.spec.js (100%) rename src/__tests__/{consumerMode => consumer}/wrapper-commands.js (100%) create mode 100644 src/__tests__/testUtils/browser.js diff --git a/karma/e2e.consumer.karma.conf.js b/karma/e2e.consumer.karma.conf.js index bd39c5a..68791c4 100644 --- a/karma/e2e.consumer.karma.conf.js +++ b/karma/e2e.consumer.karma.conf.js @@ -6,12 +6,12 @@ module.exports = function(config) { config.set(assign({}, require('./config'), { // list of files / patterns to load in the browser files: [ - '__tests__/consumerMode/browser_consumer.spec.js', - '__tests__/consumerMode/browser_consumer_partial.spec.js' + '__tests__/consumer/browser_consumer.spec.js', + '__tests__/consumer/browser_consumer_partial.spec.js' ], // prepare code for the browser using rollup preprocessors: { - '__tests__/consumerMode/*.spec.js': ['rollup'] + '__tests__/consumer/*.spec.js': ['rollup'] }, // level of logging diff --git a/karma/e2e.errors.karma.conf.js b/karma/e2e.errorCatching.karma.conf.js similarity index 80% rename from karma/e2e.errors.karma.conf.js rename to karma/e2e.errorCatching.karma.conf.js index 0010be8..69863c8 100644 --- a/karma/e2e.errors.karma.conf.js +++ b/karma/e2e.errorCatching.karma.conf.js @@ -6,11 +6,11 @@ module.exports = function(config) { config.set(assign({}, require('./config'), { // list of files / patterns to load in the browser files: [ - '__tests__/errors/browser.spec.js' + '__tests__/errorCatching/browser.spec.js' ], // prepare code for the browser using rollup preprocessors: { - '__tests__/errors/browser.spec.js': ['rollup'] + '__tests__/errorCatching/browser.spec.js': ['rollup'] }, // level of logging diff --git a/karma/e2e.gaintegration.karma.conf.js b/karma/e2e.gaIntegration.karma.conf.js similarity index 100% rename from karma/e2e.gaintegration.karma.conf.js rename to karma/e2e.gaIntegration.karma.conf.js diff --git a/package.json b/package.json index dcb575e..86f79ad 100644 --- a/package.json +++ b/package.json @@ -30,14 +30,14 @@ "build:ga-to-split-autorequire": "terser ./node_modules/@splitsoftware/splitio-commons/src/integrations/ga/autoRequire.js --mangle --output ./scripts/ga-to-split-autorequire.js", "test": "npm run test:unit && npm run test:e2e", "test:unit": "jest", - "test:e2e": "npm run test:e2e-logger && npm run test:e2e-offline && npm run test:e2e-online && npm run test:e2e-destroy && npm run test:e2e-errors && npm run test:e2e-push && npm run test:e2e-gaintegration && npm run test:e2e-consumer", + "test:e2e": "npm run test:e2e-logger && npm run test:e2e-offline && npm run test:e2e-online && npm run test:e2e-destroy && npm run test:e2e-errorCatching && npm run test:e2e-push && npm run test:e2e-gaIntegration && npm run test:e2e-consumer", "test:e2e-logger": "karma start karma/e2e.logger.karma.conf.js", "test:e2e-offline": "karma start karma/e2e.offline.karma.conf.js", "test:e2e-online": "karma start karma/e2e.online.karma.conf.js", "test:e2e-destroy": "karma start karma/e2e.destroy.karma.conf.js", - "test:e2e-errors": "karma start karma/e2e.errors.karma.conf.js", + "test:e2e-errorCatching": "karma start karma/e2e.errorCatching.karma.conf.js", "test:e2e-push": "karma start karma/e2e.push.karma.conf.js", - "test:e2e-gaintegration": "karma start karma/e2e.gaintegration.karma.conf.js", + "test:e2e-gaIntegration": "karma start karma/e2e.gaIntegration.karma.conf.js", "test:e2e-consumer": "karma start karma/e2e.consumer.karma.conf.js", "pretest-ts-decls": "npm run build:esm && npm run build:cjs && npm link", "test-ts-decls": "./scripts/ts-tests.sh", diff --git a/src/__tests__/browserSuites/evaluations.spec.js b/src/__tests__/browserSuites/evaluations.spec.js index c084dc9..fe182f2 100644 --- a/src/__tests__/browserSuites/evaluations.spec.js +++ b/src/__tests__/browserSuites/evaluations.spec.js @@ -362,7 +362,6 @@ export default function (config, fetchMock, assert) { }; - for (i; i < SDK_INSTANCES_TO_TEST; i++) { let splitio = SplitFactory(config); diff --git a/src/__tests__/browserSuites/events.spec.js b/src/__tests__/browserSuites/events.spec.js index e98c7cb..9e08f4d 100644 --- a/src/__tests__/browserSuites/events.spec.js +++ b/src/__tests__/browserSuites/events.spec.js @@ -93,6 +93,7 @@ export function withoutBindingTT(fetchMock, assert) { assert.notOk(client.track('othertraffictype', 'my.checkout.event', null, 'asd'), 'client.track returns false if an event properties was incorrect and it could not be added to the queue.'); } +// Not for JS Browser SDK, because it doesn't let bind traffic types to clients export function bindingTT(fetchMock, assert) { const localSettings = Object.assign({}, baseSettings); localSettings.core.trafficType = 'binded_tt'; diff --git a/src/__tests__/browserSuites/push-corner-cases.spec.js b/src/__tests__/browserSuites/push-corner-cases.spec.js index e130c1d..0fc203d 100644 --- a/src/__tests__/browserSuites/push-corner-cases.spec.js +++ b/src/__tests__/browserSuites/push-corner-cases.spec.js @@ -7,7 +7,7 @@ import { nearlyEqual, url } from '../testUtils'; import EventSourceMock, { setMockListener } from '../testUtils/eventSourceMock'; window.EventSource = EventSourceMock; -import { SplitFactory, InLocalStorage } from '../..'; +import { SplitFactory, InLocalStorage } from '../../index'; import { settingsValidator } from '../../settings'; const userKey = 'nicolas@split.io'; @@ -95,6 +95,6 @@ export function testSplitKillOnReadyFromCache(fetchMock, assert) { const lapse = Date.now() - start; assert.true(nearlyEqual(lapse, MILLIS_SPLIT_CHANGES_RESPONSE), 'SDK_READY once split changes arrives'); - client.destroy().then(()=> { assert.end();}); + client.destroy().then(() => { assert.end(); }); }); } diff --git a/src/__tests__/browserSuites/push-fallbacking.spec.js b/src/__tests__/browserSuites/push-fallbacking.spec.js index 3410126..5549eab 100644 --- a/src/__tests__/browserSuites/push-fallbacking.spec.js +++ b/src/__tests__/browserSuites/push-fallbacking.spec.js @@ -16,6 +16,7 @@ import occupancy0ControlSecMessage from '../mocks/message.OCCUPANCY.0.control_se import streamingPausedControlPriMessage from '../mocks/message.CONTROL.STREAMING_PAUSED.control_pri.1586987434750.json'; import streamingResumedControlPriMessage from '../mocks/message.CONTROL.STREAMING_RESUMED.control_pri.1586987434850.json'; +import streamingPausedControlPriMessage2 from '../mocks/message.CONTROL.STREAMING_PAUSED.control_pri.1586987434900.json'; import streamingDisabledControlPriMessage from '../mocks/message.CONTROL.STREAMING_DISABLED.control_pri.1586987434950.json'; import splitUpdateMessage from '../mocks/message.SPLIT_UPDATE.1457552649999.json'; @@ -24,6 +25,8 @@ import mySegmentsUpdateMessage from '../mocks/message.MY_SEGMENTS_UPDATE.nicolas import authPushEnabledNicolas from '../mocks/auth.pushEnabled.nicolas@split.io.json'; import authPushEnabledNicolasAndMarcio from '../mocks/auth.pushEnabled.nicolas@split.io.marcio@split.io.json'; +import streamingResetMessage from '../mocks/message.STREAMING_RESET.json'; + import { nearlyEqual, url } from '../testUtils'; import EventSourceMock, { setMockListener } from '../testUtils/eventSourceMock'; @@ -34,7 +37,6 @@ import { settingsValidator } from '../../settings'; const userKey = 'nicolas@split.io'; const secondUserKey = 'marcio@split.io'; -const thirdUserKey = 'facundo@split.io'; const baseUrls = { sdk: 'https://sdk.push-fallbacking/api', @@ -68,7 +70,11 @@ const MILLIS_STREAMING_PAUSED_CONTROL = MILLIS_SPLIT_UPDATE_EVENT_DURING_PUSH + const MILLIS_MY_SEGMENTS_UPDATE_EVENT_DURING_POLLING = MILLIS_STREAMING_PAUSED_CONTROL + 100; const MILLIS_STREAMING_RESUMED_CONTROL = MILLIS_STREAMING_PAUSED_CONTROL + settings.scheduler.featuresRefreshRate + 100; const MILLIS_MY_SEGMENTS_UPDATE_EVENT_DURING_PUSH = MILLIS_STREAMING_RESUMED_CONTROL + 100; -const MILLIS_STREAMING_DISABLED_CONTROL = MILLIS_MY_SEGMENTS_UPDATE_EVENT_DURING_PUSH + 100; + +const MILLIS_STREAMING_PAUSED_CONTROL_2 = MILLIS_MY_SEGMENTS_UPDATE_EVENT_DURING_PUSH + 100; +const MILLIS_STREAMING_RESET_WHILE_PUSH_DOWN = MILLIS_STREAMING_PAUSED_CONTROL_2 + 100; +const MILLIS_STREAMING_RESET_WHILE_PUSH_UP = MILLIS_STREAMING_RESET_WHILE_PUSH_DOWN + settings.scheduler.featuresRefreshRate; +const MILLIS_STREAMING_DISABLED_CONTROL = MILLIS_STREAMING_RESET_WHILE_PUSH_UP + 100; const MILLIS_DESTROY = MILLIS_STREAMING_DISABLED_CONTROL + settings.scheduler.featuresRefreshRate * 2 + 100; /** @@ -83,26 +89,27 @@ const MILLIS_DESTROY = MILLIS_STREAMING_DISABLED_CONTROL + settings.scheduler.fe * 0.55 secs: create a new client while streaming -> initial fetch (/mySegments/marcio), auth, SSE connection and syncAll (/splitChanges, /mySegments/nicolas, /mySegments/marcio) * 0.6 secs: SPLIT_UPDATE event -> /splitChanges * 0.7 secs: Streaming down (CONTROL event) -> fetch due to fallback to polling (/splitChanges, /mySegments/nicolas, /mySegments/marcio) - * 0.7 secs: create a new client while polling -> initial fetch (/mySegments/facundo), auth fail (continue polling) * 0.8 secs: MY_SEGMENTS_UPDATE event ignored * 0.9 secs: periodic fetch due to polling (/splitChanges) * 0.95 secs: periodic fetch due to polling (/mySegments/nicolas, /mySegments/marcio, /mySegments/facundo) * 1.0 secs: Streaming up (CONTROL event) -> syncAll (/splitChanges, /mySegments/nicolas, /mySegments/marcio, /mySegments/facundo) * 1.1 secs: MY_SEGMENTS_UPDATE event -> /mySegments/nicolas * 1.2 secs: Streaming down (CONTROL event) -> fetch due to fallback to polling (/splitChanges, /mySegments/nicolas, /mySegments/marcio, /mySegments/facundo) - * 1.4 secs: periodic fetch due to polling (/splitChanges): due to update without segments, mySegments are not fetched - * 1.6 secs: periodic fetch due to polling (/splitChanges) - * 1.7 secs: destroy client + * 1.3 secs: STREAMING_RESET control event -> auth, SSE connection, syncAll and stop polling + * 1.5 secs: STREAMING_RESET control event -> auth, SSE connection, syncAll + * 1.6 secs: Streaming closed (CONTROL STREAMING_DISABLED event) -> fetch due to fallback to polling (/splitChanges, /mySegments/nicolas, /mySegments/marcio, /mySegments/facundo) + * 1.8 secs: periodic fetch due to polling (/splitChanges): due to update without segments, mySegments are not fetched + * 2.0 secs: periodic fetch due to polling (/splitChanges) + * 2.1 secs: destroy client */ export function testFallbacking(fetchMock, assert) { - assert.plan(16); + assert.plan(20); fetchMock.reset(); - let start, splitio, client; - let secondClient, thirdClient; + let start, splitio, client, secondClient; // mock SSE open and message events - setMockListener(function (eventSourceInstance) { + setMockListener((eventSourceInstance) => { const expectedSSEurl = `${url(settings, '/sse')}?channels=NzM2MDI5Mzc0_NDEzMjQ1MzA0Nw%3D%3D_NTcwOTc3MDQx_mySegments,NzM2MDI5Mzc0_NDEzMjQ1MzA0Nw%3D%3D_splits,%5B%3Foccupancy%3Dmetrics.publishers%5Dcontrol_pri,%5B%3Foccupancy%3Dmetrics.publishers%5Dcontrol_sec&accessToken=${authPushEnabledNicolas.token}&v=1.1&heartbeats=true&SplitSDKVersion=${settings.version}&SplitSDKClientKey=h-1>`; assert.equals(eventSourceInstance.url, expectedSSEurl, 'EventSource URL is the expected'); @@ -118,6 +125,7 @@ export function testFallbacking(fetchMock, assert) { }, MILLIS_STREAMING_DOWN_OCCUPANCY); // send an OCCUPANCY event for switching to polling setTimeout(() => { + assert.equal(eventSourceInstance.readyState, EventSourceMock.OPEN, 'EventSource connection keeps opened after PUSH_SUBSYSTEM_DOWN (occupancy 0)'); eventSourceInstance.emitMessage(splitUpdateMessage); }, MILLIS_SPLIT_UPDATE_EVENT_DURING_POLLING); // send a SPLIT_UPDATE event while polling, to check that we are ignoring it @@ -126,10 +134,9 @@ export function testFallbacking(fetchMock, assert) { }, MILLIS_STREAMING_UP_OCCUPANCY); // send a OCCUPANCY event for switching to push setTimeout(() => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars secondClient = splitio.client(secondUserKey); - setMockListener(function (eventSourceInstance) { + setMockListener((eventSourceInstance) => { const expectedSSEurl = `${url(settings, '/sse')}?channels=NzM2MDI5Mzc0_NDEzMjQ1MzA0Nw%3D%3D_MjE0MTkxOTU2Mg%3D%3D_mySegments,NzM2MDI5Mzc0_NDEzMjQ1MzA0Nw%3D%3D_NTcwOTc3MDQx_mySegments,NzM2MDI5Mzc0_NDEzMjQ1MzA0Nw%3D%3D_splits,%5B%3Foccupancy%3Dmetrics.publishers%5Dcontrol_pri,%5B%3Foccupancy%3Dmetrics.publishers%5Dcontrol_sec&accessToken=${authPushEnabledNicolasAndMarcio.token}&v=1.1&heartbeats=true&SplitSDKVersion=${settings.version}&SplitSDKClientKey=h-1>`; assert.equals(eventSourceInstance.url, expectedSSEurl, 'new EventSource URL is the expected'); eventSourceInstance.emitOpen(); @@ -144,11 +151,10 @@ export function testFallbacking(fetchMock, assert) { setTimeout(() => { eventSourceInstance.emitMessage(streamingPausedControlPriMessage); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - thirdClient = splitio.client(thirdUserKey); }, MILLIS_STREAMING_PAUSED_CONTROL - MILLIS_CREATE_CLIENT_DURING_PUSH); // send a CONTROL event for switching to polling setTimeout(() => { + assert.equal(eventSourceInstance.readyState, EventSourceMock.OPEN, 'EventSource connection keeps opened after PUSH_SUBSYSTEM_DOWN (STREAMING_PAUSED event)'); eventSourceInstance.emitMessage(mySegmentsUpdateMessage); }, MILLIS_MY_SEGMENTS_UPDATE_EVENT_DURING_POLLING - MILLIS_CREATE_CLIENT_DURING_PUSH); // send a MY_SEGMENTS_UPDATE event while polling, to check that we are ignoring it @@ -165,15 +171,35 @@ export function testFallbacking(fetchMock, assert) { }, MILLIS_MY_SEGMENTS_UPDATE_EVENT_DURING_PUSH - MILLIS_CREATE_CLIENT_DURING_PUSH); // send a MY_SEGMENTS_UPDATE event setTimeout(() => { - eventSourceInstance.emitMessage(streamingDisabledControlPriMessage); - assert.equal(eventSourceInstance.readyState, EventSourceMock.CLOSED, 'EventSource connection closed on STREAMING_DISABLED CONTROL event'); - }, MILLIS_STREAMING_DISABLED_CONTROL - MILLIS_CREATE_CLIENT_DURING_PUSH); // send a CONTROL event for disabling push and switching to polling + eventSourceInstance.emitMessage(streamingPausedControlPriMessage2); + }, MILLIS_STREAMING_PAUSED_CONTROL_2 - MILLIS_CREATE_CLIENT_DURING_PUSH); // send a CONTROL event for switching back to polling setTimeout(() => { - client.destroy().then(() => { - assert.pass('client destroyed'); + eventSourceInstance.emitMessage(streamingResetMessage); + + setMockListener((eventSourceInstance) => { + eventSourceInstance.emitOpen(); + + setTimeout(() => { + eventSourceInstance.emitMessage(streamingResetMessage); + + setMockListener((eventSourceInstance) => { + eventSourceInstance.emitOpen(); + + setTimeout(() => { + eventSourceInstance.emitMessage(streamingDisabledControlPriMessage); + assert.equal(eventSourceInstance.readyState, EventSourceMock.CLOSED, 'EventSource connection closed on STREAMING_DISABLED CONTROL event'); + }, MILLIS_STREAMING_DISABLED_CONTROL - MILLIS_STREAMING_RESET_WHILE_PUSH_UP); // send a CONTROL event for disabling push and switching to polling + + setTimeout(() => { + Promise.all([secondClient.destroy(), client.destroy()]).then(() => { + assert.pass('client destroyed'); + }); + }, MILLIS_DESTROY - MILLIS_STREAMING_RESET_WHILE_PUSH_UP); // destroy client + }); + }, MILLIS_STREAMING_RESET_WHILE_PUSH_UP - MILLIS_STREAMING_RESET_WHILE_PUSH_DOWN); // send a new STREAMING_RESET event while PUSH is up }); - }, MILLIS_DESTROY - MILLIS_CREATE_CLIENT_DURING_PUSH); // destroy client after 1.7 seconds + }, MILLIS_STREAMING_RESET_WHILE_PUSH_DOWN - MILLIS_CREATE_CLIENT_DURING_PUSH); // send a STREAMING_RESET event while PUSH is down, for re-connecting push }); @@ -211,7 +237,7 @@ export function testFallbacking(fetchMock, assert) { // creating of second client during streaming: initial mysegment sync, reauth and syncAll due to new client fetchMock.getOnce(url(settings, '/mySegments/marcio%40split.io'), { status: 200, body: mySegmentsMarcio }); - fetchMock.getOnce(url(settings, `/v2/auth?users=${encodeURIComponent(userKey)}&users=${encodeURIComponent(secondUserKey)}`), function (url, opts) { + fetchMock.get({ url: url(settings, `/v2/auth?users=${encodeURIComponent(userKey)}&users=${encodeURIComponent(secondUserKey)}`), repeat: 3 /* initial + 2 STREAMING_RESET */ }, (url, opts) => { if (!opts.headers['Authorization']) assert.fail('`/v2/auth` request must include `Authorization` header'); assert.pass('second auth success'); return { status: 200, body: authPushEnabledNicolasAndMarcio }; @@ -232,11 +258,6 @@ export function testFallbacking(fetchMock, assert) { fetchMock.getOnce(url(settings, '/mySegments/nicolas%40split.io'), { status: 200, body: mySegmentsNicolasMock1 }); fetchMock.getOnce(url(settings, '/mySegments/marcio%40split.io'), { status: 200, body: mySegmentsMarcio }); - // creation of third client during polling: initial mysegment sync and authentication - fetchMock.getOnce(url(settings, '/mySegments/facundo%40split.io'), { status: 200, body: mySegmentsMarcio }); - // authentication fail, so we keep polling. next auth attempt is scheduled in one second (after the test finishes) - fetchMock.getOnce(url(settings, `/v2/auth?users=${encodeURIComponent(userKey)}&users=${encodeURIComponent(secondUserKey)}&users=${encodeURIComponent(thirdUserKey)}`), { throws: new TypeError('Network error') }); - // continue fetches due to second fallback to polling fetchMock.getOnce(url(settings, '/splitChanges?since=1457552649999'), function () { const lapse = Date.now() - start; @@ -245,13 +266,11 @@ export function testFallbacking(fetchMock, assert) { }); fetchMock.getOnce(url(settings, '/mySegments/nicolas%40split.io'), { status: 200, body: mySegmentsNicolasMock1 }); fetchMock.getOnce(url(settings, '/mySegments/marcio%40split.io'), { status: 200, body: mySegmentsMarcio }); - fetchMock.getOnce(url(settings, '/mySegments/facundo%40split.io'), { status: 200, body: mySegmentsMarcio }); // split and segment sync due to streaming up (CONTROL event) fetchMock.getOnce(url(settings, '/splitChanges?since=1457552649999'), { status: 200, body: { splits: [], since: 1457552649999, till: 1457552649999 } }); fetchMock.getOnce(url(settings, '/mySegments/nicolas%40split.io'), { status: 200, body: mySegmentsNicolasMock1 }); fetchMock.getOnce(url(settings, '/mySegments/marcio%40split.io'), { status: 200, body: mySegmentsMarcio }); - fetchMock.getOnce(url(settings, '/mySegments/facundo%40split.io'), { status: 200, body: mySegmentsMarcio }); // fetch due to MY_SEGMENTS_UPDATE event fetchMock.getOnce(url(settings, '/mySegments/nicolas%40split.io'), function () { @@ -260,19 +279,20 @@ export function testFallbacking(fetchMock, assert) { return { status: 200, body: mySegmentsNicolasMock2 }; }); - // fetches due to third fallback to polling (mySegments is not fetched after the first iteration) - fetchMock.getOnce(url(settings, '/splitChanges?since=1457552649999'), { status: 200, body: { splits: [], since: 1457552649999, till: 1457552649999 } }); - fetchMock.getOnce(url(settings, '/mySegments/nicolas%40split.io'), { status: 200, body: mySegmentsNicolasMock1 }); - fetchMock.getOnce(url(settings, '/mySegments/marcio%40split.io'), { status: 200, body: mySegmentsMarcio }); - fetchMock.getOnce(url(settings, '/mySegments/facundo%40split.io'), { status: 200, body: mySegmentsMarcio }); + // fetches due to third fallback to polling (STREAMING_PAUSED), two sync all (two STREAMING_RESET events) and fourth fallback (STREAMING_DISABLED) + fetchMock.get({ url: url(settings, '/splitChanges?since=1457552649999'), repeat: 4 }, { status: 200, body: { splits: [], since: 1457552649999, till: 1457552649999 } }); + fetchMock.get({ url: url(settings, '/mySegments/nicolas%40split.io'), repeat: 4 }, { status: 200, body: mySegmentsNicolasMock1 }); + fetchMock.get({ url: url(settings, '/mySegments/marcio%40split.io'), repeat: 4 }, { status: 200, body: mySegmentsMarcio }); + + // Periodic fetch due to polling (mySegments is not fetched due to smart pausing) fetchMock.getOnce(url(settings, '/splitChanges?since=1457552649999'), function () { const lapse = Date.now() - start; - assert.true(nearlyEqual(lapse, MILLIS_STREAMING_DISABLED_CONTROL + settings.scheduler.featuresRefreshRate), 'fetch due to third fallback to polling'); + assert.true(nearlyEqual(lapse, MILLIS_STREAMING_DISABLED_CONTROL + settings.scheduler.featuresRefreshRate, 75), 'fetch due to fourth fallback to polling'); return { status: 200, body: splitChangesMock3 }; }); fetchMock.getOnce(url(settings, '/splitChanges?since=1457552669999'), function () { const lapse = Date.now() - start; - assert.true(nearlyEqual(lapse, MILLIS_STREAMING_DISABLED_CONTROL + settings.scheduler.featuresRefreshRate * 2), 'fetch due to third fallback to polling'); + assert.true(nearlyEqual(lapse, MILLIS_STREAMING_DISABLED_CONTROL + settings.scheduler.featuresRefreshRate * 2, 75), 'fetch due to fourth fallback to polling'); return { status: 200, body: { splits: [], since: 1457552669999, till: 1457552669999 } }; }); diff --git a/src/__tests__/browserSuites/push-refresh-token.spec.js b/src/__tests__/browserSuites/push-refresh-token.spec.js index 39a0b24..b4ebf8e 100644 --- a/src/__tests__/browserSuites/push-refresh-token.spec.js +++ b/src/__tests__/browserSuites/push-refresh-token.spec.js @@ -6,7 +6,7 @@ import authPushDisabled from '../mocks/auth.pushDisabled.json'; import { nearlyEqual, url } from '../testUtils'; -// Polyfill EventSource with mock +// Replace global EventSource with mock import EventSourceMock, { setMockListener } from '../testUtils/eventSourceMock'; window.EventSource = EventSourceMock; diff --git a/src/__tests__/browserSuites/push-synchronization.spec.js b/src/__tests__/browserSuites/push-synchronization.spec.js index 4f5d01a..e0edb94 100644 --- a/src/__tests__/browserSuites/push-synchronization.spec.js +++ b/src/__tests__/browserSuites/push-synchronization.spec.js @@ -21,14 +21,15 @@ import segmentRemovalMessage from '../mocks/message.V2.SEGMENT_REMOVAL.145755265 import authPushEnabledNicolas from '../mocks/auth.pushEnabled.nicolas@split.io.json'; import authPushEnabledNicolasAndMarcio from '../mocks/auth.pushEnabled.nicolas@split.io.marcio@split.io.json'; -import { nearlyEqual, url, hasNoCacheHeader, triggerUnloadEvent } from '../testUtils'; +import { nearlyEqual, url, hasNoCacheHeader } from '../testUtils'; +import { triggerUnloadEvent } from '../testUtils/browser'; import includes from 'lodash/includes'; // Replace original EventSource with mock import EventSourceMock, { setMockListener } from '../testUtils/eventSourceMock'; window.EventSource = EventSourceMock; -import { SplitFactory, DebugLogger } from '../../index'; +import { SplitFactory } from '../../index'; import { settingsValidator } from '../../settings'; const userKey = 'nicolas@split.io'; @@ -49,7 +50,6 @@ const config = { }, urls: baseUrls, streamingEnabled: true, - debug: DebugLogger(), }; const settings = settingsValidator(config); diff --git a/src/__tests__/browserSuites/ready-from-cache.spec.js b/src/__tests__/browserSuites/ready-from-cache.spec.js index 7c5c0d9..f037528 100644 --- a/src/__tests__/browserSuites/ready-from-cache.spec.js +++ b/src/__tests__/browserSuites/ready-from-cache.spec.js @@ -113,11 +113,11 @@ export default function (fetchMock, assert) { const client2 = splitio.client('nicolas2@split.io'); const client3 = splitio.client('nicolas3@split.io'); - client.on(client.Event.SDK_READY_TIMED_OUT, () => { + client.once(client.Event.SDK_READY_TIMED_OUT, () => { t.fail('It should not timeout in this scenario.'); t.end(); }); - client.on(client.Event.SDK_READY_FROM_CACHE, () => { + 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(); }); diff --git a/src/__tests__/browserSuites/ready-promise.spec.js b/src/__tests__/browserSuites/ready-promise.spec.js index 0a35a4d..dde9a21 100644 --- a/src/__tests__/browserSuites/ready-promise.spec.js +++ b/src/__tests__/browserSuites/ready-promise.spec.js @@ -546,12 +546,11 @@ export default function readyPromiseAssertions(fetchMock, assert) { 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.'), 'No warning logged'); - // eslint-disable-next-line @typescript-eslint/no-unused-vars 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.'), 'Warning logged'); - client.destroy().then(() => { + Promise.all([sharedClientWithoutCb.destroy(), client.destroy()]).then(() => { client.ready() .then(() => { t.pass('### SDK IS READY - the promise remains resolved after client destruction.'); diff --git a/src/__tests__/browserSuites/shared-instantiation.spec.js b/src/__tests__/browserSuites/shared-instantiation.spec.js index 4208932..20e0b9c 100644 --- a/src/__tests__/browserSuites/shared-instantiation.spec.js +++ b/src/__tests__/browserSuites/shared-instantiation.spec.js @@ -13,7 +13,7 @@ const settings = settingsValidator({ * @param {boolean} startWithTT whether the SDK settings includes a `core.trafficType` config param or not * @param {boolean} sdkIgnoredTT whether the SDK ignores TT (i.e, clients without bound TT) or not (client with optional bound TT) */ -export default function (startWithTT, sdkIgnoresTT, fetchMock, assert) { +export default function sharedInstantiationSuite(startWithTT, sdkIgnoresTT, fetchMock, assert) { // mocking mySegments endpoints with delays for new clients fetchMock.get(url(settings, '/mySegments/emiliano%2Fsplit.io'), { status: 200, body: { mySegments: [] } }, { delay: 100 }); fetchMock.get(url(settings, '/mySegments/matias%25split.io'), { status: 200, body: { mySegments: [] } }, { delay: 200 }); @@ -42,10 +42,10 @@ export default function (startWithTT, sdkIgnoresTT, fetchMock, assert) { assert.throws(factory.client.bind(factory, null), 'Calling factory.client() with a key parameter that is not a valid key should throw.'); assert.throws(factory.client.bind(factory, {}), 'Calling factory.client() with a key parameter that is not a valid key should throw.'); - if (sdkIgnoresTT) { // Browser JS SDK + if (sdkIgnoresTT) { // JS Browser SDK assert.doesNotThrow(factory.client.bind(factory, 'facundo@split.io', null), 'Calling factory.client() with a traffic type parameter that is not valid shouldn\'t throw because it is ignored.'); assert.doesNotThrow(factory.client.bind(factory, 'facundo@split.io', []), 'Calling factory.client() with a traffic type parameter that is not valid shouldn\'t throw because it is ignored.'); - } else { // Isomorphic JS SDK + } else { // JS SDK (Isomorphic) assert.throws(factory.client.bind(factory, 'facundo@split.io', null), 'Calling factory.client() with a traffic type parameter that is not a valid should throw.'); assert.throws(factory.client.bind(factory, 'facundo@split.io', []), 'Calling factory.client() with a traffic type parameter that is not a valid should throw.'); } @@ -143,9 +143,6 @@ export default function (startWithTT, sdkIgnoresTT, fetchMock, assert) { /* Assert client.track(), no need to wait for ready. */ trackAssertions(); - emmanuelClient.setAttribute('attr', 10); - nicolasClient.setAttributes({ attr: 9 }); - /* Assert getTreatment/s */ const expectControls = ['control', 'control', 'control', 'control']; // If main is not ready and returning controls, they all return controls. @@ -155,6 +152,9 @@ export default function (startWithTT, sdkIgnoresTT, fetchMock, assert) { getTreatmentsAssertions(emilianoClient, expectControls); getTreatmentsAssertions(emmanuelClient, expectControls); + emmanuelClient.setAttribute('attr', 10); + nicolasClient.setAttributes({ attr: 9 }); + // Each client is ready when splits and its segments are fetched mainClient.ready().then(() => { assert.comment('Main instance - facundo@split.io'); diff --git a/src/__tests__/browserSuites/single-sync.spec.js b/src/__tests__/browserSuites/single-sync.spec.js new file mode 100644 index 0000000..4929fc1 --- /dev/null +++ b/src/__tests__/browserSuites/single-sync.spec.js @@ -0,0 +1,65 @@ +import { SplitFactory } from '../../index'; +import { settingsValidator } from '../../settings'; +import { url } from '../testUtils'; + +import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; +import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json'; +import mySegmentsNicolasMock2 from '../mocks/mysegments.nicolas@split.io.json'; + +const baseUrls = { + sdk: 'https://sdk.single-sync/api', + events: 'https://events.single-sync/api', +}; +const userKey = 'nicolas@split.io'; +const config = { + core: { + authorizationKey: '', + key: userKey + }, + scheduler: { + featuresRefreshRate: 0.2, + segmentsRefreshRate: 0.2, + impressionsRefreshRate: 3000, + pushRetryBackoffBase: 0.1 + }, + urls: baseUrls, + userConsent: 'UNKNOWN', + startup: { + eventsFirstPushWindow: 3000 + }, + sync: { + enabled: false + }, + streamingEnabled: true, +}; +const settings = settingsValidator(config); + +export default function singleSync(fetchMock, assert) { + + fetchMock.getOnce(url(settings, '/splitChanges?since=-1'), function () { + assert.pass('first splitChanges fetch'); + return { status: 200, body: splitChangesMock1 }; + }); + fetchMock.getOnce('begin:'+url(settings, '/splitChanges?'), function () { + assert.fail('splitChanges should not be called again'); + return { status: 200, body: splitChangesMock2 }; + }); + + fetchMock.getOnce(url(settings, '/mySegments/nicolas%40split.io'), function () { + assert.pass('first mySegments fetch'); + return { status: 200, body: mySegmentsNicolasMock2 }; + }); + fetchMock.getOnce(url(settings, '/mySegments/nicolas%40split.io'), function () { + assert.fail('mySegments should not be called again'); + return { status: 200, body: mySegmentsNicolasMock2 }; + }); + + let splitio, client = false; + + splitio = SplitFactory(config); + client = splitio.client(); + client.on(client.Event.SDK_READY, () => { + setTimeout(() => client.destroy().then(() => assert.end()), 1000); + }); + +} diff --git a/src/__tests__/browserSuites/use-beacon-api.debug.spec.js b/src/__tests__/browserSuites/use-beacon-api.debug.spec.js index 2b11880..3644b2b 100644 --- a/src/__tests__/browserSuites/use-beacon-api.debug.spec.js +++ b/src/__tests__/browserSuites/use-beacon-api.debug.spec.js @@ -4,7 +4,8 @@ import { settingsValidator } from '../../settings'; import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import mySegmentsFacundo from '../mocks/mysegments.facundo@split.io.json'; import { DEBUG } from '@splitsoftware/splitio-commons/src/utils/constants'; -import { url, triggerPagehideEvent, triggerVisibilitychange } from '../testUtils'; +import { url } from '../testUtils'; +import { triggerPagehideEvent, triggerVisibilitychange } from '../testUtils/browser'; const config = { core: { diff --git a/src/__tests__/browserSuites/use-beacon-api.spec.js b/src/__tests__/browserSuites/use-beacon-api.spec.js index d09102c..cf7e7aa 100644 --- a/src/__tests__/browserSuites/use-beacon-api.spec.js +++ b/src/__tests__/browserSuites/use-beacon-api.spec.js @@ -3,8 +3,9 @@ import { SplitFactory } from '../../index'; import { settingsValidator } from '../../settings'; import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import mySegmentsFacundo from '../mocks/mysegments.facundo@split.io.json'; -import { url, triggerPagehideEvent, triggerVisibilitychange } from '../testUtils'; import { OPTIMIZED } from '@splitsoftware/splitio-commons/src/utils/constants'; +import { url } from '../testUtils'; +import { triggerPagehideEvent, triggerVisibilitychange } from '../testUtils/browser'; const config = { core: { diff --git a/src/__tests__/browserSuites/user-consent.spec.js b/src/__tests__/browserSuites/user-consent.spec.js index ef4fbd7..f7de43c 100644 --- a/src/__tests__/browserSuites/user-consent.spec.js +++ b/src/__tests__/browserSuites/user-consent.spec.js @@ -1,6 +1,7 @@ import sinon from 'sinon'; import { SplitFactory } from '../../index'; -import { nearlyEqual, url, triggerPagehideEvent } from '../testUtils'; +import { nearlyEqual, url } from '../testUtils'; +import { triggerPagehideEvent } from '../testUtils/browser'; const trackedImpressions = []; diff --git a/src/__tests__/consumerMode/browser_consumer.spec.js b/src/__tests__/consumer/browser_consumer.spec.js similarity index 100% rename from src/__tests__/consumerMode/browser_consumer.spec.js rename to src/__tests__/consumer/browser_consumer.spec.js diff --git a/src/__tests__/consumerMode/browser_consumer_partial.spec.js b/src/__tests__/consumer/browser_consumer_partial.spec.js similarity index 100% rename from src/__tests__/consumerMode/browser_consumer_partial.spec.js rename to src/__tests__/consumer/browser_consumer_partial.spec.js diff --git a/src/__tests__/consumerMode/wrapper-commands.js b/src/__tests__/consumer/wrapper-commands.js similarity index 100% rename from src/__tests__/consumerMode/wrapper-commands.js rename to src/__tests__/consumer/wrapper-commands.js diff --git a/src/__tests__/gaIntegration/both-integrations.spec.js b/src/__tests__/gaIntegration/both-integrations.spec.js index 0ba6dc2..7f3086c 100644 --- a/src/__tests__/gaIntegration/both-integrations.spec.js +++ b/src/__tests__/gaIntegration/both-integrations.spec.js @@ -13,7 +13,7 @@ function countImpressions(parsedImpressionsBulkPayload) { const config = { core: { key: 'facundo@split.io', - trafficType: 'user', // ignored for default client, but used as default identity in GaToSplit integration + trafficType: 'user', // Traffic type is not bound to default client in JS Browser SDK, but it is used as identity in GaToSplit integration }, integrations: [GoogleAnalyticsToSplit(), SplitToGoogleAnalytics()], streamingEnabled: false, diff --git a/src/__tests__/gaIntegration/ga-to-split.spec.js b/src/__tests__/gaIntegration/ga-to-split.spec.js index 815f4b1..edcd91b 100644 --- a/src/__tests__/gaIntegration/ga-to-split.spec.js +++ b/src/__tests__/gaIntegration/ga-to-split.spec.js @@ -7,7 +7,7 @@ import { url } from '../testUtils'; const config = { core: { key: 'facundo@split.io', - trafficType: 'user', // ignored for default client, but used as default identity in GaToSplit integration + trafficType: 'user', // Traffic type is not bound to default client in JS Browser SDK, but it is used as identity in GaToSplit integration }, integrations: [GoogleAnalyticsToSplit()], startup: { diff --git a/src/__tests__/mocks/message.STREAMING_RESET.json b/src/__tests__/mocks/message.STREAMING_RESET.json index ee1c13e..791d9de 100644 --- a/src/__tests__/mocks/message.STREAMING_RESET.json +++ b/src/__tests__/mocks/message.STREAMING_RESET.json @@ -1,4 +1,4 @@ { "type": "message", - "data": "{\"timestamp\":1457552660000,\"data\":\"{\\\"type\\\":\\\"STREAMING_RESET\\\"}\"}" + "data": "{\"timestamp\":1457552660000,\"data\":\"{\\\"type\\\":\\\"CONTROL\\\",\\\"controlType\\\":\\\"STREAMING_RESET\\\"}\"}" } \ No newline at end of file diff --git a/src/__tests__/offline/browser.spec.js b/src/__tests__/offline/browser.spec.js index 05dabd6..582be44 100644 --- a/src/__tests__/offline/browser.spec.js +++ b/src/__tests__/offline/browser.spec.js @@ -3,7 +3,7 @@ import sinon from 'sinon'; import fetchMock from '../testUtils/fetchMock'; import { url } from '../testUtils'; import { SplitFactory, InLocalStorage } from '../../full'; -import { SplitFactory as SplitFactorySlim, LocalhostFromObject } from '../../'; +import { SplitFactory as SplitFactorySlim, LocalhostFromObject } from '../../index'; import { settingsValidator } from '../../settings'; const settings = settingsValidator({ core: { key: 'facundo@split.io' } }); diff --git a/src/__tests__/online/browser.spec.js b/src/__tests__/online/browser.spec.js index 8d2afd6..e6a64b2 100644 --- a/src/__tests__/online/browser.spec.js +++ b/src/__tests__/online/browser.spec.js @@ -17,6 +17,7 @@ import useBeaconDebugApiSuite from '../browserSuites/use-beacon-api.debug.spec'; import readyPromiseSuite from '../browserSuites/ready-promise.spec'; import fetchSpecificSplits from '../browserSuites/fetch-specific-splits.spec'; import userConsent from '../browserSuites/user-consent.spec'; +import singleSync from '../browserSuites/single-sync.spec'; import { settingsValidator } from '../../settings'; import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; @@ -129,6 +130,8 @@ tape('## E2E CI Tests ##', function (assert) { assert.test('E2E / Ready promise', readyPromiseSuite.bind(null, fetchMock)); /* Validate fetching specific splits */ assert.test('E2E / Fetch specific splits', fetchSpecificSplits.bind(null, fetchMock)); + /* Validate single sync */ + assert.test('E2E / Single sync', singleSync.bind(null, fetchMock)); //If we change the mocks, we need to clear localstorage. Cleaning up after testing ensures "fresh data". localStorage.clear(); diff --git a/src/__tests__/testUtils/browser.js b/src/__tests__/testUtils/browser.js new file mode 100644 index 0000000..6028492 --- /dev/null +++ b/src/__tests__/testUtils/browser.js @@ -0,0 +1,19 @@ +function triggerEvent(eventName) { + const event = document.createEvent('HTMLEvents'); + event.initEvent(eventName, true, true); + event.eventName = eventName; + window.dispatchEvent(event); +} + +export function triggerUnloadEvent() { + triggerEvent('unload'); +} + +export function triggerPagehideEvent() { + triggerEvent('pagehide'); +} + +export function triggerVisibilitychange(state = 'hidden' /* 'hidden' | 'visible' */) { + Object.defineProperty(document, 'visibilityState', { value: state, writable: true }); + document.dispatchEvent(new Event('visibilitychange')); +} diff --git a/src/__tests__/testUtils/index.js b/src/__tests__/testUtils/index.js index a140557..302e944 100644 --- a/src/__tests__/testUtils/index.js +++ b/src/__tests__/testUtils/index.js @@ -71,23 +71,3 @@ export function url(settings, target) { } return `${settings.urls.sdk}${target}`; } - -function triggerEvent(eventName) { - const event = document.createEvent('HTMLEvents'); - event.initEvent(eventName, true, true); - event.eventName = eventName; - window.dispatchEvent(event); -} - -export function triggerUnloadEvent() { - triggerEvent('unload'); -} - -export function triggerPagehideEvent() { - triggerEvent('pagehide'); -} - -export function triggerVisibilitychange(state = 'hidden' /* 'hidden' | 'visible' */) { - Object.defineProperty(document, 'visibilityState', { value: state, writable: true }); - document.dispatchEvent(new Event('visibilitychange')); -} From 630d9690d984212f2eca666eda5d7aec56581a00 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 29 Jul 2022 15:01:17 -0300 Subject: [PATCH 03/23] rename settingsValidator to settingsFactory --- src/__tests__/browserSuites/evaluations.spec.js | 2 +- src/__tests__/browserSuites/events.spec.js | 6 +++--- .../browserSuites/fetch-specific-splits.spec.js | 2 +- .../ignore-ip-addresses-setting.spec.js | 6 +++--- .../browserSuites/impressions-listener.spec.js | 6 +++--- .../browserSuites/impressions.debug.spec.js | 6 +++--- src/__tests__/browserSuites/impressions.spec.js | 6 +++--- src/__tests__/browserSuites/manager.spec.js | 2 +- .../browserSuites/push-corner-cases.spec.js | 6 +++--- .../browserSuites/push-fallbacking.spec.js | 6 +++--- .../push-initialization-nopush.spec.js | 6 +++--- .../push-initialization-retries.spec.js | 6 +++--- .../browserSuites/push-refresh-token.spec.js | 6 +++--- .../push-synchronization-retries.spec.js | 6 +++--- .../browserSuites/push-synchronization.spec.js | 6 +++--- src/__tests__/browserSuites/readiness.spec.js | 2 +- .../browserSuites/ready-from-cache.spec.js | 2 +- src/__tests__/browserSuites/ready-promise.spec.js | 2 +- .../browserSuites/shared-instantiation.spec.js | 6 +++--- src/__tests__/browserSuites/single-sync.spec.js | 6 +++--- .../browserSuites/use-beacon-api.debug.spec.js | 6 +++--- src/__tests__/browserSuites/use-beacon-api.spec.js | 6 +++--- src/__tests__/browserSuites/user-consent.spec.js | 2 +- src/__tests__/consumer/browser_consumer.spec.js | 2 +- .../consumer/browser_consumer_partial.spec.js | 2 +- src/__tests__/destroy/browser.spec.js | 6 +++--- src/__tests__/errorCatching/browser.spec.js | 6 +++--- .../gaIntegration/both-integrations.spec.js | 6 +++--- src/__tests__/gaIntegration/browser.spec.js | 4 ++-- src/__tests__/gaIntegration/ga-to-split.spec.js | 6 +++--- src/__tests__/gaIntegration/split-to-ga.spec.js | 6 +++--- src/__tests__/logger/browser.spec.js | 2 +- src/__tests__/offline/browser.spec.js | 6 +++--- src/__tests__/online/browser.spec.js | 4 ++-- src/full/splitFactory.ts | 7 ++++--- src/settings/__tests__/index.spec.ts | 14 +++++++------- src/settings/full.ts | 2 +- src/settings/index.ts | 2 +- src/splitFactory.ts | 7 ++++--- types/splitio.d.ts | 6 +++--- 40 files changed, 100 insertions(+), 98 deletions(-) diff --git a/src/__tests__/browserSuites/evaluations.spec.js b/src/__tests__/browserSuites/evaluations.spec.js index fe182f2..cc8bee2 100644 --- a/src/__tests__/browserSuites/evaluations.spec.js +++ b/src/__tests__/browserSuites/evaluations.spec.js @@ -1,4 +1,4 @@ -import { SplitFactory } from '../../index'; +import { SplitFactory } from '../../'; const SDK_INSTANCES_TO_TEST = 4; diff --git a/src/__tests__/browserSuites/events.spec.js b/src/__tests__/browserSuites/events.spec.js index 9e08f4d..a33dd79 100644 --- a/src/__tests__/browserSuites/events.spec.js +++ b/src/__tests__/browserSuites/events.spec.js @@ -1,8 +1,8 @@ -import { SplitFactory } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory } from '../../'; +import { settingsFactory } from '../../settings'; import { url } from '../testUtils'; -const settings = settingsValidator({ +const settings = settingsFactory({ core: { key: 'asd' }, diff --git a/src/__tests__/browserSuites/fetch-specific-splits.spec.js b/src/__tests__/browserSuites/fetch-specific-splits.spec.js index ffed3cc..14dc031 100644 --- a/src/__tests__/browserSuites/fetch-specific-splits.spec.js +++ b/src/__tests__/browserSuites/fetch-specific-splits.spec.js @@ -1,4 +1,4 @@ -import { SplitFactory } from '../../index'; +import { SplitFactory } from '../../'; import { splitFilters, queryStrings, groupedFilters } from '../mocks/fetchSpecificSplits'; const baseConfig = { diff --git a/src/__tests__/browserSuites/ignore-ip-addresses-setting.spec.js b/src/__tests__/browserSuites/ignore-ip-addresses-setting.spec.js index 4503d82..6266976 100644 --- a/src/__tests__/browserSuites/ignore-ip-addresses-setting.spec.js +++ b/src/__tests__/browserSuites/ignore-ip-addresses-setting.spec.js @@ -1,5 +1,5 @@ -import { SplitFactory } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory } from '../../'; +import { settingsFactory } from '../../settings'; import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import { DEBUG } from '@splitsoftware/splitio-commons/src/utils/constants'; import { url } from '../testUtils'; @@ -100,7 +100,7 @@ export default function (fetchMock, assert) { }; // Mock GET endpoints before creating the client - const settings = settingsValidator(config); + const settings = settingsFactory(config); fetchMock.getOnce(url(settings, '/splitChanges?since=-1'), { status: 200, body: splitChangesMock1 }); fetchMock.getOnce(url(settings, '/splitChanges?since=1457552620999'), { status: 200, body: { splits: [], since: 1457552620999, till: 1457552620999 } }); fetchMock.getOnce(url(settings, `/mySegments/${encodeURIComponent(config.core.key)}`), { status: 200, body: { mySegments: [] } }); diff --git a/src/__tests__/browserSuites/impressions-listener.spec.js b/src/__tests__/browserSuites/impressions-listener.spec.js index a48b75b..644d3d6 100644 --- a/src/__tests__/browserSuites/impressions-listener.spec.js +++ b/src/__tests__/browserSuites/impressions-listener.spec.js @@ -1,8 +1,8 @@ import sinon from 'sinon'; -import { SplitFactory } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory } from '../../'; +import { settingsFactory } from '../../settings'; -const settings = settingsValidator({ +const settings = settingsFactory({ core: { key: '' }, diff --git a/src/__tests__/browserSuites/impressions.debug.spec.js b/src/__tests__/browserSuites/impressions.debug.spec.js index ba8fa8a..bbccfc9 100644 --- a/src/__tests__/browserSuites/impressions.debug.spec.js +++ b/src/__tests__/browserSuites/impressions.debug.spec.js @@ -1,5 +1,5 @@ -import { SplitFactory } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory } from '../../'; +import { settingsFactory } from '../../settings'; import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json'; import mySegmentsFacundo from '../mocks/mysegments.facundo@split.io.json'; @@ -11,7 +11,7 @@ const baseUrls = { events: 'https://events.baseurl/impressionsDebugSuite' }; -const settings = settingsValidator({ +const settings = settingsFactory({ core: { key: 'asd' }, diff --git a/src/__tests__/browserSuites/impressions.spec.js b/src/__tests__/browserSuites/impressions.spec.js index 1f2f71d..8e73c5d 100644 --- a/src/__tests__/browserSuites/impressions.spec.js +++ b/src/__tests__/browserSuites/impressions.spec.js @@ -1,5 +1,5 @@ -import { SplitFactory } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory } from '../../'; +import { settingsFactory } from '../../settings'; import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json'; import mySegmentsFacundo from '../mocks/mysegments.facundo@split.io.json'; @@ -12,7 +12,7 @@ const baseUrls = { events: 'https://events.baseurl/impressionsSuite' }; -const settings = settingsValidator({ +const settings = settingsFactory({ core: { key: 'asd' }, diff --git a/src/__tests__/browserSuites/manager.spec.js b/src/__tests__/browserSuites/manager.spec.js index a530dd8..ce13cd3 100644 --- a/src/__tests__/browserSuites/manager.spec.js +++ b/src/__tests__/browserSuites/manager.spec.js @@ -1,4 +1,4 @@ -import { SplitFactory } from '../../index'; +import { SplitFactory } from '../../'; import splitChangesMockReal from '../mocks/splitchanges.real.json'; import map from 'lodash/map'; import { url } from '../testUtils'; diff --git a/src/__tests__/browserSuites/push-corner-cases.spec.js b/src/__tests__/browserSuites/push-corner-cases.spec.js index 0fc203d..0b659c6 100644 --- a/src/__tests__/browserSuites/push-corner-cases.spec.js +++ b/src/__tests__/browserSuites/push-corner-cases.spec.js @@ -7,8 +7,8 @@ import { nearlyEqual, url } from '../testUtils'; import EventSourceMock, { setMockListener } from '../testUtils/eventSourceMock'; window.EventSource = EventSourceMock; -import { SplitFactory, InLocalStorage } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory, InLocalStorage } from '../../'; +import { settingsFactory } from '../../settings'; const userKey = 'nicolas@split.io'; @@ -27,7 +27,7 @@ const config = { prefix: 'pushCornerCase' }), }; -const settings = settingsValidator(config); +const settings = settingsFactory(config); const MILLIS_SSE_OPEN = 100; const MILLIS_SPLIT_KILL_EVENT = 200; diff --git a/src/__tests__/browserSuites/push-fallbacking.spec.js b/src/__tests__/browserSuites/push-fallbacking.spec.js index 5549eab..fe12676 100644 --- a/src/__tests__/browserSuites/push-fallbacking.spec.js +++ b/src/__tests__/browserSuites/push-fallbacking.spec.js @@ -32,8 +32,8 @@ import { nearlyEqual, url } from '../testUtils'; import EventSourceMock, { setMockListener } from '../testUtils/eventSourceMock'; window.EventSource = EventSourceMock; -import { SplitFactory } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory } from '../../'; +import { settingsFactory } from '../../settings'; const userKey = 'nicolas@split.io'; const secondUserKey = 'marcio@split.io'; @@ -57,7 +57,7 @@ const config = { streamingEnabled: true, // debug: true, }; -const settings = settingsValidator(config); +const settings = settingsFactory(config); const MILLIS_SSE_OPEN = 100; const MILLIS_STREAMING_DOWN_OCCUPANCY = MILLIS_SSE_OPEN + 100; diff --git a/src/__tests__/browserSuites/push-initialization-nopush.spec.js b/src/__tests__/browserSuites/push-initialization-nopush.spec.js index b8e7bc4..0126293 100644 --- a/src/__tests__/browserSuites/push-initialization-nopush.spec.js +++ b/src/__tests__/browserSuites/push-initialization-nopush.spec.js @@ -1,5 +1,5 @@ -import { SplitFactory } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory } from '../../'; +import { settingsFactory } from '../../settings'; import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json'; import mySegmentsNicolas from '../mocks/mysegments.nicolas@split.io.json'; @@ -33,7 +33,7 @@ const config = { streamingEnabled: true, debug: true, }; -const settings = settingsValidator(config); +const settings = settingsFactory(config); /** * Sequence of calls: diff --git a/src/__tests__/browserSuites/push-initialization-retries.spec.js b/src/__tests__/browserSuites/push-initialization-retries.spec.js index 0879954..87d96d7 100644 --- a/src/__tests__/browserSuites/push-initialization-retries.spec.js +++ b/src/__tests__/browserSuites/push-initialization-retries.spec.js @@ -7,8 +7,8 @@ import mySegmentsNicolasMock from '../mocks/mysegments.nicolas@split.io.json'; import { nearlyEqual, url } from '../testUtils'; import EventSourceMock, { setMockListener } from '../testUtils/eventSourceMock'; -import { SplitFactory } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory } from '../../'; +import { settingsFactory } from '../../settings'; const baseUrls = { sdk: 'https://sdk.push-initialization-retries/api', @@ -34,7 +34,7 @@ const config = { streamingEnabled: true, // debug: true, }; -const settings = settingsValidator(config); +const settings = settingsFactory(config); /** * Sequence of calls: diff --git a/src/__tests__/browserSuites/push-refresh-token.spec.js b/src/__tests__/browserSuites/push-refresh-token.spec.js index b4ebf8e..0ff61a2 100644 --- a/src/__tests__/browserSuites/push-refresh-token.spec.js +++ b/src/__tests__/browserSuites/push-refresh-token.spec.js @@ -10,8 +10,8 @@ import { nearlyEqual, url } from '../testUtils'; import EventSourceMock, { setMockListener } from '../testUtils/eventSourceMock'; window.EventSource = EventSourceMock; -import { SplitFactory } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory } from '../../'; +import { settingsFactory } from '../../settings'; const userKey = 'nicolas@split.io'; @@ -32,7 +32,7 @@ const config = { }, // debug: true, }; -const settings = settingsValidator(config); +const settings = settingsFactory(config); const MILLIS_CONNDELAY = 500; const MILLIS_REFRESH_TOKEN = 1000; diff --git a/src/__tests__/browserSuites/push-synchronization-retries.spec.js b/src/__tests__/browserSuites/push-synchronization-retries.spec.js index c106710..855a349 100644 --- a/src/__tests__/browserSuites/push-synchronization-retries.spec.js +++ b/src/__tests__/browserSuites/push-synchronization-retries.spec.js @@ -17,8 +17,8 @@ import { Backoff } from '@splitsoftware/splitio-commons/src/utils/Backoff'; import EventSourceMock, { setMockListener } from '../testUtils/eventSourceMock'; window.EventSource = EventSourceMock; -import { SplitFactory } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory } from '../../'; +import { settingsFactory } from '../../settings'; const userKey = 'nicolas@split.io'; const otherUserKeySync = 'marcio@split.io'; @@ -37,7 +37,7 @@ const config = { streamingEnabled: true, // debug: true, }; -const settings = settingsValidator(config); +const settings = settingsFactory(config); const MILLIS_SSE_OPEN = 100; diff --git a/src/__tests__/browserSuites/push-synchronization.spec.js b/src/__tests__/browserSuites/push-synchronization.spec.js index e0edb94..f6ffa61 100644 --- a/src/__tests__/browserSuites/push-synchronization.spec.js +++ b/src/__tests__/browserSuites/push-synchronization.spec.js @@ -29,8 +29,8 @@ import includes from 'lodash/includes'; import EventSourceMock, { setMockListener } from '../testUtils/eventSourceMock'; window.EventSource = EventSourceMock; -import { SplitFactory } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory } from '../../'; +import { settingsFactory } from '../../settings'; const userKey = 'nicolas@split.io'; const otherUserKey = 'marcio@split.io'; @@ -51,7 +51,7 @@ const config = { urls: baseUrls, streamingEnabled: true, }; -const settings = settingsValidator(config); +const settings = settingsFactory(config); const MILLIS_SSE_OPEN = 100; const MILLIS_FIRST_SPLIT_UPDATE_EVENT = 200; diff --git a/src/__tests__/browserSuites/readiness.spec.js b/src/__tests__/browserSuites/readiness.spec.js index 8d50634..ee92746 100644 --- a/src/__tests__/browserSuites/readiness.spec.js +++ b/src/__tests__/browserSuites/readiness.spec.js @@ -1,4 +1,4 @@ -import { SplitFactory, InLocalStorage } from '../../index'; +import { SplitFactory, InLocalStorage } from '../../'; import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json'; diff --git a/src/__tests__/browserSuites/ready-from-cache.spec.js b/src/__tests__/browserSuites/ready-from-cache.spec.js index f037528..7909278 100644 --- a/src/__tests__/browserSuites/ready-from-cache.spec.js +++ b/src/__tests__/browserSuites/ready-from-cache.spec.js @@ -1,4 +1,4 @@ -import { SplitFactory, InLocalStorage } from '../../index'; +import { SplitFactory, InLocalStorage } from '../../'; import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json'; diff --git a/src/__tests__/browserSuites/ready-promise.spec.js b/src/__tests__/browserSuites/ready-promise.spec.js index dde9a21..c127a7c 100644 --- a/src/__tests__/browserSuites/ready-promise.spec.js +++ b/src/__tests__/browserSuites/ready-promise.spec.js @@ -10,7 +10,7 @@ const consoleSpy = { error: sinon.spy(console, 'error'), }; -import { SplitFactory, WarnLogger } from '../../index'; +import { SplitFactory, WarnLogger } from '../../'; import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import mySegmentsFacundo from '../mocks/mysegments.facundo@split.io.json'; diff --git a/src/__tests__/browserSuites/shared-instantiation.spec.js b/src/__tests__/browserSuites/shared-instantiation.spec.js index 20e0b9c..108ad1f 100644 --- a/src/__tests__/browserSuites/shared-instantiation.spec.js +++ b/src/__tests__/browserSuites/shared-instantiation.spec.js @@ -1,8 +1,8 @@ -import { SplitFactory } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory } from '../../'; +import { settingsFactory } from '../../settings'; import { url } from '../testUtils'; -const settings = settingsValidator({ +const settings = settingsFactory({ core: { key: 'asd' }, diff --git a/src/__tests__/browserSuites/single-sync.spec.js b/src/__tests__/browserSuites/single-sync.spec.js index 4929fc1..f87783d 100644 --- a/src/__tests__/browserSuites/single-sync.spec.js +++ b/src/__tests__/browserSuites/single-sync.spec.js @@ -1,5 +1,5 @@ -import { SplitFactory } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory } from '../../'; +import { settingsFactory } from '../../settings'; import { url } from '../testUtils'; import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; @@ -32,7 +32,7 @@ const config = { }, streamingEnabled: true, }; -const settings = settingsValidator(config); +const settings = settingsFactory(config); export default function singleSync(fetchMock, assert) { diff --git a/src/__tests__/browserSuites/use-beacon-api.debug.spec.js b/src/__tests__/browserSuites/use-beacon-api.debug.spec.js index 3644b2b..96320f2 100644 --- a/src/__tests__/browserSuites/use-beacon-api.debug.spec.js +++ b/src/__tests__/browserSuites/use-beacon-api.debug.spec.js @@ -1,6 +1,6 @@ import sinon from 'sinon'; -import { SplitFactory } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory } from '../../'; +import { settingsFactory } from '../../settings'; import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import mySegmentsFacundo from '../mocks/mysegments.facundo@split.io.json'; import { DEBUG } from '@splitsoftware/splitio-commons/src/utils/constants'; @@ -22,7 +22,7 @@ const config = { } }; -const settings = settingsValidator(config); +const settings = settingsFactory(config); // Spy calls to Beacon API method let sendBeaconSpyDebug; diff --git a/src/__tests__/browserSuites/use-beacon-api.spec.js b/src/__tests__/browserSuites/use-beacon-api.spec.js index cf7e7aa..27bea08 100644 --- a/src/__tests__/browserSuites/use-beacon-api.spec.js +++ b/src/__tests__/browserSuites/use-beacon-api.spec.js @@ -1,6 +1,6 @@ import sinon from 'sinon'; -import { SplitFactory } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory } from '../../'; +import { settingsFactory } from '../../settings'; import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import mySegmentsFacundo from '../mocks/mysegments.facundo@split.io.json'; import { OPTIMIZED } from '@splitsoftware/splitio-commons/src/utils/constants'; @@ -19,7 +19,7 @@ const config = { streamingEnabled: false }; -const settings = settingsValidator(config); +const settings = settingsFactory(config); // Spy calls to Beacon API method let sendBeaconSpy; diff --git a/src/__tests__/browserSuites/user-consent.spec.js b/src/__tests__/browserSuites/user-consent.spec.js index f7de43c..2334916 100644 --- a/src/__tests__/browserSuites/user-consent.spec.js +++ b/src/__tests__/browserSuites/user-consent.spec.js @@ -1,5 +1,5 @@ import sinon from 'sinon'; -import { SplitFactory } from '../../index'; +import { SplitFactory } from '../../'; import { nearlyEqual, url } from '../testUtils'; import { triggerPagehideEvent } from '../testUtils/browser'; diff --git a/src/__tests__/consumer/browser_consumer.spec.js b/src/__tests__/consumer/browser_consumer.spec.js index c8e29a0..f2575b6 100644 --- a/src/__tests__/consumer/browser_consumer.spec.js +++ b/src/__tests__/consumer/browser_consumer.spec.js @@ -5,7 +5,7 @@ import { SDK_NOT_READY, EXCEPTION } from '@splitsoftware/splitio-commons/src/uti import { applyOperations } from './wrapper-commands'; import { nearlyEqual } from '../testUtils'; -import { SplitFactory, PluggableStorage } from '../../index'; +import { SplitFactory, PluggableStorage } from '../../'; const expectedSplitName = 'hierarchical_splits_testing_on'; const expectedSplitView = { name: 'hierarchical_splits_testing_on', trafficType: 'user', killed: false, changeNumber: 1487277320548, treatments: ['on', 'off'], configs: {} }; diff --git a/src/__tests__/consumer/browser_consumer_partial.spec.js b/src/__tests__/consumer/browser_consumer_partial.spec.js index c3fd126..b487880 100644 --- a/src/__tests__/consumer/browser_consumer_partial.spec.js +++ b/src/__tests__/consumer/browser_consumer_partial.spec.js @@ -7,7 +7,7 @@ import { SDK_NOT_READY } from '@splitsoftware/splitio-commons/src/utils/labels'; import { url } from '../testUtils'; import { applyOperations } from './wrapper-commands'; -import { SplitFactory, PluggableStorage } from '../../index'; +import { SplitFactory, PluggableStorage } from '../../'; const expectedSplitName = 'hierarchical_splits_testing_on'; const expectedSplitView = { name: 'hierarchical_splits_testing_on', trafficType: 'user', killed: false, changeNumber: 1487277320548, treatments: ['on', 'off'], configs: {} }; diff --git a/src/__tests__/destroy/browser.spec.js b/src/__tests__/destroy/browser.spec.js index 79be403..7f9ef38 100644 --- a/src/__tests__/destroy/browser.spec.js +++ b/src/__tests__/destroy/browser.spec.js @@ -3,14 +3,14 @@ import fetchMock from '../testUtils/fetchMock'; import { url } from '../testUtils'; import map from 'lodash/map'; import pick from 'lodash/pick'; -import { SplitFactory, DebugLogger } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory, DebugLogger } from '../../'; +import { settingsFactory } from '../../settings'; import splitChangesMock1 from '../mocks/splitChanges.since.-1.till.1500492097547.json'; import splitChangesMock2 from '../mocks/splitChanges.since.1500492097547.json'; import mySegmentsMock from '../mocks/mySegmentsEmpty.json'; import impressionsMock from '../mocks/impressions.json'; -const settings = settingsValidator({ +const settings = settingsFactory({ core: { key: 'facundo@split.io' }, diff --git a/src/__tests__/errorCatching/browser.spec.js b/src/__tests__/errorCatching/browser.spec.js index e21f05d..3853da4 100644 --- a/src/__tests__/errorCatching/browser.spec.js +++ b/src/__tests__/errorCatching/browser.spec.js @@ -7,10 +7,10 @@ import splitChangesMock1 from '../mocks/splitChanges.since.-1.till.1500492097547 import mySegmentsMock from '../mocks/mySegmentsEmpty.json'; import splitChangesMock2 from '../mocks/splitChanges.since.1500492097547.till.1500492297547.json'; import splitChangesMock3 from '../mocks/splitChanges.since.1500492297547.json'; -import { SplitFactory, InLocalStorage } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory, InLocalStorage } from '../../'; +import { settingsFactory } from '../../settings'; -const settings = settingsValidator({ +const settings = settingsFactory({ core: { authorizationKey: '' }, diff --git a/src/__tests__/gaIntegration/both-integrations.spec.js b/src/__tests__/gaIntegration/both-integrations.spec.js index 7f3086c..884a411 100644 --- a/src/__tests__/gaIntegration/both-integrations.spec.js +++ b/src/__tests__/gaIntegration/both-integrations.spec.js @@ -1,5 +1,5 @@ -import { SplitFactory, GoogleAnalyticsToSplit, SplitToGoogleAnalytics } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory, GoogleAnalyticsToSplit, SplitToGoogleAnalytics } from '../../'; +import { settingsFactory } from '../../settings'; import { gaSpy, gaTag } from './gaTestUtils'; import includes from 'lodash/includes'; import { DEBUG } from '@splitsoftware/splitio-commons/src/utils/constants'; @@ -21,7 +21,7 @@ const config = { impressionsMode: DEBUG, } }; -const settings = settingsValidator(config); +const settings = settingsFactory(config); export default function (fetchMock, assert) { diff --git a/src/__tests__/gaIntegration/browser.spec.js b/src/__tests__/gaIntegration/browser.spec.js index c1fbe67..2248fb5 100644 --- a/src/__tests__/gaIntegration/browser.spec.js +++ b/src/__tests__/gaIntegration/browser.spec.js @@ -4,11 +4,11 @@ import { url } from '../testUtils'; import gaToSplitSuite from './ga-to-split.spec'; import splitToGaSuite from './split-to-ga.spec'; import bothIntegrationsSuite from './both-integrations.spec'; -import { settingsValidator } from '../../settings'; +import { settingsFactory } from '../../settings'; import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import mySegmentsFacundo from '../mocks/mysegments.facundo@split.io.json'; -const settings = settingsValidator({ +const settings = settingsFactory({ core: { key: 'facundo@split.io' } diff --git a/src/__tests__/gaIntegration/ga-to-split.spec.js b/src/__tests__/gaIntegration/ga-to-split.spec.js index edcd91b..e26c441 100644 --- a/src/__tests__/gaIntegration/ga-to-split.spec.js +++ b/src/__tests__/gaIntegration/ga-to-split.spec.js @@ -1,6 +1,6 @@ import sinon from 'sinon'; -import { SplitFactory, GoogleAnalyticsToSplit, DebugLogger } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory, GoogleAnalyticsToSplit, DebugLogger } from '../../'; +import { settingsFactory } from '../../settings'; import { gaSpy, gaTag, addGaTag, removeGaTag } from './gaTestUtils'; import { url } from '../testUtils'; @@ -17,7 +17,7 @@ const config = { debug: DebugLogger() }; -const settings = settingsValidator(config); +const settings = settingsFactory(config); export default function (fetchMock, assert) { diff --git a/src/__tests__/gaIntegration/split-to-ga.spec.js b/src/__tests__/gaIntegration/split-to-ga.spec.js index dd36617..e6b43d5 100644 --- a/src/__tests__/gaIntegration/split-to-ga.spec.js +++ b/src/__tests__/gaIntegration/split-to-ga.spec.js @@ -1,6 +1,6 @@ import sinon from 'sinon'; -import { SplitFactory, SplitToGoogleAnalytics, DebugLogger } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory, SplitToGoogleAnalytics, DebugLogger } from '../../'; +import { settingsFactory } from '../../settings'; import { gaSpy, gaTag, removeGaTag, addGaTag } from './gaTestUtils'; import { SPLIT_IMPRESSION, SPLIT_EVENT, DEBUG } from '@splitsoftware/splitio-commons/src/utils/constants'; import { url } from '../testUtils'; @@ -26,7 +26,7 @@ const config = { } }; -const settings = settingsValidator(config); +const settings = settingsFactory(config); export default function (fetchMock, assert) { diff --git a/src/__tests__/logger/browser.spec.js b/src/__tests__/logger/browser.spec.js index 6b1a652..14549a8 100644 --- a/src/__tests__/logger/browser.spec.js +++ b/src/__tests__/logger/browser.spec.js @@ -3,7 +3,7 @@ import { initialLogLevel } from './setLocalStorage'; import tape from 'tape'; import sinon from 'sinon'; import fetchMock from '../testUtils/fetchMock'; -import { SplitFactory, ErrorLogger, DebugLogger } from '../../index'; +import { SplitFactory, ErrorLogger, DebugLogger } from '../../'; // Don't care about SDK readiness fetchMock.get('*', { throws: new TypeError('Network error') }); diff --git a/src/__tests__/offline/browser.spec.js b/src/__tests__/offline/browser.spec.js index 582be44..0b2be89 100644 --- a/src/__tests__/offline/browser.spec.js +++ b/src/__tests__/offline/browser.spec.js @@ -3,10 +3,10 @@ import sinon from 'sinon'; import fetchMock from '../testUtils/fetchMock'; import { url } from '../testUtils'; import { SplitFactory, InLocalStorage } from '../../full'; -import { SplitFactory as SplitFactorySlim, LocalhostFromObject } from '../../index'; -import { settingsValidator } from '../../settings'; +import { SplitFactory as SplitFactorySlim, LocalhostFromObject } from '../../'; +import { settingsFactory } from '../../settings'; -const settings = settingsValidator({ core: { key: 'facundo@split.io' } }); +const settings = settingsFactory({ core: { key: 'facundo@split.io' } }); const spySplitChanges = sinon.spy(); const spySegmentChanges = sinon.spy(); diff --git a/src/__tests__/online/browser.spec.js b/src/__tests__/online/browser.spec.js index e6a64b2..cf75666 100644 --- a/src/__tests__/online/browser.spec.js +++ b/src/__tests__/online/browser.spec.js @@ -19,7 +19,7 @@ import fetchSpecificSplits from '../browserSuites/fetch-specific-splits.spec'; import userConsent from '../browserSuites/user-consent.spec'; import singleSync from '../browserSuites/single-sync.spec'; -import { settingsValidator } from '../../settings'; +import { settingsFactory } from '../../settings'; import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json'; import mySegmentsFacundo from '../mocks/mysegments.facundo@split.io.json'; @@ -28,7 +28,7 @@ import mySegmentsMarcio from '../mocks/mysegments.marcio@split.io.json'; import mySegmentsEmmanuel from '../mocks/mysegments.emmanuel@split.io.json'; import { InLocalStorage } from '../../index'; -const settings = settingsValidator({ +const settings = settingsFactory({ core: { key: 'facundo@split.io' }, diff --git a/src/full/splitFactory.ts b/src/full/splitFactory.ts index 9c2864b..83ba000 100644 --- a/src/full/splitFactory.ts +++ b/src/full/splitFactory.ts @@ -1,4 +1,4 @@ -import { settingsValidator } from '../settings/full'; +import { settingsFactory } from '../settings/full'; import { getModules } from '../platform/getModules'; import { sdkFactory } from '@splitsoftware/splitio-commons/src/sdkFactory/index'; import { ISdkFactoryParams } from '@splitsoftware/splitio-commons/src/sdkFactory/types'; @@ -6,6 +6,7 @@ import { getFetch } from '../platform/getFetchFull'; import { getEventSource } from '../platform/getEventSource'; import { EventEmitter } from '@splitsoftware/splitio-commons/src/utils/MinEvents'; import { now } from '@splitsoftware/splitio-commons/src/utils/timeTracker/now/browser'; +import { IBrowserSettings } from '../../types/splitio'; const platform = { getFetch, getEventSource, EventEmitter, now }; @@ -18,8 +19,8 @@ const platform = { getFetch, getEventSource, EventEmitter, now }; * caution since, unlike `config`, this param is not validated neither considered part of the public API. * @throws Will throw an error if the provided config is invalid. */ -export function SplitFactory(config: any, __updateModules?: (modules: ISdkFactoryParams) => void) { - const settings = settingsValidator(config); +export function SplitFactory(config: IBrowserSettings, __updateModules?: (modules: ISdkFactoryParams) => void) { + const settings = settingsFactory(config); const modules = getModules(settings, platform); if (__updateModules) __updateModules(modules); return sdkFactory(modules); diff --git a/src/settings/__tests__/index.spec.ts b/src/settings/__tests__/index.spec.ts index a9fc014..4b1ad49 100644 --- a/src/settings/__tests__/index.spec.ts +++ b/src/settings/__tests__/index.spec.ts @@ -1,18 +1,18 @@ -import { settingsValidator as slimSettingsValidator } from '../index'; -import { settingsValidator as fullSettingsValidator } from '../index'; +import { settingsFactory as slimSettingsFactory } from '../index'; +import { settingsFactory as fullSettingsFactory } from '../full'; test('SETTINGS / Consent is overwritable and "GRANTED" by default', () => { - [slimSettingsValidator, fullSettingsValidator].forEach((settingsValidator) => { - let settings = settingsValidator({}); + [slimSettingsFactory, fullSettingsFactory].forEach((settingsFactory) => { + let settings = settingsFactory({}); expect(settings.userConsent).toEqual('GRANTED'); // userConsent defaults to granted if not provided - settings = settingsValidator({ userConsent: 'INVALID-VALUE' }); + settings = settingsFactory({ userConsent: 'INVALID-VALUE' }); expect(settings.userConsent).toEqual('GRANTED'); // userConsent defaults to granted if a wrong value is provided - settings = settingsValidator({ userConsent: 'UNKNOWN' }); + settings = settingsFactory({ userConsent: 'UNKNOWN' }); expect(settings.userConsent).toEqual('UNKNOWN'); // userConsent can be overwritten - settings = settingsValidator({ userConsent: 'declined' }); + settings = settingsFactory({ userConsent: 'declined' }); expect(settings.userConsent).toEqual('DECLINED'); // userConsent can be overwritten }); }); diff --git a/src/settings/full.ts b/src/settings/full.ts index bd39f10..8afa840 100644 --- a/src/settings/full.ts +++ b/src/settings/full.ts @@ -18,6 +18,6 @@ const params = { consent: validateConsent, }; -export function settingsValidator(config: any) { +export function settingsFactory(config: any) { return settingsValidation(config, params); } diff --git a/src/settings/index.ts b/src/settings/index.ts index 9b0f0d2..bfe6541 100644 --- a/src/settings/index.ts +++ b/src/settings/index.ts @@ -18,6 +18,6 @@ const params = { consent: validateConsent, }; -export function settingsValidator(config: any) { +export function settingsFactory(config: any) { return settingsValidation(config, params); } diff --git a/src/splitFactory.ts b/src/splitFactory.ts index c782d43..db14cd3 100644 --- a/src/splitFactory.ts +++ b/src/splitFactory.ts @@ -1,4 +1,4 @@ -import { settingsValidator } from './settings'; +import { settingsFactory } from './settings'; import { getModules } from './platform/getModules'; import { sdkFactory } from '@splitsoftware/splitio-commons/src/sdkFactory/index'; import { ISdkFactoryParams } from '@splitsoftware/splitio-commons/src/sdkFactory/types'; @@ -6,6 +6,7 @@ import { getFetch } from './platform/getFetchSlim'; import { getEventSource } from './platform/getEventSource'; import { EventEmitter } from '@splitsoftware/splitio-commons/src/utils/MinEvents'; import { now } from '@splitsoftware/splitio-commons/src/utils/timeTracker/now/browser'; +import { IBrowserSettings } from '../types/splitio'; const platform = { getFetch, getEventSource, EventEmitter, now }; @@ -18,8 +19,8 @@ const platform = { getFetch, getEventSource, EventEmitter, now }; * caution since, unlike `config`, this param is not validated neither considered part of the public API. * @throws Will throw an error if the provided config is invalid. */ -export function SplitFactory(config: any, __updateModules?: (modules: ISdkFactoryParams) => void) { - const settings = settingsValidator(config); +export function SplitFactory(config: IBrowserSettings, __updateModules?: (modules: ISdkFactoryParams) => void) { + const settings = settingsFactory(config); const modules = getModules(settings, platform); if (__updateModules) __updateModules(modules); return sdkFactory(modules); diff --git a/types/splitio.d.ts b/types/splitio.d.ts index be289de..d54f534 100644 --- a/types/splitio.d.ts +++ b/types/splitio.d.ts @@ -91,8 +91,8 @@ interface ISettings { readonly sync: { splitFilters: SplitIO.SplitFilter[], impressionsMode: SplitIO.ImpressionsMode, - localhostMode?: SplitIO.LocalhostFactory, - enabled?: boolean + enabled: boolean, + localhostMode?: SplitIO.LocalhostFactory }, readonly userConsent: SplitIO.ConsentStatus } @@ -247,7 +247,7 @@ interface ISharedSettings { * Controls the SDK continuous synchronization flags. * * When `true` a running SDK will process rollout plan updates performed on the UI (default). - * When false it'll just fetch all data upon init + * When false it'll just fetch all data upon init. * * @property {boolean} enabled * @default true From b2bde23fb98f146833067ab630eac336989775ce Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 29 Jul 2022 15:32:14 -0300 Subject: [PATCH 04/23] update on destroy test --- src/__tests__/destroy/browser.spec.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/__tests__/destroy/browser.spec.js b/src/__tests__/destroy/browser.spec.js index 7f9ef38..149a5a3 100644 --- a/src/__tests__/destroy/browser.spec.js +++ b/src/__tests__/destroy/browser.spec.js @@ -3,7 +3,7 @@ import fetchMock from '../testUtils/fetchMock'; import { url } from '../testUtils'; import map from 'lodash/map'; import pick from 'lodash/pick'; -import { SplitFactory, DebugLogger } from '../../'; +import { SplitFactory } from '../../'; import { settingsFactory } from '../../settings'; import splitChangesMock1 from '../mocks/splitChanges.since.-1.till.1500492097547.json'; import splitChangesMock2 from '../mocks/splitChanges.since.1500492097547.json'; @@ -30,7 +30,6 @@ tape('SDK destroy for BrowserJS', async function (assert) { authorizationKey: 'fake-key', key: 'ut1' }, - debug: DebugLogger(), streamingEnabled: false }; From ae9c6a0ed4816dfa8f4ee6c67b148b0d309bc32b Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 3 Aug 2022 11:50:08 -0300 Subject: [PATCH 05/23] formatting --- src/__tests__/browserSuites/impressions-listener.spec.js | 1 + src/__tests__/browserSuites/push-initialization-nopush.spec.js | 1 + src/__tests__/browserSuites/push-initialization-retries.spec.js | 2 ++ src/__tests__/browserSuites/push-refresh-token.spec.js | 1 + .../browserSuites/push-synchronization-retries.spec.js | 2 ++ src/__tests__/browserSuites/use-beacon-api.spec.js | 2 +- src/__tests__/browserSuites/user-consent.spec.js | 2 +- src/__tests__/destroy/browser.spec.js | 1 + src/__tests__/gaIntegration/browser.spec.js | 2 ++ 9 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/__tests__/browserSuites/impressions-listener.spec.js b/src/__tests__/browserSuites/impressions-listener.spec.js index 644d3d6..de6c41e 100644 --- a/src/__tests__/browserSuites/impressions-listener.spec.js +++ b/src/__tests__/browserSuites/impressions-listener.spec.js @@ -1,4 +1,5 @@ import sinon from 'sinon'; + import { SplitFactory } from '../../'; import { settingsFactory } from '../../settings'; diff --git a/src/__tests__/browserSuites/push-initialization-nopush.spec.js b/src/__tests__/browserSuites/push-initialization-nopush.spec.js index 0126293..6e0e0a4 100644 --- a/src/__tests__/browserSuites/push-initialization-nopush.spec.js +++ b/src/__tests__/browserSuites/push-initialization-nopush.spec.js @@ -7,6 +7,7 @@ import authPushDisabled from '../mocks/auth.pushDisabled.json'; import authPushEnabledNicolas from '../mocks/auth.pushEnabled.nicolas@split.io.json'; import authInvalidCredentials from '../mocks/auth.invalidCredentials.txt'; import { nearlyEqual, url } from '../testUtils'; + import EventSourceMock, { setMockListener } from '../testUtils/eventSourceMock'; const baseUrls = { diff --git a/src/__tests__/browserSuites/push-initialization-retries.spec.js b/src/__tests__/browserSuites/push-initialization-retries.spec.js index 87d96d7..4d72ee1 100644 --- a/src/__tests__/browserSuites/push-initialization-retries.spec.js +++ b/src/__tests__/browserSuites/push-initialization-retries.spec.js @@ -6,7 +6,9 @@ import authPushBadToken from '../mocks/auth.pushBadToken.json'; import mySegmentsNicolasMock from '../mocks/mysegments.nicolas@split.io.json'; import { nearlyEqual, url } from '../testUtils'; + import EventSourceMock, { setMockListener } from '../testUtils/eventSourceMock'; + import { SplitFactory } from '../../'; import { settingsFactory } from '../../settings'; diff --git a/src/__tests__/browserSuites/push-refresh-token.spec.js b/src/__tests__/browserSuites/push-refresh-token.spec.js index 0ff61a2..8a22650 100644 --- a/src/__tests__/browserSuites/push-refresh-token.spec.js +++ b/src/__tests__/browserSuites/push-refresh-token.spec.js @@ -1,6 +1,7 @@ import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json'; import mySegmentsNicolasMock1 from '../mocks/mysegments.nicolas@split.io.json'; + import authPushEnabledNicolas from '../mocks/auth.pushEnabled.nicolas@split.io.601secs.json'; import authPushDisabled from '../mocks/auth.pushDisabled.json'; diff --git a/src/__tests__/browserSuites/push-synchronization-retries.spec.js b/src/__tests__/browserSuites/push-synchronization-retries.spec.js index 855a349..03c7955 100644 --- a/src/__tests__/browserSuites/push-synchronization-retries.spec.js +++ b/src/__tests__/browserSuites/push-synchronization-retries.spec.js @@ -4,10 +4,12 @@ import splitChangesMock3 from '../mocks/splitchanges.since.1457552620999.till.14 import mySegmentsNicolasMock1 from '../mocks/mysegments.nicolas@split.io.json'; import mySegmentsNicolasMock2 from '../mocks/mysegments.nicolas@split.io.mock2.json'; import mySegmentsMarcio from '../mocks/mysegments.marcio@split.io.json'; + import splitUpdateMessage from '../mocks/message.SPLIT_UPDATE.1457552649999.json'; import oldSplitUpdateMessage from '../mocks/message.SPLIT_UPDATE.1457552620999.json'; import mySegmentsUpdateMessage from '../mocks/message.MY_SEGMENTS_UPDATE.nicolas@split.io.1457552640000.json'; import splitKillMessage from '../mocks/message.SPLIT_KILL.1457552650000.json'; + import authPushEnabledNicolas from '../mocks/auth.pushEnabled.nicolas@split.io.json'; import { nearlyEqual, url } from '../testUtils'; diff --git a/src/__tests__/browserSuites/use-beacon-api.spec.js b/src/__tests__/browserSuites/use-beacon-api.spec.js index 27bea08..8cb2122 100644 --- a/src/__tests__/browserSuites/use-beacon-api.spec.js +++ b/src/__tests__/browserSuites/use-beacon-api.spec.js @@ -3,8 +3,8 @@ import { SplitFactory } from '../../'; import { settingsFactory } from '../../settings'; import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import mySegmentsFacundo from '../mocks/mysegments.facundo@split.io.json'; -import { OPTIMIZED } from '@splitsoftware/splitio-commons/src/utils/constants'; import { url } from '../testUtils'; +import { OPTIMIZED } from '@splitsoftware/splitio-commons/src/utils/constants'; import { triggerPagehideEvent, triggerVisibilitychange } from '../testUtils/browser'; const config = { diff --git a/src/__tests__/browserSuites/user-consent.spec.js b/src/__tests__/browserSuites/user-consent.spec.js index 2334916..7dd3cad 100644 --- a/src/__tests__/browserSuites/user-consent.spec.js +++ b/src/__tests__/browserSuites/user-consent.spec.js @@ -1,7 +1,7 @@ import sinon from 'sinon'; import { SplitFactory } from '../../'; -import { nearlyEqual, url } from '../testUtils'; import { triggerPagehideEvent } from '../testUtils/browser'; +import { nearlyEqual, url } from '../testUtils'; const trackedImpressions = []; diff --git a/src/__tests__/destroy/browser.spec.js b/src/__tests__/destroy/browser.spec.js index 149a5a3..2c1b3d2 100644 --- a/src/__tests__/destroy/browser.spec.js +++ b/src/__tests__/destroy/browser.spec.js @@ -5,6 +5,7 @@ import map from 'lodash/map'; import pick from 'lodash/pick'; import { SplitFactory } from '../../'; import { settingsFactory } from '../../settings'; + import splitChangesMock1 from '../mocks/splitChanges.since.-1.till.1500492097547.json'; import splitChangesMock2 from '../mocks/splitChanges.since.1500492097547.json'; import mySegmentsMock from '../mocks/mySegmentsEmpty.json'; diff --git a/src/__tests__/gaIntegration/browser.spec.js b/src/__tests__/gaIntegration/browser.spec.js index 2248fb5..6d61aea 100644 --- a/src/__tests__/gaIntegration/browser.spec.js +++ b/src/__tests__/gaIntegration/browser.spec.js @@ -4,7 +4,9 @@ import { url } from '../testUtils'; import gaToSplitSuite from './ga-to-split.spec'; import splitToGaSuite from './split-to-ga.spec'; import bothIntegrationsSuite from './both-integrations.spec'; + import { settingsFactory } from '../../settings'; + import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import mySegmentsFacundo from '../mocks/mysegments.facundo@split.io.json'; From 4a381c155a8473428ed5a078c112e503c4539a69 Mon Sep 17 00:00:00 2001 From: Luciano Caravajal Date: Thu, 4 Aug 2022 16:14:14 -0300 Subject: [PATCH 06/23] Add sonar to ci-cd pipeline --- .github/workflows/ci-cd.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 86739af..797cb96 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -72,3 +72,33 @@ jobs: SOURCE_DIR: ./umd DEST_DIR: sdk ARGS: --acl public-read --follow-symlinks --cache-control max-age=31536000,public + + - name: SonarQube Scan (Push) + if: github.event_name == 'push' + uses: SonarSource/sonarcloud-github-action@v1.5 + env: + SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }} + with: + projectBaseDir: . + args: > + -Dsonar.host.url=${{ secrets.SONARQUBE_HOST }} + -Dsonar.projectName=${{ github.event.repository.name }} + -Dsonar.projectKey=${{ github.event.repository.name }} + -Dsonar.links.ci="https://github.com/splitio/${{ github.event.repository.name }}/actions" + -Dsonar.links.scm="https://github.com/splitio/${{ github.event.repository.name }}" + - name: SonarQube Scan (Pull Request) + if: github.event_name == 'pull_request' + uses: SonarSource/sonarcloud-github-action@v1.5 + env: + SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }} + with: + projectBaseDir: . + args: > + -Dsonar.host.url=${{ secrets.SONARQUBE_HOST }} + -Dsonar.projectName=${{ github.event.repository.name }} + -Dsonar.projectKey=${{ github.event.repository.name }} + -Dsonar.links.ci="https://github.com/splitio/${{ github.event.repository.name }}/actions" + -Dsonar.links.scm="https://github.com/splitio/${{ github.event.repository.name }}" + -Dsonar.pullrequest.key=${{ github.event.pull_request.number }} + -Dsonar.pullrequest.branch=${{ github.event.pull_request.head.ref }} + -Dsonar.pullrequest.base=${{ github.event.pull_request.base.ref }} From 6903c1f05fdf1bf379b722f703295efcc072db45 Mon Sep 17 00:00:00 2001 From: Luciano Caravajal Date: Thu, 4 Aug 2022 18:10:43 -0300 Subject: [PATCH 07/23] Moved sonar to a different workflow --- .github/workflows/ci-cd.yml | 30 -------------- .github/workflows/sonar-scan.yml | 69 ++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 30 deletions(-) create mode 100644 .github/workflows/sonar-scan.yml diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 797cb96..86739af 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -72,33 +72,3 @@ jobs: SOURCE_DIR: ./umd DEST_DIR: sdk ARGS: --acl public-read --follow-symlinks --cache-control max-age=31536000,public - - - name: SonarQube Scan (Push) - if: github.event_name == 'push' - uses: SonarSource/sonarcloud-github-action@v1.5 - env: - SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }} - with: - projectBaseDir: . - args: > - -Dsonar.host.url=${{ secrets.SONARQUBE_HOST }} - -Dsonar.projectName=${{ github.event.repository.name }} - -Dsonar.projectKey=${{ github.event.repository.name }} - -Dsonar.links.ci="https://github.com/splitio/${{ github.event.repository.name }}/actions" - -Dsonar.links.scm="https://github.com/splitio/${{ github.event.repository.name }}" - - name: SonarQube Scan (Pull Request) - if: github.event_name == 'pull_request' - uses: SonarSource/sonarcloud-github-action@v1.5 - env: - SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }} - with: - projectBaseDir: . - args: > - -Dsonar.host.url=${{ secrets.SONARQUBE_HOST }} - -Dsonar.projectName=${{ github.event.repository.name }} - -Dsonar.projectKey=${{ github.event.repository.name }} - -Dsonar.links.ci="https://github.com/splitio/${{ github.event.repository.name }}/actions" - -Dsonar.links.scm="https://github.com/splitio/${{ github.event.repository.name }}" - -Dsonar.pullrequest.key=${{ github.event.pull_request.number }} - -Dsonar.pullrequest.branch=${{ github.event.pull_request.head.ref }} - -Dsonar.pullrequest.base=${{ github.event.pull_request.base.ref }} diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml new file mode 100644 index 0000000..623542f --- /dev/null +++ b/.github/workflows/sonar-scan.yml @@ -0,0 +1,69 @@ +name: ci-cd +on: + pull_request: + branches: + - main + - development + push: + branches: + - main + - development + +permissions: + contents: read + id-token: write + +jobs: + build: + name: Build + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up nodejs + uses: actions/setup-node@v2 + with: + node-version: '14' + cache: 'npm' + + - name: npm CI + run: npm ci + + - name: npm Check + run: npm run check + + - name: npm Build + run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") BUILD_COMMIT=${{ github.sha }} npm run build + + - name: SonarQube Scan (Push) + if: github.event_name == 'push' + uses: SonarSource/sonarcloud-github-action@v1.6 + env: + SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }} + with: + projectBaseDir: . + args: > + -Dsonar.host.url=${{ secrets.SONARQUBE_HOST }} + -Dsonar.projectName=${{ github.event.repository.name }} + -Dsonar.projectKey=${{ github.event.repository.name }} + -Dsonar.links.ci="https://github.com/splitio/${{ github.event.repository.name }}/actions" + -Dsonar.links.scm="https://github.com/splitio/${{ github.event.repository.name }}" + - name: SonarQube Scan (Pull Request) + if: github.event_name == 'pull_request' + uses: SonarSource/sonarcloud-github-action@v1.5 + env: + SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }} + with: + projectBaseDir: . + args: > + -Dsonar.host.url=${{ secrets.SONARQUBE_HOST }} + -Dsonar.projectName=${{ github.event.repository.name }} + -Dsonar.projectKey=${{ github.event.repository.name }} + -Dsonar.links.ci="https://github.com/splitio/${{ github.event.repository.name }}/actions" + -Dsonar.links.scm="https://github.com/splitio/${{ github.event.repository.name }}" + -Dsonar.pullrequest.key=${{ github.event.pull_request.number }} + -Dsonar.pullrequest.branch=${{ github.event.pull_request.head.ref }} + -Dsonar.pullrequest.base=${{ github.event.pull_request.base.ref }} From 5f22d72d289092b1feb54749ea5e5628502820b2 Mon Sep 17 00:00:00 2001 From: Luciano Caravajal Date: Thu, 4 Aug 2022 18:12:10 -0300 Subject: [PATCH 08/23] Rename sonar workflow --- .github/workflows/sonar-scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml index 623542f..7180a9e 100644 --- a/.github/workflows/sonar-scan.yml +++ b/.github/workflows/sonar-scan.yml @@ -1,4 +1,4 @@ -name: ci-cd +name: sonar-scan on: pull_request: branches: From 220499c2b0c2c0c7b9e67e560eba48f125eac94f Mon Sep 17 00:00:00 2001 From: Luciano Caravajal Date: Thu, 4 Aug 2022 18:37:37 -0300 Subject: [PATCH 09/23] Removed not required permissions --- .github/workflows/sonar-scan.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml index 7180a9e..3354a30 100644 --- a/.github/workflows/sonar-scan.yml +++ b/.github/workflows/sonar-scan.yml @@ -9,10 +9,6 @@ on: - main - development -permissions: - contents: read - id-token: write - jobs: build: name: Build From e2f499d9f51d076d0343151d4f5de88dd80da227 Mon Sep 17 00:00:00 2001 From: Luciano Caravajal Date: Thu, 4 Aug 2022 18:52:34 -0300 Subject: [PATCH 10/23] Update sonar github version --- .github/workflows/sonar-scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml index 3354a30..7e428af 100644 --- a/.github/workflows/sonar-scan.yml +++ b/.github/workflows/sonar-scan.yml @@ -49,7 +49,7 @@ jobs: -Dsonar.links.scm="https://github.com/splitio/${{ github.event.repository.name }}" - name: SonarQube Scan (Pull Request) if: github.event_name == 'pull_request' - uses: SonarSource/sonarcloud-github-action@v1.5 + uses: SonarSource/sonarcloud-github-action@v1.6 env: SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }} with: From 9078e335f2a87330eaa7fd88f2a95fbeaf530f95 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 14 Sep 2022 17:15:51 +0200 Subject: [PATCH 11/23] update e2e tests to assert telemetry with pluggable storage --- CHANGES.txt | 3 +++ karma/config.debug.js | 15 ++++++++++++ package-lock.json | 6 ++--- package.json | 2 +- .../browserSuites/ready-from-cache.spec.js | 2 +- .../browserSuites/ready-promise.spec.js | 2 +- .../consumer/browser_consumer.spec.js | 24 ++++++++++++++----- .../consumer/browser_consumer_partial.spec.js | 23 +++++++++++------- 8 files changed, 56 insertions(+), 21 deletions(-) create mode 100644 karma/config.debug.js diff --git a/CHANGES.txt b/CHANGES.txt index e52991f..213a27b 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,6 @@ +0.8.1 (September XXX, 2022) +- Updated @splitsoftware/splitio-commons package to version 1.6.2, that improves the performance of split evaluations (i.e., `getTreatment(s)` method calls) when using the default storage in memory. + 0.8.0 (July 22, 2022) - Added `autoRequire` configuration option to the Google Analytics to Split integration, which takes care of requiring the splitTracker plugin on trackers dynamically created by Google tag managers (See https://help.split.io/hc/en-us/articles/360040838752#set-up-with-gtm-and-gtag.js). - Updated browser listener to push remaining impressions and events on 'visibilitychange' and 'pagehide' DOM events, instead of 'unload', which is not reliable in modern mobile and desktop Web browsers. diff --git a/karma/config.debug.js b/karma/config.debug.js new file mode 100644 index 0000000..4e2bfe9 --- /dev/null +++ b/karma/config.debug.js @@ -0,0 +1,15 @@ +'use strict'; + +const merge = require('lodash/merge'); + +module.exports = merge({}, require('./config'), { + browsers: [ + 'Chrome' + ], + rollupPreprocessor: { + output: { + sourcemap: 'inline', + }, + }, + singleRun: false +}); diff --git a/package-lock.json b/package-lock.json index 91f54f5..742795d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2194,9 +2194,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.6.1.tgz", - "integrity": "sha512-lijSMpX5a7HiphPnzr7fKlicGSd5TeBWX5URLPWfL87SPlO+8iF7S7PNFPg8GMu+44CdRrp4REHPJo97ht6ePQ==", + "version": "1.6.2-rc.9", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.6.2-rc.9.tgz", + "integrity": "sha512-pUTAuhZlkTBgs5nGu5in4jDdlvj0yPRdnqXWUjNml4+GmRuUx827R8FL07jFHV2m88K9BbqZfpztsgbis5hRHQ==", "requires": { "tslib": "^2.3.1" } diff --git a/package.json b/package.json index 86f79ad..a35a08c 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "bugs": "https://github.com/splitio/javascript-browser-client/issues", "homepage": "https://github.com/splitio/javascript-browser-client#readme", "dependencies": { - "@splitsoftware/splitio-commons": "1.6.1", + "@splitsoftware/splitio-commons": "1.6.2-rc.9", "@types/google.analytics": "0.0.40" }, "devDependencies": { diff --git a/src/__tests__/browserSuites/ready-from-cache.spec.js b/src/__tests__/browserSuites/ready-from-cache.spec.js index 7909278..8997e00 100644 --- a/src/__tests__/browserSuites/ready-from-cache.spec.js +++ b/src/__tests__/browserSuites/ready-from-cache.spec.js @@ -687,7 +687,7 @@ export default function (fetchMock, assert) { localStorage.setItem('readyFromCache_8.SPLITIO.splits.till', 25); localStorage.setItem('readyFromCache_8.SPLITIO.split.p1__split', JSON.stringify(splitDeclarations.p1__split)); localStorage.setItem('readyFromCache_8.SPLITIO.split.p2__split', JSON.stringify(splitDeclarations.p2__split)); - localStorage.setItem('readyFromCache_8.SPLITIO.split.deleted__split', 'deleted_split'); + localStorage.setItem('readyFromCache_8.SPLITIO.split.deleted__split', '{ "name": "deleted_split" }'); localStorage.setItem('readyFromCache_8.SPLITIO.splits.filterQuery', '&names=p2__split&prefixes=p1'); const splitio = SplitFactory({ diff --git a/src/__tests__/browserSuites/ready-promise.spec.js b/src/__tests__/browserSuites/ready-promise.spec.js index c127a7c..0a111e3 100644 --- a/src/__tests__/browserSuites/ready-promise.spec.js +++ b/src/__tests__/browserSuites/ready-promise.spec.js @@ -562,7 +562,7 @@ export default function readyPromiseAssertions(fetchMock, assert) { t.end(); }); }); - }, 0); + }, 10); }); }, fromSecondsToMillis(0.2)); diff --git a/src/__tests__/consumer/browser_consumer.spec.js b/src/__tests__/consumer/browser_consumer.spec.js index f2575b6..b3f206b 100644 --- a/src/__tests__/consumer/browser_consumer.spec.js +++ b/src/__tests__/consumer/browser_consumer.spec.js @@ -4,6 +4,7 @@ import { inMemoryWrapperFactory } from '@splitsoftware/splitio-commons/src/stora import { SDK_NOT_READY, EXCEPTION } from '@splitsoftware/splitio-commons/src/utils/labels'; import { applyOperations } from './wrapper-commands'; import { nearlyEqual } from '../testUtils'; +import { version } from '../../../package.json'; import { SplitFactory, PluggableStorage } from '../../'; @@ -11,7 +12,7 @@ const expectedSplitName = 'hierarchical_splits_testing_on'; const expectedSplitView = { name: 'hierarchical_splits_testing_on', trafficType: 'user', killed: false, changeNumber: 1487277320548, treatments: ['on', 'off'], configs: {} }; const wrapperPrefix = 'PLUGGABLE_STORAGE_UT'; -const wrapperInstance = inMemoryWrapperFactory(0); +const wrapperInstance = inMemoryWrapperFactory(); const TOTAL_RAW_IMPRESSIONS = 18; const TOTAL_EVENTS = 5; @@ -39,13 +40,16 @@ tape('Browser Consumer mode with pluggable storage', function (t) { const impressions = []; const disconnectSpy = sinon.spy(wrapperInstance, 'disconnect'); - const expectedConfig = '{"color":"brown"}'; + // Overwrite Math.random to track telemetry + const originalMathRandom = Math.random; Math.random = () => 0.001; const sdk = SplitFactory({ ...config, impressionListener: { logImpression(data) { impressions.push(data); } } }); + Math.random = originalMathRandom; // restore + const client = sdk.client(); const otherClient = sdk.client('emi@split.io'); const manager = sdk.manager(); @@ -59,7 +63,6 @@ tape('Browser Consumer mode with pluggable storage', function (t) { const splitsResult = manager.splits(); assert.equal(typeof getTreatmentResult.then, 'function', 'GetTreatment calls should always return a promise on Consumer mode.'); - // @TODO caveat: if wrapper.connect is resolved before wrapper operations, next evaluation might be different than control assert.equal(await getTreatmentResult, 'control', 'Evaluations using pluggable storage should be control if initiated before SDK_READY.'); assert.equal(client.__getStatus().isReadyFromCache, false, 'SDK in consumer mode is not operational inmediatelly'); assert.equal(client.__getStatus().isReady, false, 'SDK in consumer mode is not operational inmediatelly'); @@ -106,7 +109,7 @@ tape('Browser Consumer mode with pluggable storage', function (t) { client.clearAttributes(); assert.deepEqual(await client.getTreatmentWithConfig('always-o.n-with-config'), { treatment: 'o.n', - config: expectedConfig + config: '{"color":"brown"}' }, 'Evaluations using pluggable storage should be correct, including configs.'); assert.equal(await client.getTreatment('always-on'), 'on', 'Evaluations using pluggable storage should be correct.'); @@ -134,8 +137,8 @@ tape('Browser Consumer mode with pluggable storage', function (t) { // New shared client created const newClient = sdk.client('other'); - assert.true(await newClient.track('user', 'test.event', 18), 'Track should attempt to track, whether SDK_READY has been emitted or not.'); - assert.equal((await newClient.getTreatment('UT_IN_SEGMENT')), 'control', '`getTreatment` evaluation is control if shared client is not ready yet.'); + newClient.track('user', 'test.event', 18).then(result => assert.true(result, 'Track should attempt to track, whether SDK_READY has been emitted or not.')); + newClient.getTreatment('UT_IN_SEGMENT').then(result => assert.equal(result, 'control', '`getTreatment` evaluation is control if shared client is not ready yet.')); await newClient.ready(); assert.true(await newClient.track('user', 'test.event', 18), 'Track should attempt to track, whether SDK_READY has been emitted or not.'); @@ -148,11 +151,20 @@ tape('Browser Consumer mode with pluggable storage', function (t) { assert.equal(disconnectSpy.callCount, 1, 'Wrapper disconnect method should be called only once, when the main client is destroyed'); + // Validate stored impressions and events const trackedImpressions = await wrapperInstance.popItems('PLUGGABLE_STORAGE_UT.SPLITIO.impressions', await wrapperInstance.getItemsCount('PLUGGABLE_STORAGE_UT.SPLITIO.impressions')); const trackedEvents = await wrapperInstance.popItems('PLUGGABLE_STORAGE_UT.SPLITIO.events', await wrapperInstance.getItemsCount('PLUGGABLE_STORAGE_UT.SPLITIO.events')); assert.equal(trackedImpressions.length, TOTAL_RAW_IMPRESSIONS, 'Tracked impressions should be present in the external storage'); assert.equal(trackedEvents.length, TOTAL_EVENTS, 'Tracked events should be present in the external storage'); + // Validate stored telemetry + const latencies = await wrapperInstance.getKeysByPrefix(`PLUGGABLE_STORAGE_UT.SPLITIO.telemetry.latencies::browserjs-${version}/unknown/unknown`); + assert.true(latencies.length > 0, 'There are stored latencies'); + const exceptions = await wrapperInstance.getKeysByPrefix(`PLUGGABLE_STORAGE_UT.SPLITIO.telemetry.exceptions::browserjs-${version}/unknown/unknown`); + assert.true(exceptions.length === 0, 'There aren\'t stored exceptions'); + const configValue = await wrapperInstance.get(`PLUGGABLE_STORAGE_UT.SPLITIO.telemetry.init::browserjs-${version}/unknown/unknown`); + assert.deepEqual(JSON.parse(configValue), { oM: 1, st: 'pluggable', aF: 1, rF: 0 }, 'There is stored telemetry config'); + // Assert impressionsListener setTimeout(() => { assert.equal(impressions.length, TOTAL_RAW_IMPRESSIONS, 'Each evaluation has its corresponting impression'); diff --git a/src/__tests__/consumer/browser_consumer_partial.spec.js b/src/__tests__/consumer/browser_consumer_partial.spec.js index b487880..4f493c7 100644 --- a/src/__tests__/consumer/browser_consumer_partial.spec.js +++ b/src/__tests__/consumer/browser_consumer_partial.spec.js @@ -13,7 +13,7 @@ const expectedSplitName = 'hierarchical_splits_testing_on'; const expectedSplitView = { name: 'hierarchical_splits_testing_on', trafficType: 'user', killed: false, changeNumber: 1487277320548, treatments: ['on', 'off'], configs: {} }; const wrapperPrefix = 'PLUGGABLE_STORAGE_UT'; -const wrapperInstance = inMemoryWrapperFactory(0); +const wrapperInstance = inMemoryWrapperFactory(); const TOTAL_RAW_IMPRESSIONS = 17; const TOTAL_EVENTS = 5; @@ -33,7 +33,8 @@ const config = { // }, urls: { sdk: 'https://sdk.baseurl/impressionsSuite', - events: 'https://events.baseurl/impressionsSuite' + events: 'https://events.baseurl/impressionsSuite', + telemetry: 'https://telemetry.baseurl/impressionsSuite' } }; @@ -55,6 +56,8 @@ tape('Browser Consumer Partial mode with pluggable storage', function (t) { }); fetchMock.postOnce(url(config, '/testImpressions/count'), 200); + fetchMock.postOnce(url(config, '/v1/metrics/config'), 200); + fetchMock.postOnce(url(config, '/v1/metrics/usage'), 200); fetchMock.postOnce(url(config, '/events/bulk'), (url, req) => { const resp = JSON.parse(req.body); @@ -69,13 +72,16 @@ tape('Browser Consumer Partial mode with pluggable storage', function (t) { const impressions = []; const disconnectSpy = sinon.spy(wrapperInstance, 'disconnect'); - const expectedConfig = '{"color":"brown"}'; + // Overwrite Math.random to track telemetry + const originalMathRandom = Math.random; Math.random = () => 0.001; const sdk = SplitFactory({ ...config, impressionListener: { logImpression(data) { impressions.push(data); } } }); + Math.random = originalMathRandom; // restore + const client = sdk.client(); const otherClient = sdk.client('emi@split.io'); const manager = sdk.manager(); @@ -89,7 +95,6 @@ tape('Browser Consumer Partial mode with pluggable storage', function (t) { const splitsResult = manager.splits(); assert.equal(typeof getTreatmentResult.then, 'function', 'GetTreatment calls should always return a promise on Consumer mode.'); - // @TODO caveat: if wrapper.connect is resolved before wrapper operations, next evaluation might be different than control assert.equal(await getTreatmentResult, 'control', 'Evaluations using pluggable storage should be control if initiated before SDK_READY.'); assert.equal(client.__getStatus().isReadyFromCache, false, 'SDK in consumer mode is not operational inmediatelly'); assert.equal(client.__getStatus().isReady, false, 'SDK in consumer mode is not operational inmediatelly'); @@ -135,7 +140,7 @@ tape('Browser Consumer Partial mode with pluggable storage', function (t) { }, 'Evaluations using pluggable storage should be correct, including configs.'); assert.deepEqual(await client.getTreatmentWithConfig('always-o.n-with-config'), { treatment: 'o.n', - config: expectedConfig + config: '{"color":"brown"}' }, 'Evaluations using pluggable storage should be correct, including configs.'); assert.equal(await client.getTreatment('always-on'), 'on', 'Evaluations using pluggable storage should be correct.'); @@ -163,8 +168,8 @@ tape('Browser Consumer Partial mode with pluggable storage', function (t) { // New shared client created const newClient = sdk.client('other'); - assert.true(await newClient.track('user', 'test.event', 18), 'Track should attempt to track, whether SDK_READY has been emitted or not.'); - assert.equal((await newClient.getTreatment('UT_IN_SEGMENT')), 'control', '`getTreatment` evaluation is control if shared client is not ready yet.'); + newClient.track('user', 'test.event', 18).then(result => assert.true(result, 'Track should attempt to track, whether SDK_READY has been emitted or not.')); + newClient.getTreatment('UT_IN_SEGMENT').then(result => assert.equal(result, 'control', '`getTreatment` evaluation is control if shared client is not ready yet.')); await newClient.ready(); assert.true(await newClient.track('user', 'test.event', 18), 'Track should attempt to track, whether SDK_READY has been emitted or not.'); @@ -174,9 +179,9 @@ tape('Browser Consumer Partial mode with pluggable storage', function (t) { await newClient.destroy(); await otherClient.destroy(); - assert.false(fetchMock.called(), 'fetch hasn\'t been called yet'); + assert.equal(fetchMock.calls().length, 1, 'fetch has been called once for posting telemetry config stats'); await client.destroy(); - assert.equal(fetchMock.calls().length, 3, 'fetch has been called 3 times, for posting events, impressions and impression counts, after main client is destroyed'); + assert.equal(fetchMock.calls().length, 5, 'fetch has been called 5 times after main client is destroyed, for posting events, impressions, impression counts, telemetry config and usage stats'); assert.equal(disconnectSpy.callCount, 1, 'Wrapper disconnect method should be called only once, when the main client is destroyed'); From f82e255e808e8c64d5802925ab9b2aae90422371 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Mon, 19 Sep 2022 17:40:07 -0300 Subject: [PATCH 12/23] upgrade js-commons and tests to support NONE impressions mode --- src/__tests__/browserSuites/impressions.spec.js | 2 +- src/__tests__/browserSuites/telemetry.spec.js | 6 ++++-- src/__tests__/browserSuites/use-beacon-api.spec.js | 6 ++++-- src/__tests__/browserSuites/user-consent.spec.js | 3 ++- src/__tests__/consumer/browser_consumer.spec.js | 7 +++++-- src/__tests__/consumer/browser_consumer_partial.spec.js | 2 +- src/__tests__/testUtils/index.js | 2 +- src/platform/getModules.ts | 3 +-- types/splitio.d.ts | 2 +- 9 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/__tests__/browserSuites/impressions.spec.js b/src/__tests__/browserSuites/impressions.spec.js index 8e73c5d..6be91e6 100644 --- a/src/__tests__/browserSuites/impressions.spec.js +++ b/src/__tests__/browserSuites/impressions.spec.js @@ -94,7 +94,7 @@ export default function (fetchMock, assert) { fetchMock.postOnce(url(settings, '/testImpressions/count'), (url, opts) => { const data = JSON.parse(opts.body); - assert.equal(data.pf.length, 2, 'We should generated 2 impressions count.'); + assert.equal(data.pf.length, 1, 'We should generate impressions count for one feature.'); // finding these validate the feature names collection too const dependencyChildImpr = data.pf.filter(e => e.f === 'hierarchical_splits_test')[0]; diff --git a/src/__tests__/browserSuites/telemetry.spec.js b/src/__tests__/browserSuites/telemetry.spec.js index e6ebbad..80f1ac1 100644 --- a/src/__tests__/browserSuites/telemetry.spec.js +++ b/src/__tests__/browserSuites/telemetry.spec.js @@ -69,8 +69,9 @@ export default async function telemetryBrowserSuite(fetchMock, assert) { assert.equal(getLatencyCount(data.mL.tr), 1, 'One latency metric for track'); delete data.hL; delete data.mL; + // @TODO check if iDe value is correct assert.deepEqual(data, { - mE: {}, hE: { sp: { 500: 1 }, ms: { 500: 1 } }, tR: 0, aR: 0, iQ: 4, iDe: 3, iDr: 0, spC: 31, seC: 1, skC: 1, eQ: 1, eD: 0, sE: [], t: [] + mE: {}, hE: { sp: { 500: 1 }, ms: { 500: 1 } }, tR: 0, aR: 0, iQ: 4, iDe: 1, iDr: 0, spC: 31, seC: 1, skC: 1, eQ: 1, eD: 0, sE: [], t: [] }, 'metrics/usage JSON payload should be the expected'); finish.next(); @@ -87,9 +88,10 @@ export default async function telemetryBrowserSuite(fetchMock, assert) { assert.true(data.sL > 0, 'sessionLengthMs must be defined'); delete data.sL; + // @TODO check if iDe value is correct assert.deepEqual(data, { mL: {}, mE: {}, hE: {}, hL: {}, // errors and latencies were popped - tR: 0, aR: 0, iQ: 4, iDe: 3, iDr: 0, spC: 31, seC: 1, skC: 1, eQ: 1, eD: 0, sE: [], t: [] + tR: 0, aR: 0, iQ: 4, iDe: 1, iDr: 0, spC: 31, seC: 1, skC: 1, eQ: 1, eD: 0, sE: [], t: [] }, '2nd metrics/usage JSON payload should be the expected'); return 200; }); diff --git a/src/__tests__/browserSuites/use-beacon-api.spec.js b/src/__tests__/browserSuites/use-beacon-api.spec.js index 8cb2122..41ab094 100644 --- a/src/__tests__/browserSuites/use-beacon-api.spec.js +++ b/src/__tests__/browserSuites/use-beacon-api.spec.js @@ -110,7 +110,8 @@ function beaconApiSendTest(fetchMock, assert) { const splitio = SplitFactory(config); const client = splitio.client(); client.on(client.Event.SDK_READY, () => { - client.getTreatment('hierarchical_splits_test'); + client.getTreatment('hierarchical_splits_test'); // first impression counted in backend + client.getTreatment('hierarchical_splits_test'); // impression counted in sdk client.track('sometraffictype', 'someEvent', 10); // trigger both events inmmediatly, before scheduled push of events and impressions, to assert that beacon requests are not duplicated @@ -174,7 +175,8 @@ function fallbackTest(fetchMock, assert) { }); client.on(client.Event.SDK_READY, () => { - client.getTreatment('hierarchical_splits_test'); + client.getTreatment('hierarchical_splits_test');// first impression counted in backend + client.getTreatment('hierarchical_splits_test');// impression counted in sdk client.track('sometraffictype', 'someEvent', 10); // trigger both events inmmediatly, before scheduled push of events and impressions, to assert that POST requests are not duplicated triggerPagehideEvent(); diff --git a/src/__tests__/browserSuites/user-consent.spec.js b/src/__tests__/browserSuites/user-consent.spec.js index 7dd3cad..024fcb4 100644 --- a/src/__tests__/browserSuites/user-consent.spec.js +++ b/src/__tests__/browserSuites/user-consent.spec.js @@ -158,7 +158,8 @@ export default function userConsent(fetchMock, t) { await client.ready(); assert.equal(client.track('user', 'event1'), true, 'Events queue is full, but submitter is not executed'); - assert.equal(client.getTreatment('always_on'), 'on', 'Impressions queue is full, but submitter is not executed'); + assert.equal(client.getTreatment('always_on'), 'on', 'Impressions queue is full, but submitter is not executed');// First impression counted in backend + assert.equal(client.getTreatment('always_on'), 'on', 'Impressions queue is full, but submitter is not executed');// impression counted in sdk let submitterCalls = 0; const start = Date.now(); diff --git a/src/__tests__/consumer/browser_consumer.spec.js b/src/__tests__/consumer/browser_consumer.spec.js index b3f206b..3de89e2 100644 --- a/src/__tests__/consumer/browser_consumer.spec.js +++ b/src/__tests__/consumer/browser_consumer.spec.js @@ -26,12 +26,15 @@ const config = { storage: PluggableStorage({ prefix: wrapperPrefix, wrapper: wrapperInstance - }) + }), + sync: { + impressionsMode: 'DEBUG' + }, }; tape('Browser Consumer mode with pluggable storage', function (t) { - t.test('Regular usage', async (assert) => { + t.test('Regular usage - DEBUG strategy', async (assert) => { // Load wrapper with data to do the proper tests await applyOperations(wrapperInstance); diff --git a/src/__tests__/consumer/browser_consumer_partial.spec.js b/src/__tests__/consumer/browser_consumer_partial.spec.js index 4f493c7..81476ff 100644 --- a/src/__tests__/consumer/browser_consumer_partial.spec.js +++ b/src/__tests__/consumer/browser_consumer_partial.spec.js @@ -44,7 +44,7 @@ tape('Browser Consumer Partial mode with pluggable storage', function (t) { * We only validates regular usage. * Corner cases, such as wrapper connection timeout and operation errors, are validated in `browser_consumer.spec.js` */ - t.test('Regular usage', async (assert) => { + t.test('Regular usage - OPTIMIZED strategy', async (assert) => { fetchMock.postOnce(url(config, '/testImpressions/bulk'), (url, req) => { assert.equal(req.headers.SplitSDKImpressionsMode, OPTIMIZED, 'Impressions mode is OPTIMIZED by default'); diff --git a/src/__tests__/testUtils/index.js b/src/__tests__/testUtils/index.js index 302e944..2717982 100644 --- a/src/__tests__/testUtils/index.js +++ b/src/__tests__/testUtils/index.js @@ -43,7 +43,7 @@ export function hasNoCacheHeader(fetchMockOpts) { return fetchMockOpts.headers['Cache-Control'] === 'no-cache'; } -const telemetryEndpointMatcher = /^\/v1\/metrics\/(config|usage)/; +const telemetryEndpointMatcher = /^\/v1\/(metrics|keys)\/(config|usage|ss|cs)/; const eventsEndpointMatcher = /^\/(testImpressions|metrics|events)/; const authEndpointMatcher = /^\/v2\/auth/; const streamingEndpointMatcher = /^\/(sse|event-stream)/; diff --git a/src/platform/getModules.ts b/src/platform/getModules.ts index 8d5416f..90c45e9 100644 --- a/src/platform/getModules.ts +++ b/src/platform/getModules.ts @@ -8,7 +8,6 @@ import { BrowserSignalListener } from '@splitsoftware/splitio-commons/src/listen import { impressionObserverCSFactory } from '@splitsoftware/splitio-commons/src/trackers/impressionObserver/impressionObserverCS'; import { pluggableIntegrationsManagerFactory } from '@splitsoftware/splitio-commons/src/integrations/pluggable'; -import { shouldAddPt } from '@splitsoftware/splitio-commons/src/trackers/impressionObserver/utils'; import { IPlatform, ISdkFactoryParams } from '@splitsoftware/splitio-commons/src/sdkFactory/types'; import { ISettings } from '@splitsoftware/splitio-commons/src/types'; import { CONSUMER_MODE, CONSUMER_PARTIAL_MODE, LOCALHOST_MODE } from '@splitsoftware/splitio-commons/src/utils/constants'; @@ -40,7 +39,7 @@ export function getModules(settings: ISettings, platform: IPlatform): ISdkFactor integrationsManagerFactory: settings.integrations && settings.integrations.length > 0 ? pluggableIntegrationsManagerFactory.bind(null, settings.integrations) : undefined, - impressionsObserverFactory: shouldAddPt(settings) ? impressionObserverCSFactory : undefined, + impressionsObserverFactory: impressionObserverCSFactory, extraProps: (params) => { return { diff --git a/types/splitio.d.ts b/types/splitio.d.ts index d54f534..9c1a89f 100644 --- a/types/splitio.d.ts +++ b/types/splitio.d.ts @@ -809,7 +809,7 @@ declare namespace SplitIO { * ImpressionsMode type * @typedef {string} ImpressionsMode */ - type ImpressionsMode = 'OPTIMIZED' | 'DEBUG'; + type ImpressionsMode = 'OPTIMIZED' | 'DEBUG' | 'NONE'; /** * User consent status. * @typedef {string} ConsentStatus From 004409148dc905f310c7c746f082d47e4010ab39 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Mon, 19 Sep 2022 19:31:43 -0300 Subject: [PATCH 13/23] updated e2e tests for consumer mode with pluggable storage --- .../consumer/browser_consumer.spec.js | 289 ++++++++++++++++++ 1 file changed, 289 insertions(+) diff --git a/src/__tests__/consumer/browser_consumer.spec.js b/src/__tests__/consumer/browser_consumer.spec.js index 3de89e2..a601fb1 100644 --- a/src/__tests__/consumer/browser_consumer.spec.js +++ b/src/__tests__/consumer/browser_consumer.spec.js @@ -2,6 +2,7 @@ import tape from 'tape-catch'; import sinon from 'sinon'; import { inMemoryWrapperFactory } from '@splitsoftware/splitio-commons/src/storages/pluggable/inMemoryWrapper'; import { SDK_NOT_READY, EXCEPTION } from '@splitsoftware/splitio-commons/src/utils/labels'; +import { truncateTimeFrame } from '@splitsoftware/splitio-commons/src/utils/time'; import { applyOperations } from './wrapper-commands'; import { nearlyEqual } from '../testUtils'; import { version } from '../../../package.json'; @@ -15,6 +16,8 @@ const wrapperPrefix = 'PLUGGABLE_STORAGE_UT'; const wrapperInstance = inMemoryWrapperFactory(); const TOTAL_RAW_IMPRESSIONS = 18; const TOTAL_EVENTS = 5; +const DEDUPED_IMPRESSIONS = 2; +const timeFrame = Date.now(); /** @type SplitIO.IBrowserAsyncSettings */ const config = { @@ -177,6 +180,292 @@ tape('Browser Consumer mode with pluggable storage', function (t) { }); }); + t.test('Regular usage - OPTIMIZED strategy', async (assert) => { + const wrapperInstance = inMemoryWrapperFactory(); + // Load wrapper with data to do the proper tests + await applyOperations(wrapperInstance); + + /** @type SplitIO.ImpressionData[] */ + const impressions = []; + const disconnectSpy = sinon.spy(wrapperInstance, 'disconnect'); + + // Overwrite Math.random to track telemetry + const originalMathRandom = Math.random; Math.random = () => 0.5; + const sdk = SplitFactory({ + ...config, + storage: PluggableStorage({ + prefix: wrapperPrefix, + wrapper: wrapperInstance + }), + sync: { + impressionsMode: 'OPTIMIZED' + }, + impressionListener: { + logImpression(data) { impressions.push(data); } + } + }); + Math.random = originalMathRandom; // restore + + const client = sdk.client(); + const otherClient = sdk.client('emi@split.io'); + + /** Evaluation and track methods before SDK_READY */ + + const getTreatmentResult = client.getTreatment('UT_IN_SEGMENT'); + + assert.equal(typeof getTreatmentResult.then, 'function', 'GetTreatment calls should always return a promise on Consumer mode.'); + assert.equal(await getTreatmentResult, 'control', 'Evaluations using pluggable storage should be control if initiated before SDK_READY.'); + assert.equal(client.__getStatus().isReadyFromCache, false, 'SDK in consumer mode is not operational inmediatelly'); + assert.equal(client.__getStatus().isReady, false, 'SDK in consumer mode is not operational inmediatelly'); + + const trackResult = otherClient.track('user', 'test.event', 18); + assert.equal(typeof trackResult.then, 'function', 'Track calls should always return a promise on Consumer mode.'); + assert.true(await trackResult, 'If the wrapper operation success to queue the event, the promise will resolve to true'); + + /** Evaluation and track methods on SDK_READY with OPTIMIZED impressions mode */ + + await client.ready(); + await otherClient.ready(); // waiting to avoid 'control' with label 'sdk not ready' + + assert.equal(await client.getTreatment('UT_IN_SEGMENT'), 'on', '`getTreatment` evaluation using pluggable storage should be correct.'); + assert.equal((await otherClient.getTreatmentWithConfig('UT_IN_SEGMENT')).treatment, 'off', '`getTreatmentWithConfig` evaluation using pluggable storage should be correct.'); + + assert.equal((await client.getTreatments(['UT_NOT_IN_SEGMENT']))['UT_NOT_IN_SEGMENT'], 'off', '`getTreatments` evaluation using pluggable storage should be correct.'); + assert.equal((await otherClient.getTreatmentsWithConfig(['UT_NOT_IN_SEGMENT']))['UT_NOT_IN_SEGMENT'].treatment, 'on', '`getTreatmentsWithConfig` evaluation using pluggable storage should be correct.'); + + client.setAttribute('permissions', ['not_matching']); + assert.equal(await client.getTreatment('UT_SET_MATCHER', { + permissions: ['admin'] + }), 'on', 'Evaluations using pluggable storage should be correct.'); + client.setAttributes({ permissions: ['admin'] }); + assert.equal(await client.getTreatment('UT_SET_MATCHER', { + permissions: ['not_matching'] + }), 'off', 'Evaluations using pluggable storage should be correct.'); + assert.equal(await client.getTreatment('UT_SET_MATCHER'), 'on', 'Evaluations using pluggable storage and attributes binding should be correct.'); + + client.setAttribute('permissions', ['not_matching']); + assert.equal(await client.getTreatment('UT_NOT_SET_MATCHER', { + permissions: ['create'] + }), 'off', 'Evaluations using pluggable storage should be correct.'); + assert.equal(await client.getTreatment('UT_NOT_SET_MATCHER'), 'on', 'Evaluations using pluggable storage should be correct.'); + assert.deepEqual(await client.getTreatmentWithConfig('UT_NOT_SET_MATCHER'), { + treatment: 'on', + config: null + }, 'Evaluations using pluggable storage should be correct, including configs.'); + client.clearAttributes(); + assert.deepEqual(await client.getTreatmentWithConfig('always-o.n-with-config'), { + treatment: 'o.n', + config: '{"color":"brown"}' + }, 'Evaluations using pluggable storage should be correct, including configs.'); + + assert.equal(await client.getTreatment('always-on'), 'on', 'Evaluations using pluggable storage should be correct.'); + + // Below splits were added manually. + // They are all_keys (always evaluate to on) which depend from always-on split. the _on/off is what treatment they are expecting there. + assert.equal(await client.getTreatment('hierarchical_splits_testing_on'), 'on', 'Evaluations using pluggable storage should be correct.'); + assert.equal(await client.getTreatment('hierarchical_splits_testing_off'), 'off', 'Evaluations using pluggable storage should be correct.'); + assert.equal(await client.getTreatment('hierarchical_splits_testing_on_negated'), 'off', 'Evaluations using pluggable storage should be correct.'); + + assert.equal(typeof client.track('user', 'test.event', 18).then, 'function', 'Track calls should always return a promise on Consumer mode.'); + assert.equal(typeof client.track().then, 'function', 'Track calls should always return a promise on Consumer mode, even when parameters are incorrect.'); + + assert.true(await client.track('user', 'test.event', 18), 'If the event was succesfully queued the promise will resolve to true'); + assert.false(await client.track(), 'If the event was NOT succesfully queued the promise will resolve to false'); + + // New shared client created + const newClient = sdk.client('other'); + newClient.track('user', 'test.event', 18).then(result => assert.true(result, 'Track should attempt to track, whether SDK_READY has been emitted or not.')); + newClient.getTreatment('UT_IN_SEGMENT').then(result => assert.equal(result, 'control', '`getTreatment` evaluation is control if shared client is not ready yet.')); + + await newClient.ready(); + assert.true(await newClient.track('user', 'test.event', 18), 'Track should attempt to track, whether SDK_READY has been emitted or not.'); + assert.equal((await newClient.getTreatment('UT_IN_SEGMENT')), 'off', '`getTreatment` evaluation using pluggable storage should be correct.'); + + await client.ready(); // promise already resolved + await newClient.destroy(); + await otherClient.destroy(); + await client.destroy(); + + assert.equal(disconnectSpy.callCount, 1, 'Wrapper disconnect method should be called only once, when the main client is destroyed'); + + // Validate stored impressions and events + const trackedImpressions = await wrapperInstance.popItems('PLUGGABLE_STORAGE_UT.SPLITIO.impressions', await wrapperInstance.getItemsCount('PLUGGABLE_STORAGE_UT.SPLITIO.impressions')); + const trackedEvents = await wrapperInstance.popItems('PLUGGABLE_STORAGE_UT.SPLITIO.events', await wrapperInstance.getItemsCount('PLUGGABLE_STORAGE_UT.SPLITIO.events')); + assert.equal(trackedImpressions.length, TOTAL_RAW_IMPRESSIONS - DEDUPED_IMPRESSIONS, 'Tracked impressions should be present in the external storage'); + assert.equal(trackedEvents.length, TOTAL_EVENTS, 'Tracked events should be present in the external storage'); + + // Validate impression counts + const trackedImpressionCounts = await wrapperInstance.getKeysByPrefix('PLUGGABLE_STORAGE_UT.SPLITIO.impressions.count') + .then(impressionCountsKeys => Promise.all(impressionCountsKeys.map(key => wrapperInstance.get(key).then(count => ([key, count]))))); + const expectedImpressionCount = [ + [`${wrapperPrefix}.SPLITIO.impressions.count::UT_SET_MATCHER::${truncateTimeFrame(timeFrame)}`, '1'], + [`${wrapperPrefix}.SPLITIO.impressions.count::UT_NOT_SET_MATCHER::${truncateTimeFrame(timeFrame)}`, '1'], + ] + assert.deepEqual(trackedImpressionCounts, expectedImpressionCount, 'Impression counts should be present in the external storage'); + + // Assert impressionsListener + setTimeout(() => { + assert.equal(impressions.length, TOTAL_RAW_IMPRESSIONS, 'Each evaluation has its corresponting impression'); + assert.equal(impressions[0].impression.label, SDK_NOT_READY, 'The first impression is control with label "sdk not ready"'); + + assert.end(); + }); + }); + + t.test('Regular usage - NONE strategy', async (assert) => { + const wrapperInstance = inMemoryWrapperFactory(); + // Load wrapper with data to do the proper tests + await applyOperations(wrapperInstance); + + /** @type SplitIO.ImpressionData[] */ + const impressions = []; + const disconnectSpy = sinon.spy(wrapperInstance, 'disconnect'); + + // Overwrite Math.random to not track telemetry + const originalMathRandom = Math.random; Math.random = () => 0.5; + const sdk = SplitFactory({ + ...config, + storage: PluggableStorage({ + prefix: wrapperPrefix, + wrapper: wrapperInstance + }), + sync: { + impressionsMode: 'NONE' + }, + impressionListener: { + logImpression(data) { impressions.push(data); } + } + }); + Math.random = originalMathRandom; // restore + + const client = sdk.client(); + const otherClient = sdk.client('emi@split.io'); + + /** Evaluation and track methods before SDK_READY */ + + const getTreatmentResult = client.getTreatment('UT_IN_SEGMENT'); + + assert.equal(typeof getTreatmentResult.then, 'function', 'GetTreatment calls should always return a promise on Consumer mode.'); + assert.equal(await getTreatmentResult, 'control', 'Evaluations using pluggable storage should be control if initiated before SDK_READY.'); + assert.equal(client.__getStatus().isReadyFromCache, false, 'SDK in consumer mode is not operational inmediatelly'); + assert.equal(client.__getStatus().isReady, false, 'SDK in consumer mode is not operational inmediatelly'); + + const trackResult = otherClient.track('user', 'test.event', 18); + assert.equal(typeof trackResult.then, 'function', 'Track calls should always return a promise on Consumer mode.'); + assert.true(await trackResult, 'If the wrapper operation success to queue the event, the promise will resolve to true'); + + /** Evaluation and track methods on SDK_READY with OPTIMIZED impressions mode */ + + await client.ready(); + await otherClient.ready(); // waiting to avoid 'control' with label 'sdk not ready' + + assert.equal(await client.getTreatment('UT_IN_SEGMENT'), 'on', '`getTreatment` evaluation using pluggable storage should be correct.'); + assert.equal((await otherClient.getTreatmentWithConfig('UT_IN_SEGMENT')).treatment, 'off', '`getTreatmentWithConfig` evaluation using pluggable storage should be correct.'); + + assert.equal((await client.getTreatments(['UT_NOT_IN_SEGMENT']))['UT_NOT_IN_SEGMENT'], 'off', '`getTreatments` evaluation using pluggable storage should be correct.'); + assert.equal((await otherClient.getTreatmentsWithConfig(['UT_NOT_IN_SEGMENT']))['UT_NOT_IN_SEGMENT'].treatment, 'on', '`getTreatmentsWithConfig` evaluation using pluggable storage should be correct.'); + + client.setAttribute('permissions', ['not_matching']); + assert.equal(await client.getTreatment('UT_SET_MATCHER', { + permissions: ['admin'] + }), 'on', 'Evaluations using pluggable storage should be correct.'); + client.setAttributes({ permissions: ['admin'] }); + assert.equal(await client.getTreatment('UT_SET_MATCHER', { + permissions: ['not_matching'] + }), 'off', 'Evaluations using pluggable storage should be correct.'); + assert.equal(await client.getTreatment('UT_SET_MATCHER'), 'on', 'Evaluations using pluggable storage and attributes binding should be correct.'); + + client.setAttribute('permissions', ['not_matching']); + assert.equal(await client.getTreatment('UT_NOT_SET_MATCHER', { + permissions: ['create'] + }), 'off', 'Evaluations using pluggable storage should be correct.'); + assert.equal(await client.getTreatment('UT_NOT_SET_MATCHER'), 'on', 'Evaluations using pluggable storage should be correct.'); + assert.deepEqual(await client.getTreatmentWithConfig('UT_NOT_SET_MATCHER'), { + treatment: 'on', + config: null + }, 'Evaluations using pluggable storage should be correct, including configs.'); + client.clearAttributes(); + assert.deepEqual(await client.getTreatmentWithConfig('always-o.n-with-config'), { + treatment: 'o.n', + config: '{"color":"brown"}' + }, 'Evaluations using pluggable storage should be correct, including configs.'); + + assert.equal(await client.getTreatment('always-on'), 'on', 'Evaluations using pluggable storage should be correct.'); + + // Below splits were added manually. + // They are all_keys (always evaluate to on) which depend from always-on split. the _on/off is what treatment they are expecting there. + assert.equal(await client.getTreatment('hierarchical_splits_testing_on'), 'on', 'Evaluations using pluggable storage should be correct.'); + assert.equal(await client.getTreatment('hierarchical_splits_testing_off'), 'off', 'Evaluations using pluggable storage should be correct.'); + assert.equal(await client.getTreatment('hierarchical_splits_testing_on_negated'), 'off', 'Evaluations using pluggable storage should be correct.'); + + assert.equal(typeof client.track('user', 'test.event', 18).then, 'function', 'Track calls should always return a promise on Consumer mode.'); + assert.equal(typeof client.track().then, 'function', 'Track calls should always return a promise on Consumer mode, even when parameters are incorrect.'); + + assert.true(await client.track('user', 'test.event', 18), 'If the event was succesfully queued the promise will resolve to true'); + assert.false(await client.track(), 'If the event was NOT succesfully queued the promise will resolve to false'); + + // New shared client created + const newClient = sdk.client('other'); + newClient.track('user', 'test.event', 18).then(result => assert.true(result, 'Track should attempt to track, whether SDK_READY has been emitted or not.')); + newClient.getTreatment('UT_IN_SEGMENT').then(result => assert.equal(result, 'control', '`getTreatment` evaluation is control if shared client is not ready yet.')); + + await newClient.ready(); + assert.true(await newClient.track('user', 'test.event', 18), 'Track should attempt to track, whether SDK_READY has been emitted or not.'); + assert.equal((await newClient.getTreatment('UT_IN_SEGMENT')), 'off', '`getTreatment` evaluation using pluggable storage should be correct.'); + + await client.ready(); // promise already resolved + await newClient.destroy(); + await otherClient.destroy(); + await client.destroy(); + + assert.equal(disconnectSpy.callCount, 1, 'Wrapper disconnect method should be called only once, when the main client is destroyed'); + + // Validate stored events and no impressions + const trackedImpressions = await wrapperInstance.popItems('PLUGGABLE_STORAGE_UT.SPLITIO.impressions', await wrapperInstance.getItemsCount('PLUGGABLE_STORAGE_UT.SPLITIO.impressions')); + const trackedEvents = await wrapperInstance.popItems('PLUGGABLE_STORAGE_UT.SPLITIO.events', await wrapperInstance.getItemsCount('PLUGGABLE_STORAGE_UT.SPLITIO.events')); + assert.equal(trackedImpressions.length, 0, 'No impressions are tracked in NONE impressions mode'); + assert.equal(trackedEvents.length, TOTAL_EVENTS, 'Tracked events should be present in the external storage'); + + // Validate impression counts + const trackedImpressionCounts = await wrapperInstance.getKeysByPrefix('PLUGGABLE_STORAGE_UT.SPLITIO.impressions.count') + .then(impressionCountsKeys => Promise.all(impressionCountsKeys.map(key => wrapperInstance.get(key).then(count => ([key, count]))))); + const expectedImpressionCount = [ + [`${wrapperPrefix}.SPLITIO.impressions.count::UT_IN_SEGMENT::${truncateTimeFrame(timeFrame)}`, '1'], + [`${wrapperPrefix}.SPLITIO.impressions.count::UT_NOT_IN_SEGMENT::${truncateTimeFrame(timeFrame)}`, '1'], + [`${wrapperPrefix}.SPLITIO.impressions.count::UT_SET_MATCHER::${truncateTimeFrame(timeFrame)}`, '1'], + [`${wrapperPrefix}.SPLITIO.impressions.count::UT_NOT_SET_MATCHER::${truncateTimeFrame(timeFrame)}`, '1'], + [`${wrapperPrefix}.SPLITIO.impressions.count::always-o.n-with-config::${truncateTimeFrame(timeFrame)}`, '1'], + [`${wrapperPrefix}.SPLITIO.impressions.count::always-on::${truncateTimeFrame(timeFrame)}`, '1'], + [`${wrapperPrefix}.SPLITIO.impressions.count::hierarchical_splits_testing_on::${truncateTimeFrame(timeFrame)}`, '1'], + [`${wrapperPrefix}.SPLITIO.impressions.count::hierarchical_splits_testing_off::${truncateTimeFrame(timeFrame)}`, '1'], + [`${wrapperPrefix}.SPLITIO.impressions.count::hierarchical_splits_testing_on_negated::${truncateTimeFrame(timeFrame)}`, '1'] + ]; + assert.deepEqual(trackedImpressionCounts, expectedImpressionCount, 'Impression counts should be present in the external storage'); + + // Validate unique keys + const trackedUniqueKeys = await wrapperInstance.popItems('PLUGGABLE_STORAGE_UT.SPLITIO.uniquekeys', await wrapperInstance.getItemsCount('PLUGGABLE_STORAGE_UT.SPLITIO.uniquekeys')); + const expectedUniqueKeys = [ + JSON.stringify({ 'f': 'UT_IN_SEGMENT', 'ks': ['UT_Segment_member', 'emi@split.io', 'other'] }), + JSON.stringify({ 'f': 'UT_NOT_IN_SEGMENT', 'ks': ['UT_Segment_member', 'emi@split.io'] }), + JSON.stringify({ 'f': 'UT_SET_MATCHER', 'ks': ['UT_Segment_member'] }), + JSON.stringify({ 'f': 'UT_NOT_SET_MATCHER', 'ks': ['UT_Segment_member'] }), + JSON.stringify({ 'f': 'always-o.n-with-config', 'ks': ['UT_Segment_member'] }), + JSON.stringify({ 'f': 'always-on', 'ks': ['UT_Segment_member'] }), + JSON.stringify({ 'f': 'hierarchical_splits_testing_on', 'ks': ['UT_Segment_member'] }), + JSON.stringify({ 'f': 'hierarchical_splits_testing_off', 'ks': ['UT_Segment_member'] }), + JSON.stringify({ 'f': 'hierarchical_splits_testing_on_negated', 'ks': ['UT_Segment_member'] }), + ]; + assert.deepEqual(trackedUniqueKeys, expectedUniqueKeys); + + // Assert impressionsListener + setTimeout(() => { + assert.equal(impressions.length, TOTAL_RAW_IMPRESSIONS, 'Each evaluation has its corresponting impression'); + assert.equal(impressions[0].impression.label, SDK_NOT_READY, 'The first impression is control with label "sdk not ready"'); + + assert.end(); + }); + }); + t.test('Connection timeout and then ready', assert => { const connDelay = 110; const readyTimeout = 0.1; // 100 millis From 82c20f2cdfb65fe71880ea9d65b103d52c7f4797 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Mon, 19 Sep 2022 19:46:45 -0300 Subject: [PATCH 14/23] updated e2e tests for partial consumer mode with pluggable storage to validate NONE impressions mode --- .../consumer/browser_consumer_partial.spec.js | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/src/__tests__/consumer/browser_consumer_partial.spec.js b/src/__tests__/consumer/browser_consumer_partial.spec.js index 81476ff..5c705ab 100644 --- a/src/__tests__/consumer/browser_consumer_partial.spec.js +++ b/src/__tests__/consumer/browser_consumer_partial.spec.js @@ -194,4 +194,151 @@ tape('Browser Consumer Partial mode with pluggable storage', function (t) { }); }); + t.test('Regular usage - NONE strategy', async (assert) => { + + fetchMock.postOnce(url(config, '/testImpressions/count'), 200); + fetchMock.postOnce(url(config, '/v1/keys/cs'), (url, req) => { + const data = JSON.parse(req.body); + + assert.deepEqual(data, { + keys: [ + { + k: 'UT_Segment_member', + fs: ['UT_IN_SEGMENT', 'UT_NOT_IN_SEGMENT', 'UT_SET_MATCHER', 'UT_NOT_SET_MATCHER', 'always-o.n-with-config', 'always-on', 'hierarchical_splits_testing_on', 'hierarchical_splits_testing_off', 'hierarchical_splits_testing_on_negated'] + }, + { + k: 'emi@split.io', + fs: ['UT_IN_SEGMENT', 'UT_NOT_IN_SEGMENT'] + }, + { + k: 'other', + fs: ['UT_IN_SEGMENT'] + }] + }, 'We performed evaluations for 3 keys, so we should have 3 items total.'); + + return 200; + }); + + fetchMock.postOnce(url(config, '/events/bulk'), (url, req) => { + const resp = JSON.parse(req.body); + assert.equal(resp.length, TOTAL_EVENTS, 'All successfully tracked events were sent'); + return 200; + }); + + // Load wrapper with data to do the proper tests + const wrapperInstance = inMemoryWrapperFactory(); + await applyOperations(wrapperInstance); + + /** @type SplitIO.ImpressionData[] */ + const impressions = []; + const disconnectSpy = sinon.spy(wrapperInstance, 'disconnect'); + + // Overwrite Math.random to NOT track telemetry + const originalMathRandom = Math.random; Math.random = () => 0.5; + const sdk = SplitFactory({ + ...config, + storage: PluggableStorage({ + prefix: wrapperPrefix, + wrapper: wrapperInstance + }), + sync: { + impressionsMode: 'NONE' + }, + impressionListener: { + logImpression(data) { impressions.push(data); } + } + }); + Math.random = originalMathRandom; // restore + + const client = sdk.client(); + const otherClient = sdk.client('emi@split.io'); + + /** Evaluation, track and manager methods before SDK_READY */ + + const getTreatmentResult = client.getTreatment('UT_IN_SEGMENT'); + + assert.equal(typeof getTreatmentResult.then, 'function', 'GetTreatment calls should always return a promise on Consumer mode.'); + assert.equal(await getTreatmentResult, 'control', 'Evaluations using pluggable storage should be control if initiated before SDK_READY.'); + assert.equal(client.__getStatus().isReadyFromCache, false, 'SDK in consumer mode is not operational inmediatelly'); + assert.equal(client.__getStatus().isReady, false, 'SDK in consumer mode is not operational inmediatelly'); + + const trackResult = otherClient.track('user', 'test.event', 18); + assert.equal(typeof trackResult.then, 'function', 'Track calls should always return a promise on Consumer mode.'); + assert.true(await trackResult, 'If the wrapper operation success to queue the event, the promise will resolve to true'); + + /** Evaluation, track and manager methods on SDK_READY */ + + await client.ready(); + await otherClient.ready(); // waiting to avoid 'control' with label 'sdk not ready' + + assert.equal(await client.getTreatment('UT_IN_SEGMENT'), 'on', '`getTreatment` evaluation using pluggable storage should be correct.'); + assert.equal((await otherClient.getTreatmentWithConfig('UT_IN_SEGMENT')).treatment, 'off', '`getTreatmentWithConfig` evaluation using pluggable storage should be correct.'); + + assert.equal((await client.getTreatments(['UT_NOT_IN_SEGMENT']))['UT_NOT_IN_SEGMENT'], 'off', '`getTreatments` evaluation using pluggable storage should be correct.'); + assert.equal((await otherClient.getTreatmentsWithConfig(['UT_NOT_IN_SEGMENT']))['UT_NOT_IN_SEGMENT'].treatment, 'on', '`getTreatmentsWithConfig` evaluation using pluggable storage should be correct.'); + + assert.equal(await client.getTreatment('UT_SET_MATCHER', { + permissions: ['admin'] + }), 'on', 'Evaluations using pluggable storage should be correct.'); + assert.equal(await client.getTreatment('UT_SET_MATCHER', { + permissions: ['not_matching'] + }), 'off', 'Evaluations using pluggable storage should be correct.'); + + assert.equal(await client.getTreatment('UT_NOT_SET_MATCHER', { + permissions: ['create'] + }), 'off', 'Evaluations using pluggable storage should be correct.'); + assert.equal(await client.getTreatment('UT_NOT_SET_MATCHER', { + permissions: ['not_matching'] + }), 'on', 'Evaluations using pluggable storage should be correct.'); + assert.deepEqual(await client.getTreatmentWithConfig('UT_NOT_SET_MATCHER', { + permissions: ['not_matching'] + }), { + treatment: 'on', + config: null + }, 'Evaluations using pluggable storage should be correct, including configs.'); + assert.deepEqual(await client.getTreatmentWithConfig('always-o.n-with-config'), { + treatment: 'o.n', + config: '{"color":"brown"}' + }, 'Evaluations using pluggable storage should be correct, including configs.'); + + assert.equal(await client.getTreatment('always-on'), 'on', 'Evaluations using pluggable storage should be correct.'); + + // Below splits were added manually. + // They are all_keys (always evaluate to on) which depend from always-on split. the _on/off is what treatment they are expecting there. + assert.equal(await client.getTreatment('hierarchical_splits_testing_on'), 'on', 'Evaluations using pluggable storage should be correct.'); + assert.equal(await client.getTreatment('hierarchical_splits_testing_off'), 'off', 'Evaluations using pluggable storage should be correct.'); + assert.equal(await client.getTreatment('hierarchical_splits_testing_on_negated'), 'off', 'Evaluations using pluggable storage should be correct.'); + + assert.equal(typeof client.track('user', 'test.event', 18).then, 'function', 'Track calls should always return a promise on Consumer mode.'); + assert.equal(typeof client.track().then, 'function', 'Track calls should always return a promise on Consumer mode, even when parameters are incorrect.'); + + assert.true(await client.track('user', 'test.event', 18), 'If the event was succesfully queued the promise will resolve to true'); + assert.false(await client.track(), 'If the event was NOT succesfully queued the promise will resolve to false'); + + // New shared client created + const newClient = sdk.client('other'); + newClient.track('user', 'test.event', 18).then(result => assert.true(result, 'Track should attempt to track, whether SDK_READY has been emitted or not.')); + newClient.getTreatment('UT_IN_SEGMENT').then(result => assert.equal(result, 'control', '`getTreatment` evaluation is control if shared client is not ready yet.')); + + await newClient.ready(); + assert.true(await newClient.track('user', 'test.event', 18), 'Track should attempt to track, whether SDK_READY has been emitted or not.'); + assert.equal((await newClient.getTreatment('UT_IN_SEGMENT')), 'off', '`getTreatment` evaluation using pluggable storage should be correct.'); + + await client.ready(); // promise already resolved + await newClient.destroy(); + await otherClient.destroy(); + + await client.destroy(); + + assert.equal(disconnectSpy.callCount, 1, 'Wrapper disconnect method should be called only once, when the main client is destroyed'); + + // Assert impressionsListener + setTimeout(() => { + assert.equal(impressions.length, TOTAL_RAW_IMPRESSIONS, 'Each evaluation has its corresponting impression'); + assert.equal(impressions[0].impression.label, SDK_NOT_READY, 'The first impression is control with label "sdk not ready"'); + + assert.end(); + }); + }); + }); From 8c24dafc529ed9fce8924a86ed886ce4ac8efdab Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Mon, 19 Sep 2022 19:53:38 -0300 Subject: [PATCH 15/23] rc --- .github/workflows/ci-cd.yml | 4 ++-- package-lock.json | 8 ++++---- package.json | 4 ++-- src/__tests__/consumer/browser_consumer.spec.js | 2 +- src/settings/defaults.ts | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 86739af..1cb610c 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -42,14 +42,14 @@ jobs: run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") BUILD_COMMIT=${{ github.sha }} npm run build - name: Configure AWS credentials (development) - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/pluggable_storage_mtk_producer_api' }} uses: aws-actions/configure-aws-credentials@v1 with: role-to-assume: arn:aws:iam::079419646996:role/public-assets aws-region: us-east-1 - name: Upload to S3 (development) - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/pluggable_storage_mtk_producer_api' }} run: aws s3 sync $SOURCE_DIR s3://$BUCKET/$DEST_DIR $ARGS env: BUCKET: split-public-stage diff --git a/package-lock.json b/package-lock.json index 742795d..32c273a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-browserjs", - "version": "0.8.0", + "version": "0.8.1-rc.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2194,9 +2194,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "1.6.2-rc.9", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.6.2-rc.9.tgz", - "integrity": "sha512-pUTAuhZlkTBgs5nGu5in4jDdlvj0yPRdnqXWUjNml4+GmRuUx827R8FL07jFHV2m88K9BbqZfpztsgbis5hRHQ==", + "version": "1.6.2-rc.10", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.6.2-rc.10.tgz", + "integrity": "sha512-Z6zNqaBO9XraodPdaRw7+fIx0ngh2Fs9slhnN/eFgeX91im649trhS/jW3542ik0vggVUEG6SN38g8o7dChuhg==", "requires": { "tslib": "^2.3.1" } diff --git a/package.json b/package.json index a35a08c..c1cfbe8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-browserjs", - "version": "0.8.0", + "version": "0.8.1-rc.1", "description": "Split SDK for Javascript on Browser", "main": "cjs/index.js", "module": "esm/index.js", @@ -63,7 +63,7 @@ "bugs": "https://github.com/splitio/javascript-browser-client/issues", "homepage": "https://github.com/splitio/javascript-browser-client#readme", "dependencies": { - "@splitsoftware/splitio-commons": "1.6.2-rc.9", + "@splitsoftware/splitio-commons": "1.6.2-rc.10", "@types/google.analytics": "0.0.40" }, "devDependencies": { diff --git a/src/__tests__/consumer/browser_consumer.spec.js b/src/__tests__/consumer/browser_consumer.spec.js index a601fb1..c2685f6 100644 --- a/src/__tests__/consumer/browser_consumer.spec.js +++ b/src/__tests__/consumer/browser_consumer.spec.js @@ -300,7 +300,7 @@ tape('Browser Consumer mode with pluggable storage', function (t) { const expectedImpressionCount = [ [`${wrapperPrefix}.SPLITIO.impressions.count::UT_SET_MATCHER::${truncateTimeFrame(timeFrame)}`, '1'], [`${wrapperPrefix}.SPLITIO.impressions.count::UT_NOT_SET_MATCHER::${truncateTimeFrame(timeFrame)}`, '1'], - ] + ]; assert.deepEqual(trackedImpressionCounts, expectedImpressionCount, 'Impression counts should be present in the external storage'); // Assert impressionsListener diff --git a/src/settings/defaults.ts b/src/settings/defaults.ts index 5a9b687..9f52a0b 100644 --- a/src/settings/defaults.ts +++ b/src/settings/defaults.ts @@ -2,7 +2,7 @@ import { LogLevels, isLogLevelString } from '@splitsoftware/splitio-commons/src/ import { ConsentStatus, LogLevel } from '@splitsoftware/splitio-commons/src/types'; import { CONSENT_GRANTED } from '@splitsoftware/splitio-commons/src/utils/constants'; -const packageVersion = '0.8.0'; +const packageVersion = '0.8.1-rc.1'; /** * In browser, the default debug level, can be set via the `localStorage.splitio_debug` item. From 8f75cc457b84734025224e38a3e83422333f55c7 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 27 Sep 2022 22:38:35 -0300 Subject: [PATCH 16/23] rc --- package-lock.json | 8 ++++---- package.json | 5 +++-- src/settings/defaults.ts | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 32c273a..973a2f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-browserjs", - "version": "0.8.1-rc.1", + "version": "0.8.1-rc.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2194,9 +2194,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "1.6.2-rc.10", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.6.2-rc.10.tgz", - "integrity": "sha512-Z6zNqaBO9XraodPdaRw7+fIx0ngh2Fs9slhnN/eFgeX91im649trhS/jW3542ik0vggVUEG6SN38g8o7dChuhg==", + "version": "1.6.2-rc.13", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.6.2-rc.13.tgz", + "integrity": "sha512-QwK7EaBCp+r0/Bizk/yvNJXUkIrY5Du3EJVkg6C/yXN7FmgZqBXXjSp2EoP/YGMh2q6SWWv7L5Gfxb6d0TuGSg==", "requires": { "tslib": "^2.3.1" } diff --git a/package.json b/package.json index c1cfbe8..8c550ef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-browserjs", - "version": "0.8.1-rc.1", + "version": "0.8.1-rc.2", "description": "Split SDK for Javascript on Browser", "main": "cjs/index.js", "module": "esm/index.js", @@ -42,6 +42,7 @@ "pretest-ts-decls": "npm run build:esm && npm run build:cjs && npm link", "test-ts-decls": "./scripts/ts-tests.sh", "posttest-ts-decls": "npm unlink && npm install", + "all": "npm run check && npm run build && npm run test-ts-decls && npm run test", "publish:rc": "npm run check && npm run build && npm publish --tag rc", "publish:stable": "npm run check && npm run build && npm publish" }, @@ -63,7 +64,7 @@ "bugs": "https://github.com/splitio/javascript-browser-client/issues", "homepage": "https://github.com/splitio/javascript-browser-client#readme", "dependencies": { - "@splitsoftware/splitio-commons": "1.6.2-rc.10", + "@splitsoftware/splitio-commons": "1.6.2-rc.13", "@types/google.analytics": "0.0.40" }, "devDependencies": { diff --git a/src/settings/defaults.ts b/src/settings/defaults.ts index 9f52a0b..94a343b 100644 --- a/src/settings/defaults.ts +++ b/src/settings/defaults.ts @@ -2,7 +2,7 @@ import { LogLevels, isLogLevelString } from '@splitsoftware/splitio-commons/src/ import { ConsentStatus, LogLevel } from '@splitsoftware/splitio-commons/src/types'; import { CONSENT_GRANTED } from '@splitsoftware/splitio-commons/src/utils/constants'; -const packageVersion = '0.8.1-rc.1'; +const packageVersion = '0.8.1-rc.2'; /** * In browser, the default debug level, can be set via the `localStorage.splitio_debug` item. From dd52383ae54fc9248892d1d0e6088da375f7406e Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 29 Sep 2022 17:14:08 -0300 Subject: [PATCH 17/23] upgrade js-commons and prepare rc --- .eslintrc | 3 ++- package-lock.json | 8 ++++---- package.json | 4 ++-- src/settings/defaults.ts | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.eslintrc b/.eslintrc index dabb965..9954be9 100644 --- a/.eslintrc +++ b/.eslintrc @@ -30,7 +30,8 @@ "no-unused-vars": "off", "@typescript-eslint/no-unused-vars": "error", "keyword-spacing": "error", - "comma-style": "error" + "comma-style": "error", + "no-trailing-spaces": "error" }, "overrides": [ diff --git a/package-lock.json b/package-lock.json index 973a2f0..78a359a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-browserjs", - "version": "0.8.1-rc.2", + "version": "0.8.1-rc.3", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2194,9 +2194,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "1.6.2-rc.13", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.6.2-rc.13.tgz", - "integrity": "sha512-QwK7EaBCp+r0/Bizk/yvNJXUkIrY5Du3EJVkg6C/yXN7FmgZqBXXjSp2EoP/YGMh2q6SWWv7L5Gfxb6d0TuGSg==", + "version": "1.6.2-rc.14", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.6.2-rc.14.tgz", + "integrity": "sha512-cslzWAu0ony85y0SUcXa3vRhES3pwYDROuke79IjyH0UDunr30kmPwXRWONFS+t4KU+9N4ABNNOKgrX/B5sv9Q==", "requires": { "tslib": "^2.3.1" } diff --git a/package.json b/package.json index 8c550ef..a533f74 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-browserjs", - "version": "0.8.1-rc.2", + "version": "0.8.1-rc.3", "description": "Split SDK for Javascript on Browser", "main": "cjs/index.js", "module": "esm/index.js", @@ -64,7 +64,7 @@ "bugs": "https://github.com/splitio/javascript-browser-client/issues", "homepage": "https://github.com/splitio/javascript-browser-client#readme", "dependencies": { - "@splitsoftware/splitio-commons": "1.6.2-rc.13", + "@splitsoftware/splitio-commons": "1.6.2-rc.14", "@types/google.analytics": "0.0.40" }, "devDependencies": { diff --git a/src/settings/defaults.ts b/src/settings/defaults.ts index 94a343b..13e5bcb 100644 --- a/src/settings/defaults.ts +++ b/src/settings/defaults.ts @@ -2,7 +2,7 @@ import { LogLevels, isLogLevelString } from '@splitsoftware/splitio-commons/src/ import { ConsentStatus, LogLevel } from '@splitsoftware/splitio-commons/src/types'; import { CONSENT_GRANTED } from '@splitsoftware/splitio-commons/src/utils/constants'; -const packageVersion = '0.8.1-rc.2'; +const packageVersion = '0.8.1-rc.3'; /** * In browser, the default debug level, can be set via the `localStorage.splitio_debug` item. From fd9caedbf8dbd9c8684da68fa5a5c4759a4eb6fd Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 29 Sep 2022 18:55:23 -0300 Subject: [PATCH 18/23] fix e2e test --- src/__tests__/consumer/browser_consumer.spec.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/__tests__/consumer/browser_consumer.spec.js b/src/__tests__/consumer/browser_consumer.spec.js index c2685f6..1144853 100644 --- a/src/__tests__/consumer/browser_consumer.spec.js +++ b/src/__tests__/consumer/browser_consumer.spec.js @@ -430,10 +430,10 @@ tape('Browser Consumer mode with pluggable storage', function (t) { const trackedImpressionCounts = await wrapperInstance.getKeysByPrefix('PLUGGABLE_STORAGE_UT.SPLITIO.impressions.count') .then(impressionCountsKeys => Promise.all(impressionCountsKeys.map(key => wrapperInstance.get(key).then(count => ([key, count]))))); const expectedImpressionCount = [ - [`${wrapperPrefix}.SPLITIO.impressions.count::UT_IN_SEGMENT::${truncateTimeFrame(timeFrame)}`, '1'], - [`${wrapperPrefix}.SPLITIO.impressions.count::UT_NOT_IN_SEGMENT::${truncateTimeFrame(timeFrame)}`, '1'], - [`${wrapperPrefix}.SPLITIO.impressions.count::UT_SET_MATCHER::${truncateTimeFrame(timeFrame)}`, '1'], - [`${wrapperPrefix}.SPLITIO.impressions.count::UT_NOT_SET_MATCHER::${truncateTimeFrame(timeFrame)}`, '1'], + [`${wrapperPrefix}.SPLITIO.impressions.count::UT_IN_SEGMENT::${truncateTimeFrame(timeFrame)}`, '5'], + [`${wrapperPrefix}.SPLITIO.impressions.count::UT_NOT_IN_SEGMENT::${truncateTimeFrame(timeFrame)}`, '2'], + [`${wrapperPrefix}.SPLITIO.impressions.count::UT_SET_MATCHER::${truncateTimeFrame(timeFrame)}`, '3'], + [`${wrapperPrefix}.SPLITIO.impressions.count::UT_NOT_SET_MATCHER::${truncateTimeFrame(timeFrame)}`, '3'], [`${wrapperPrefix}.SPLITIO.impressions.count::always-o.n-with-config::${truncateTimeFrame(timeFrame)}`, '1'], [`${wrapperPrefix}.SPLITIO.impressions.count::always-on::${truncateTimeFrame(timeFrame)}`, '1'], [`${wrapperPrefix}.SPLITIO.impressions.count::hierarchical_splits_testing_on::${truncateTimeFrame(timeFrame)}`, '1'], From 6acac871f6c9b690fe10db813a55426344901f39 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 30 Sep 2022 14:56:52 -0300 Subject: [PATCH 19/23] update type definitions comment regarding new NONE impression mode option --- .github/workflows/ci-cd.yml | 4 ++-- types/splitio.d.ts | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 1cb610c..86739af 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -42,14 +42,14 @@ jobs: run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") BUILD_COMMIT=${{ github.sha }} npm run build - name: Configure AWS credentials (development) - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/pluggable_storage_mtk_producer_api' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} uses: aws-actions/configure-aws-credentials@v1 with: role-to-assume: arn:aws:iam::079419646996:role/public-assets aws-region: us-east-1 - name: Upload to S3 (development) - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/pluggable_storage_mtk_producer_api' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} run: aws s3 sync $SOURCE_DIR s3://$BUCKET/$DEST_DIR $ARGS env: BUCKET: split-public-stage diff --git a/types/splitio.d.ts b/types/splitio.d.ts index 9c1a89f..87ab9e0 100644 --- a/types/splitio.d.ts +++ b/types/splitio.d.ts @@ -217,9 +217,11 @@ interface ISharedSettings { splitFilters?: SplitIO.SplitFilter[] /** * Impressions Collection Mode. Option to determine how impressions are going to be sent to Split Servers. - * Possible values are 'DEBUG' and 'OPTIMIZED'. + * Possible values are 'DEBUG', 'OPTIMIZED', and 'NONE'. * - DEBUG: will send all the impressions generated (recommended only for debugging purposes). - * - OPTIMIZED: will send unique impressions to Split Servers avoiding a considerable amount of traffic that duplicated impressions could generate. + * - OPTIMIZED: will send unique impressions to Split Servers, avoiding a considerable amount of traffic that duplicated impressions could generate. + * - NONE: will send unique keys evaluated per feature to Split Servers, avoiding a considerable amount of traffic that impressions could generate. + * * @property {String} impressionsMode * @default 'OPTIMIZED' */ From 8253d0d814be6faacba3a261bc9d792a6c80c58b Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 4 Oct 2022 19:59:06 -0300 Subject: [PATCH 20/23] update changelog and js-commons version for stable release --- CHANGES.txt | 5 +++-- package-lock.json | 8 ++++---- package.json | 4 ++-- src/settings/defaults.ts | 2 +- types/splitio.d.ts | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 213a27b..d35c78b 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,6 @@ -0.8.1 (September XXX, 2022) -- Updated @splitsoftware/splitio-commons package to version 1.6.2, that improves the performance of split evaluations (i.e., `getTreatment(s)` method calls) when using the default storage in memory. +0.9.0 (October 5, 2022) +- Added a new impressions mode for the SDK called NONE, to be used in factory when there is no desire to capture impressions on an SDK factory to feed Split's analytics engine. Running NONE mode, the SDK will only capture unique keys evaluated for a particular feature flag instead of full blown impressions. +- Updated @splitsoftware/splitio-commons package to version 1.7.0, that improves the performance of split evaluations (i.e., `getTreatment(s)` method calls) when using the default storage in memory, among other improvements. 0.8.0 (July 22, 2022) - Added `autoRequire` configuration option to the Google Analytics to Split integration, which takes care of requiring the splitTracker plugin on trackers dynamically created by Google tag managers (See https://help.split.io/hc/en-us/articles/360040838752#set-up-with-gtm-and-gtag.js). diff --git a/package-lock.json b/package-lock.json index 78a359a..3838356 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-browserjs", - "version": "0.8.1-rc.3", + "version": "0.9.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2194,9 +2194,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "1.6.2-rc.14", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.6.2-rc.14.tgz", - "integrity": "sha512-cslzWAu0ony85y0SUcXa3vRhES3pwYDROuke79IjyH0UDunr30kmPwXRWONFS+t4KU+9N4ABNNOKgrX/B5sv9Q==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.7.0.tgz", + "integrity": "sha512-QjDcSV2mbwkhMkA9zutmdU4NwY/Hb09EZeXFCmRxWHHYLegl6XWztbghqD6fw3Q5yb7jsQ+wn7nMEZsvNKum7g==", "requires": { "tslib": "^2.3.1" } diff --git a/package.json b/package.json index a533f74..e85665d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-browserjs", - "version": "0.8.1-rc.3", + "version": "0.9.0", "description": "Split SDK for Javascript on Browser", "main": "cjs/index.js", "module": "esm/index.js", @@ -64,7 +64,7 @@ "bugs": "https://github.com/splitio/javascript-browser-client/issues", "homepage": "https://github.com/splitio/javascript-browser-client#readme", "dependencies": { - "@splitsoftware/splitio-commons": "1.6.2-rc.14", + "@splitsoftware/splitio-commons": "1.7.0", "@types/google.analytics": "0.0.40" }, "devDependencies": { diff --git a/src/settings/defaults.ts b/src/settings/defaults.ts index 13e5bcb..60aaad6 100644 --- a/src/settings/defaults.ts +++ b/src/settings/defaults.ts @@ -2,7 +2,7 @@ import { LogLevels, isLogLevelString } from '@splitsoftware/splitio-commons/src/ import { ConsentStatus, LogLevel } from '@splitsoftware/splitio-commons/src/types'; import { CONSENT_GRANTED } from '@splitsoftware/splitio-commons/src/utils/constants'; -const packageVersion = '0.8.1-rc.3'; +const packageVersion = '0.9.0'; /** * In browser, the default debug level, can be set via the `localStorage.splitio_debug` item. diff --git a/types/splitio.d.ts b/types/splitio.d.ts index 87ab9e0..a1e9d14 100644 --- a/types/splitio.d.ts +++ b/types/splitio.d.ts @@ -220,7 +220,7 @@ interface ISharedSettings { * Possible values are 'DEBUG', 'OPTIMIZED', and 'NONE'. * - DEBUG: will send all the impressions generated (recommended only for debugging purposes). * - OPTIMIZED: will send unique impressions to Split Servers, avoiding a considerable amount of traffic that duplicated impressions could generate. - * - NONE: will send unique keys evaluated per feature to Split Servers, avoiding a considerable amount of traffic that impressions could generate. + * - NONE: will send unique keys evaluated per feature to Split Servers instead of full blown impressions, avoiding a considerable amount of traffic that impressions could generate. * * @property {String} impressionsMode * @default 'OPTIMIZED' From f6baed6e6414dd91cf808eeae50bbdcc02892cf7 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 5 Oct 2022 12:26:09 -0300 Subject: [PATCH 21/23] prepare release v0.9.0 --- CHANGES.txt | 3 ++- package-lock.json | 6 +++--- package.json | 2 +- types/splitio.d.ts | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index d35c78b..55c830a 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,6 +1,7 @@ 0.9.0 (October 5, 2022) - Added a new impressions mode for the SDK called NONE, to be used in factory when there is no desire to capture impressions on an SDK factory to feed Split's analytics engine. Running NONE mode, the SDK will only capture unique keys evaluated for a particular feature flag instead of full blown impressions. -- Updated @splitsoftware/splitio-commons package to version 1.7.0, that improves the performance of split evaluations (i.e., `getTreatment(s)` method calls) when using the default storage in memory, among other improvements. +- Updated default value of `scheduler.featuresRefreshRate` config parameter from 30 seconds to 60 seconds. +- Updated @splitsoftware/splitio-commons package to version 1.7.1, that improves the performance of split evaluations (i.e., `getTreatment(s)` method calls) when using the default storage in memory, among other improvements. 0.8.0 (July 22, 2022) - Added `autoRequire` configuration option to the Google Analytics to Split integration, which takes care of requiring the splitTracker plugin on trackers dynamically created by Google tag managers (See https://help.split.io/hc/en-us/articles/360040838752#set-up-with-gtm-and-gtag.js). diff --git a/package-lock.json b/package-lock.json index 3838356..1c98851 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2194,9 +2194,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.7.0.tgz", - "integrity": "sha512-QjDcSV2mbwkhMkA9zutmdU4NwY/Hb09EZeXFCmRxWHHYLegl6XWztbghqD6fw3Q5yb7jsQ+wn7nMEZsvNKum7g==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.7.1.tgz", + "integrity": "sha512-kiHHH8oRx7HKx2cJko11kfEXIvLbPUdlJp6yqNC7wWspUCGhPmarm7qrTD3lsene3j0dJ2fpfEc19ElulxtMkQ==", "requires": { "tslib": "^2.3.1" } diff --git a/package.json b/package.json index e85665d..1568e7e 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "bugs": "https://github.com/splitio/javascript-browser-client/issues", "homepage": "https://github.com/splitio/javascript-browser-client#readme", "dependencies": { - "@splitsoftware/splitio-commons": "1.7.0", + "@splitsoftware/splitio-commons": "1.7.1", "@types/google.analytics": "0.0.40" }, "devDependencies": { diff --git a/types/splitio.d.ts b/types/splitio.d.ts index a1e9d14..9a4d665 100644 --- a/types/splitio.d.ts +++ b/types/splitio.d.ts @@ -957,7 +957,7 @@ declare namespace SplitIO { /** * The SDK polls Split servers for changes to feature roll-out plans. This parameter controls this polling period in seconds. * @property {number} featuresRefreshRate - * @default 30 + * @default 60 */ featuresRefreshRate?: number, /** From ca9bb827049ff22518302a57ab4ecb1798ae8419 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 5 Oct 2022 13:38:00 -0300 Subject: [PATCH 22/23] re-run ci-cd workflow From 4b85710c15bd6a36d34283cbbf5c20c6504a2fca Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 5 Oct 2022 14:38:28 -0300 Subject: [PATCH 23/23] update test to reduce flakiness --- .../browserSuites/ready-from-cache.spec.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/__tests__/browserSuites/ready-from-cache.spec.js b/src/__tests__/browserSuites/ready-from-cache.spec.js index 8997e00..38aceae 100644 --- a/src/__tests__/browserSuites/ready-from-cache.spec.js +++ b/src/__tests__/browserSuites/ready-from-cache.spec.js @@ -503,7 +503,7 @@ export default function (fetchMock, assert) { }); client.once(client.Event.SDK_READY, () => { - t.deepEqual(manager.names(), ['p1__split', 'p2__split'], 'p1__split should be added for evaluation'); + t.deepEqual(manager.names().sort(), ['p1__split', 'p2__split'], 'p1__split should be added for evaluation'); client.destroy().then(() => { t.equal(localStorage.getItem('some_user_item'), 'user_item', 'user items at localStorage must not be changed'); @@ -547,7 +547,7 @@ export default function (fetchMock, assert) { }); client.once(client.Event.SDK_READY, () => { - t.deepEqual(manager.names(), ['p1__split', 'p2__split'], 'p1__split should be added for evaluation'); + t.deepEqual(manager.names().sort(), ['p1__split', 'p2__split'], 'p1__split should be added for evaluation'); client.destroy().then(() => { t.equal(localStorage.getItem('readyFromCache_5B.SPLITIO.splits.till'), '1457552620999', 'splits.till must correspond to the till of the last successfully fetched Splits'); @@ -591,11 +591,11 @@ export default function (fetchMock, assert) { const manager = splitio.manager(); client.once(client.Event.SDK_READY_FROM_CACHE, () => { - t.deepEqual(manager.names(), ['p2__split', 'p1__split'], 'splits shouldn\'t be removed for evaluation'); + t.deepEqual(manager.names().sort(), ['p1__split', 'p2__split'], 'splits shouldn\'t be removed for evaluation'); }); client.once(client.Event.SDK_READY, () => { - t.deepEqual(manager.names(), ['p2__split', 'p1__split'], 'active splits should be present for evaluation'); + t.deepEqual(manager.names().sort(), ['p1__split', 'p2__split'], 'active splits should be present for evaluation'); client.destroy().then(() => { t.equal(localStorage.getItem('some_user_item'), 'user_item', 'user items at localStorage must not be changed'); @@ -646,7 +646,7 @@ export default function (fetchMock, assert) { }); client.once(client.Event.SDK_READY, () => { - t.deepEqual(manager.names(), ['p2__split', 'p1__split'], 'active splits should be present for evaluation'); + t.deepEqual(manager.names().sort(), ['p1__split', 'p2__split'], 'active splits should be present for evaluation'); client.destroy().then(() => { t.equal(localStorage.getItem('some_user_item'), 'user_item', 'user items at localStorage must not be changed'); @@ -708,7 +708,7 @@ export default function (fetchMock, assert) { }); client.once(client.Event.SDK_READY, () => { - t.deepEqual(manager.names(), ['p1__split', 'p2__split', 'p3__split'], 'active splits should be present for evaluation'); + t.deepEqual(manager.names().sort(), ['p1__split', 'p2__split', 'p3__split'], 'active splits should be present for evaluation'); client.destroy().then(() => { t.equal(localStorage.getItem('some_user_item'), 'user_item', 'user items at localStorage must not be changed'); @@ -761,7 +761,7 @@ export default function (fetchMock, assert) { }); client.once(client.Event.SDK_READY, () => { - t.deepEqual(manager.names(), ['p3__split', 'p2__split'], 'active splits should be present for evaluation'); + t.deepEqual(manager.names().sort(), ['p2__split', 'p3__split'], 'active splits should be present for evaluation'); client.destroy().then(() => { t.equal(localStorage.getItem('some_user_item'), 'user_item', 'user items at localStorage must not be changed');