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__/online/evaluations.spec.js b/src/__tests__/browserSuites/evaluations.spec.js similarity index 99% rename from src/__tests__/online/evaluations.spec.js rename to src/__tests__/browserSuites/evaluations.spec.js index c084dc9..cc8bee2 100644 --- a/src/__tests__/online/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; @@ -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__/online/events.spec.js b/src/__tests__/browserSuites/events.spec.js similarity index 98% rename from src/__tests__/online/events.spec.js rename to src/__tests__/browserSuites/events.spec.js index e98c7cb..a33dd79 100644 --- a/src/__tests__/online/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' }, @@ -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__/online/fetch-specific-splits.spec.js b/src/__tests__/browserSuites/fetch-specific-splits.spec.js similarity index 97% rename from src/__tests__/online/fetch-specific-splits.spec.js rename to src/__tests__/browserSuites/fetch-specific-splits.spec.js index ffed3cc..14dc031 100644 --- a/src/__tests__/online/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__/online/ignore-ip-addresses-setting.spec.js b/src/__tests__/browserSuites/ignore-ip-addresses-setting.spec.js similarity index 96% rename from src/__tests__/online/ignore-ip-addresses-setting.spec.js rename to src/__tests__/browserSuites/ignore-ip-addresses-setting.spec.js index 4503d82..6266976 100644 --- a/src/__tests__/online/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__/online/impressions-listener.spec.js b/src/__tests__/browserSuites/impressions-listener.spec.js similarity index 95% rename from src/__tests__/online/impressions-listener.spec.js rename to src/__tests__/browserSuites/impressions-listener.spec.js index a48b75b..de6c41e 100644 --- a/src/__tests__/online/impressions-listener.spec.js +++ b/src/__tests__/browserSuites/impressions-listener.spec.js @@ -1,8 +1,9 @@ import sinon from 'sinon'; -import { SplitFactory } from '../../index'; -import { settingsValidator } from '../../settings'; -const settings = settingsValidator({ +import { SplitFactory } from '../../'; +import { settingsFactory } from '../../settings'; + +const settings = settingsFactory({ core: { key: '' }, diff --git a/src/__tests__/online/impressions.debug.spec.js b/src/__tests__/browserSuites/impressions.debug.spec.js similarity index 96% rename from src/__tests__/online/impressions.debug.spec.js rename to src/__tests__/browserSuites/impressions.debug.spec.js index ba8fa8a..bbccfc9 100644 --- a/src/__tests__/online/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__/online/impressions.spec.js b/src/__tests__/browserSuites/impressions.spec.js similarity index 97% rename from src/__tests__/online/impressions.spec.js rename to src/__tests__/browserSuites/impressions.spec.js index 1f2f71d..8e73c5d 100644 --- a/src/__tests__/online/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__/online/manager.spec.js b/src/__tests__/browserSuites/manager.spec.js similarity index 98% rename from src/__tests__/online/manager.spec.js rename to src/__tests__/browserSuites/manager.spec.js index a530dd8..ce13cd3 100644 --- a/src/__tests__/online/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__/push/push-corner-cases.spec.js b/src/__tests__/browserSuites/push-corner-cases.spec.js similarity index 96% rename from src/__tests__/push/push-corner-cases.spec.js rename to src/__tests__/browserSuites/push-corner-cases.spec.js index 25f38e7..0b659c6 100644 --- a/src/__tests__/push/push-corner-cases.spec.js +++ b/src/__tests__/browserSuites/push-corner-cases.spec.js @@ -8,7 +8,7 @@ import EventSourceMock, { setMockListener } from '../testUtils/eventSourceMock'; window.EventSource = EventSourceMock; import { SplitFactory, InLocalStorage } from '../../'; -import { settingsValidator } from '../../settings'; +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; @@ -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__/push/push-fallbacking.spec.js b/src/__tests__/browserSuites/push-fallbacking.spec.js similarity index 77% rename from src/__tests__/push/push-fallbacking.spec.js rename to src/__tests__/browserSuites/push-fallbacking.spec.js index 3410126..fe12676 100644 --- a/src/__tests__/push/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,17 +25,18 @@ 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'; 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'; -const thirdUserKey = 'facundo@split.io'; const baseUrls = { sdk: 'https://sdk.push-fallbacking/api', @@ -55,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; @@ -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__/push/push-initialization-nopush.spec.js b/src/__tests__/browserSuites/push-initialization-nopush.spec.js similarity index 97% rename from src/__tests__/push/push-initialization-nopush.spec.js rename to src/__tests__/browserSuites/push-initialization-nopush.spec.js index b8e7bc4..6e0e0a4 100644 --- a/src/__tests__/push/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'; @@ -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 = { @@ -33,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__/push/push-initialization-retries.spec.js b/src/__tests__/browserSuites/push-initialization-retries.spec.js similarity index 98% rename from src/__tests__/push/push-initialization-retries.spec.js rename to src/__tests__/browserSuites/push-initialization-retries.spec.js index 0879954..4d72ee1 100644 --- a/src/__tests__/push/push-initialization-retries.spec.js +++ b/src/__tests__/browserSuites/push-initialization-retries.spec.js @@ -6,9 +6,11 @@ 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 '../../index'; -import { settingsValidator } from '../../settings'; + +import { SplitFactory } from '../../'; +import { settingsFactory } from '../../settings'; const baseUrls = { sdk: 'https://sdk.push-initialization-retries/api', @@ -34,7 +36,7 @@ const config = { streamingEnabled: true, // debug: true, }; -const settings = settingsValidator(config); +const settings = settingsFactory(config); /** * Sequence of calls: diff --git a/src/__tests__/push/push-refresh-token.spec.js b/src/__tests__/browserSuites/push-refresh-token.spec.js similarity index 97% rename from src/__tests__/push/push-refresh-token.spec.js rename to src/__tests__/browserSuites/push-refresh-token.spec.js index 39a0b24..8a22650 100644 --- a/src/__tests__/push/push-refresh-token.spec.js +++ b/src/__tests__/browserSuites/push-refresh-token.spec.js @@ -1,17 +1,18 @@ 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'; import { nearlyEqual, url } from '../testUtils'; -// Polyfill EventSource with mock +// Replace global EventSource with mock 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 +33,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__/push/push-synchronization-retries.spec.js b/src/__tests__/browserSuites/push-synchronization-retries.spec.js similarity index 98% rename from src/__tests__/push/push-synchronization-retries.spec.js rename to src/__tests__/browserSuites/push-synchronization-retries.spec.js index c106710..03c7955 100644 --- a/src/__tests__/push/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'; @@ -17,8 +19,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 +39,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__/push/push-synchronization.spec.js b/src/__tests__/browserSuites/push-synchronization.spec.js similarity index 98% rename from src/__tests__/push/push-synchronization.spec.js rename to src/__tests__/browserSuites/push-synchronization.spec.js index 4f5d01a..f6ffa61 100644 --- a/src/__tests__/push/push-synchronization.spec.js +++ b/src/__tests__/browserSuites/push-synchronization.spec.js @@ -21,15 +21,16 @@ 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 { settingsValidator } from '../../settings'; +import { SplitFactory } from '../../'; +import { settingsFactory } from '../../settings'; const userKey = 'nicolas@split.io'; const otherUserKey = 'marcio@split.io'; @@ -49,9 +50,8 @@ const config = { }, urls: baseUrls, streamingEnabled: true, - debug: DebugLogger(), }; -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__/online/readiness.spec.js b/src/__tests__/browserSuites/readiness.spec.js similarity index 99% rename from src/__tests__/online/readiness.spec.js rename to src/__tests__/browserSuites/readiness.spec.js index 8d50634..ee92746 100644 --- a/src/__tests__/online/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__/online/ready-from-cache.spec.js b/src/__tests__/browserSuites/ready-from-cache.spec.js similarity index 99% rename from src/__tests__/online/ready-from-cache.spec.js rename to src/__tests__/browserSuites/ready-from-cache.spec.js index 7c5c0d9..7909278 100644 --- a/src/__tests__/online/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'; @@ -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__/online/ready-promise.spec.js b/src/__tests__/browserSuites/ready-promise.spec.js similarity index 99% rename from src/__tests__/online/ready-promise.spec.js rename to src/__tests__/browserSuites/ready-promise.spec.js index 0a35a4d..c127a7c 100644 --- a/src/__tests__/online/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'; @@ -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__/online/shared-instantiation.spec.js b/src/__tests__/browserSuites/shared-instantiation.spec.js similarity index 96% rename from src/__tests__/online/shared-instantiation.spec.js rename to src/__tests__/browserSuites/shared-instantiation.spec.js index 4208932..108ad1f 100644 --- a/src/__tests__/online/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' }, @@ -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..f87783d --- /dev/null +++ b/src/__tests__/browserSuites/single-sync.spec.js @@ -0,0 +1,65 @@ +import { SplitFactory } from '../../'; +import { settingsFactory } 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 = settingsFactory(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__/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 96% rename from src/__tests__/online/use-beacon-api.debug.spec.js rename to src/__tests__/browserSuites/use-beacon-api.debug.spec.js index 2b11880..96320f2 100644 --- a/src/__tests__/online/use-beacon-api.debug.spec.js +++ b/src/__tests__/browserSuites/use-beacon-api.debug.spec.js @@ -1,10 +1,11 @@ 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'; -import { url, triggerPagehideEvent, triggerVisibilitychange } from '../testUtils'; +import { url } from '../testUtils'; +import { triggerPagehideEvent, triggerVisibilitychange } from '../testUtils/browser'; const config = { core: { @@ -21,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__/online/use-beacon-api.spec.js b/src/__tests__/browserSuites/use-beacon-api.spec.js similarity index 96% rename from src/__tests__/online/use-beacon-api.spec.js rename to src/__tests__/browserSuites/use-beacon-api.spec.js index d09102c..8cb2122 100644 --- a/src/__tests__/online/use-beacon-api.spec.js +++ b/src/__tests__/browserSuites/use-beacon-api.spec.js @@ -1,10 +1,11 @@ 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 { url, triggerPagehideEvent, triggerVisibilitychange } from '../testUtils'; +import { url } from '../testUtils'; import { OPTIMIZED } from '@splitsoftware/splitio-commons/src/utils/constants'; +import { triggerPagehideEvent, triggerVisibilitychange } from '../testUtils/browser'; const config = { core: { @@ -18,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__/online/user-consent.spec.js b/src/__tests__/browserSuites/user-consent.spec.js similarity index 98% rename from src/__tests__/online/user-consent.spec.js rename to src/__tests__/browserSuites/user-consent.spec.js index ef4fbd7..7dd3cad 100644 --- a/src/__tests__/online/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 { SplitFactory } from '../../'; +import { triggerPagehideEvent } from '../testUtils/browser'; +import { nearlyEqual, url } from '../testUtils'; const trackedImpressions = []; diff --git a/src/__tests__/consumerMode/browser_consumer.spec.js b/src/__tests__/consumer/browser_consumer.spec.js similarity index 99% rename from src/__tests__/consumerMode/browser_consumer.spec.js rename to src/__tests__/consumer/browser_consumer.spec.js index c8e29a0..f2575b6 100644 --- a/src/__tests__/consumerMode/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__/consumerMode/browser_consumer_partial.spec.js b/src/__tests__/consumer/browser_consumer_partial.spec.js similarity index 99% rename from src/__tests__/consumerMode/browser_consumer_partial.spec.js rename to src/__tests__/consumer/browser_consumer_partial.spec.js index c3fd126..b487880 100644 --- a/src/__tests__/consumerMode/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__/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__/destroy/browser.spec.js b/src/__tests__/destroy/browser.spec.js index 79be403..2c1b3d2 100644 --- a/src/__tests__/destroy/browser.spec.js +++ b/src/__tests__/destroy/browser.spec.js @@ -3,14 +3,15 @@ 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 } 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' }, @@ -30,7 +31,6 @@ tape('SDK destroy for BrowserJS', async function (assert) { authorizationKey: 'fake-key', key: 'ut1' }, - debug: DebugLogger(), streamingEnabled: false }; diff --git a/src/__tests__/errors/browser.spec.js b/src/__tests__/errorCatching/browser.spec.js similarity index 96% rename from src/__tests__/errors/browser.spec.js rename to src/__tests__/errorCatching/browser.spec.js index e21f05d..3853da4 100644 --- a/src/__tests__/errors/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 0ba6dc2..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'; @@ -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, @@ -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..6d61aea 100644 --- a/src/__tests__/gaIntegration/browser.spec.js +++ b/src/__tests__/gaIntegration/browser.spec.js @@ -4,11 +4,13 @@ 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 815f4b1..e26c441 100644 --- a/src/__tests__/gaIntegration/ga-to-split.spec.js +++ b/src/__tests__/gaIntegration/ga-to-split.spec.js @@ -1,13 +1,13 @@ 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'; 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: { @@ -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__/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 892d277..0b2be89 100644 --- a/src/__tests__/offline/browser.spec.js +++ b/src/__tests__/offline/browser.spec.js @@ -4,9 +4,9 @@ import fetchMock from '../testUtils/fetchMock'; import { url } from '../testUtils'; import { SplitFactory, InLocalStorage } from '../../full'; import { SplitFactory as SplitFactorySlim, LocalhostFromObject } from '../../'; -import { settingsValidator } from '../../settings'; +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(); @@ -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..cf75666 100644 --- a/src/__tests__/online/browser.spec.js +++ b/src/__tests__/online/browser.spec.js @@ -1,24 +1,25 @@ 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 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'; @@ -27,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' }, @@ -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__/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 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')); -} 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