From 575a518059786279c1b6cb115df22f7b8ebd2b42 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Mon, 22 Aug 2022 17:53:30 +0200 Subject: [PATCH 1/2] add test-ts-decls --- .github/workflows/ci.yml | 3 + CONTRIBUTORS-GUIDE.md | 2 + package.json | 1 + ts-tests/index.ts | 617 +++++++++++++++++++++++++++++++++++++++ ts-tests/tsconfig.json | 11 + 5 files changed, 634 insertions(+) create mode 100644 ts-tests/index.ts create mode 100644 ts-tests/tsconfig.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 55ae4708..c983ecb0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,6 +33,9 @@ jobs: - name: npm Check run: npm run check + - name: npm ts tests + run: npm run test-ts-decls + - name: npm Test run: npm run test diff --git a/CONTRIBUTORS-GUIDE.md b/CONTRIBUTORS-GUIDE.md index 24d51b40..e77d95ae 100644 --- a/CONTRIBUTORS-GUIDE.md +++ b/CONTRIBUTORS-GUIDE.md @@ -32,6 +32,8 @@ The project includes unit as well as integration tests for browser environments. All tests can be run at once with the command `npm run test`. +If you've updated the TypeScript declaration file (`/src/types.d.ts`), you should add some lines verifying the updates in `/ts-tests/index.ts` and then run the TypeScript compilation test using the `npm run test-ts-decls` command. + For additional testing scripts or to get more insight on how these work, please refer to our [package.json](package.json) file. ### Linting and other useful checks diff --git a/package.json b/package.json index b8a27b5f..aaaca0d5 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "build": "npm run build:cjs && npm run build:esm", "build:esm": "rimraf esm types && tsc -m es2015 --outDir esm", "build:cjs": "rimraf cjs && tsc -m CommonJS --outDir cjs", + "test-ts-decls": "tsc --build ts-tests", "test": "jest", "test:coverage": "jest --coverage", "publish:rc": "npm run check && npm run test && npm run build && npm publish --tag rc", diff --git a/ts-tests/index.ts b/ts-tests/index.ts new file mode 100644 index 00000000..b17ee2c8 --- /dev/null +++ b/ts-tests/index.ts @@ -0,0 +1,617 @@ +/** + * Split software typescript declarations testing. + * + * This file is not meant to run but to be compiled without errors. This is the same way to test .d.ts files + * that you will need to comply to publish packages on @types organization on NPM (DefinitelyTyped). + * We import the declarations through the NPM package name (using the development branch of the repo) + * to test in the same way in which customers will be using it on development. + * + * The step of compiling this file is part of the continous integration systems in place. + * + * @author Nico Zelaya + */ + +/// + +let stringPromise: Promise; +let splitNamesPromise: Promise; +let splitViewPromise: Promise; +let splitViewsPromise: Promise; +let treatmentsPromise: Promise; +let treatmentWithConfigPromise: Promise; +let treatmentsWithConfigPromise: Promise; +let trackPromise: Promise; + +/**** Interfaces ****/ + +// Facade return interface +let SDK: SplitIO.ISDK; +let AsyncSDK: SplitIO.IAsyncSDK; +let BrowserSDK: SplitIO.IBrowserSDK; +// Settings interfaces +let nodeSettings: SplitIO.INodeSettings; +let asyncSettings: SplitIO.INodeAsyncSettings; +let browserSettings: SplitIO.IBrowserSettings; +// Client & Manager APIs +let client: SplitIO.IClient; +let manager: SplitIO.IManager; +let asyncClient: SplitIO.IAsyncClient; +let asyncManager: SplitIO.IAsyncManager; +let browserClient: SplitIO.IBrowserClient; +// Utility interfaces +let impressionListener: SplitIO.IImpressionListener; + +/**** Custom Types ****/ + +// Common +let treatment: SplitIO.Treatment = 'on'; +let treatmentWithConfig: SplitIO.TreatmentWithConfig = { + treatment: 'control', + config: null +}; +treatmentWithConfig = { treatment: 'off', config: '{}' }; +let asyncTreatment: SplitIO.AsyncTreatment = stringPromise; +let asyncTreatmentWithConfig: SplitIO.AsyncTreatmentWithConfig = treatmentWithConfigPromise; +let tracked: boolean; +let treatmentsMap: SplitIO.Treatments = { + feature1: 'on', + feature2: 'control' +}; +let treatmentsWithConfigMap: SplitIO.TreatmentsWithConfig = { + feature1: { treatment: 'control', config: null }, + feature2: { treatment: 'off', config: '{"color":"blue"}' } +}; +let treatments: SplitIO.Treatments = treatmentsMap; +let treatmentsWithConfig: SplitIO.TreatmentsWithConfig = treatmentsWithConfigMap; +let asyncTreatments: SplitIO.AsyncTreatments = treatmentsPromise; +let asyncTreatmentsWithConfig: SplitIO.AsyncTreatmentsWithConfig = treatmentsWithConfigPromise; +let splitEvent: SplitIO.Event; +const attributes: SplitIO.Attributes = { + attr1: 1, + attr2: '2', + attr3: Date.now(), + attr4: ['str1', 2], + attr5: ['str1', 'str2'], + attr6: [1, 2], + attr7: true +}; +const splitKeyObj: SplitIO.SplitKeyObject = { + matchingKey: 'matchingKey', + bucketingKey: 'bucketingKey' +}; +let splitKey: SplitIO.SplitKey; +// Mocks +let mockedFeaturesPath: SplitIO.MockedFeaturesFilePath; +let mockedFeaturesMap: SplitIO.MockedFeaturesMap; +// Split Data +let splitView: SplitIO.SplitView; +let splitViews: SplitIO.SplitViews; +let splitNames: SplitIO.SplitNames; +let splitNamesAsync: SplitIO.SplitNamesAsync; +let splitViewAsync: SplitIO.SplitViewAsync; +let splitViewsAsync: SplitIO.SplitViewsAsync; +// Impression data +let impressionData: SplitIO.ImpressionData; +// Storages +let nodeStorage: SplitIO.NodeSyncStorage; +let nodeAsyncStorage: SplitIO.NodeAsyncStorage; +let browserStorage: SplitIO.BrowserStorage; + +mockedFeaturesPath = 'path/to/file'; +mockedFeaturesMap = { + feature1: 'treatment', + feature2: { treatment: 'treatment2', config: "{ 'prop': 'value'}" }, + feature3: { treatment: 'treatment3', config: null } +}; + +// Treatment can be the string or the promise which will resolve to treatment string +treatment = 'some treatment'; // Sync case +asyncTreatment = stringPromise; // Async case + +// Treatments can be the object or the promise which will resolve to treatments object +treatments = { + someFeature: 'treatment' +}; // Sync +asyncTreatments = treatmentsPromise; // Async + +// SplitViews can be the SplitViewData or the promise which will resolve to SplitViewData obj +splitView = { + name: 'asd', + killed: false, + trafficType: 'user', + treatments: ['on', 'off'], + changeNumber: 18294, + configs: { + off: '{"dimensions":"{\"height\":20,\"width\":40}"}' + } +}; +splitViews = [splitView]; + +splitViewAsync = splitViewPromise; +splitNamesAsync = splitNamesPromise; +splitViewsAsync = splitViewsPromise; + +// Split key could be a split key object or a string +splitKey = 'someKey'; +splitKey = splitKeyObj; + +/**** Tests for ISDK interface ****/ + +// For node with sync storage +nodeSettings = { + core: { + authorizationKey: 'key' + } +}; +// For node with async storage +asyncSettings = { + core: { + authorizationKey: 'key' + }, + mode: 'consumer', + storage: { + type: 'REDIS' + } +}; +// For browser +browserSettings = { + core: { + authorizationKey: 'another-key', + key: 'customer-key' + } +}; +// With sync settings should return ISDK, if settings have async storage it should return IAsyncSDK +SDK = SplitFactory(nodeSettings); +AsyncSDK = SplitFactory(asyncSettings); +BrowserSDK = SplitFactory(browserSettings); + +// The settings values the SDK expose. +const instantiatedSettingsCore: { + authorizationKey: string, + key?: SplitIO.SplitKey, + trafficType?: string, + labelsEnabled: boolean, + IPAddressesEnabled?: boolean +} = SDK.settings.core; +const instantiatedSettingsMode: ('standalone' | 'consumer' | 'localhost' | 'consumer_partial') = SDK.settings.mode; +const instantiatedSettingsScheduler: { [key: string]: number } = SDK.settings.scheduler; +const instantiatedSettingsStartup: { [key: string]: number } = SDK.settings.startup; +const instantiatedSettingsStorage: { + prefix: string, + options: Object, + // It can have any of the storages. + type: SplitIO.StorageType +} | SplitIO.StorageSyncFactory | SplitIO.StorageAsyncFactory = SDK.settings.storage; +const instantiatedSettingsUrls: { [key: string]: string } = SDK.settings.urls; +const instantiatedSettingsVersion: string = SDK.settings.version; +let instantiatedSettingsFeatures = SDK.settings.features as SplitIO.MockedFeaturesMap; +// We should be able to write on features prop. The rest are readonly props. +instantiatedSettingsFeatures.something = 'something'; +SDK.settings.features = 'new_file_path'; // Node +SDK.settings.features = { 'split_x': 'on' }; // Browser + +// Client and Manager in Node +client = SDK.client(); +manager = SDK.manager(); +// Today async clients are only possible on Node. Shared client creation not available here. +asyncClient = AsyncSDK.client(); +asyncManager = AsyncSDK.manager(); +// Browser client for attributes binding +browserClient = BrowserSDK.client(); +browserClient = BrowserSDK.client('a customer key'); +browserClient = BrowserSDK.client('a customer key', 'a traffic type'); + +// Logger +SDK.Logger.enable(); +SDK.Logger.setLogLevel(SDK.Logger.LogLevel.DEBUG); +SDK.Logger.setLogLevel(SDK.Logger.LogLevel.INFO); +SDK.Logger.setLogLevel(SDK.Logger.LogLevel.WARN); +SDK.Logger.setLogLevel(SDK.Logger.LogLevel.ERROR); +SDK.Logger.setLogLevel(SDK.Logger.LogLevel.NONE); +SDK.Logger.disable(); + +AsyncSDK.Logger.enable(); +AsyncSDK.Logger.setLogLevel(AsyncSDK.Logger.LogLevel.DEBUG); +AsyncSDK.Logger.setLogLevel(AsyncSDK.Logger.LogLevel.INFO); +AsyncSDK.Logger.setLogLevel(AsyncSDK.Logger.LogLevel.WARN); +AsyncSDK.Logger.setLogLevel(AsyncSDK.Logger.LogLevel.ERROR); +AsyncSDK.Logger.setLogLevel(AsyncSDK.Logger.LogLevel.NONE); +AsyncSDK.Logger.disable(); + +/**** Tests for IClient interface ****/ + +// Events constants we get +const eventConsts: { [key: string]: SplitIO.Event } = client.Event; +splitEvent = client.Event.SDK_READY; +splitEvent = client.Event.SDK_READY_FROM_CACHE; +splitEvent = client.Event.SDK_READY_TIMED_OUT; +splitEvent = client.Event.SDK_UPDATE; + +// Client implements methods from NodeJS.Events. Testing a few. +client = client.on(splitEvent, () => { }); +const a: boolean = client.emit(splitEvent); +client = client.removeAllListeners(splitEvent); +client = client.removeAllListeners(); +const b: number = client.listenerCount(splitEvent); +let nodeEventEmitter: NodeJS.EventEmitter = client; + +// Ready and destroy +const readyPromise: Promise = client.ready(); +const destroyPromise: Promise = client.destroy(); + +// We can call getTreatment with or without a key. +treatment = client.getTreatment(splitKey, 'mySplit'); +treatment = browserClient.getTreatment('mySplit'); +// Attributes parameter is optional on both signatures. +treatment = client.getTreatment(splitKey, 'mySplit', attributes); +treatment = browserClient.getTreatment('mySplit', attributes); + +// We can call getTreatments with or without a key. +treatments = client.getTreatments(splitKey, ['mySplit']); +treatments = browserClient.getTreatments(['mySplit']); +// Attributes parameter is optional on both signatures. +treatments = client.getTreatments(splitKey, ['mySplit'], attributes); +treatments = browserClient.getTreatments(['mySplit'], attributes); + +// We can call getTreatmentWithConfig with or without a key. +treatmentWithConfig = client.getTreatmentWithConfig(splitKey, 'mySplit'); +treatmentWithConfig = browserClient.getTreatmentWithConfig('mySplit'); +// Attributes parameter is optional on both signatures. +treatmentWithConfig = client.getTreatmentWithConfig(splitKey, 'mySplit', attributes); +treatmentWithConfig = browserClient.getTreatmentWithConfig('mySplit', attributes); + +// We can call getTreatmentsWithConfig with or without a key. +treatmentsWithConfig = client.getTreatmentsWithConfig(splitKey, ['mySplit']); +treatmentsWithConfig = browserClient.getTreatmentsWithConfig(['mySplit']); +// Attributes parameter is optional on both signatures. +treatmentsWithConfig = client.getTreatmentsWithConfig(splitKey, ['mySplit'], attributes); +treatmentsWithConfig = browserClient.getTreatmentsWithConfig(['mySplit'], attributes); + +// We can call track with or without a key. Traffic type can also be binded to the client. +tracked = client.track(splitKey, 'myTrafficType', 'myEventType'); // all params +tracked = browserClient.track('myTrafficType', 'myEventType'); // key binded, tt provided. +tracked = browserClient.track('myEventType'); // key and tt binded. +// Value parameter is optional on all signatures. +tracked = client.track(splitKey, 'myTrafficType', 'myEventType', 10); +tracked = browserClient.track('myTrafficType', 'myEventType', 10); +tracked = browserClient.track('myEventType', 10); +// Properties parameter is optional on all signatures. +tracked = client.track(splitKey, 'myTrafficType', 'myEventType', 10, { prop1: 1, prop2: '2', prop3: false, prop4: null }); +tracked = browserClient.track('myTrafficType', 'myEventType', null, { prop1: 1, prop2: '2', prop3: false, prop4: null }); +tracked = browserClient.track('myEventType', undefined, { prop1: 1, prop2: '2', prop3: false, prop4: null }); + +/*** Repeating tests for Async Client ***/ + +// Events constants we get (same as for sync client, just for interface checking) +const eventConstsAsync: { [key: string]: SplitIO.Event } = asyncClient.Event; +splitEvent = asyncClient.Event.SDK_READY; +splitEvent = asyncClient.Event.SDK_READY_FROM_CACHE; +splitEvent = asyncClient.Event.SDK_READY_TIMED_OUT; +splitEvent = asyncClient.Event.SDK_UPDATE; + +// Client implements methods from NodeJS.Events. (same as for sync client, just for interface checking) +asyncClient = asyncClient.on(splitEvent, () => { }); +const a1: boolean = asyncClient.emit(splitEvent); +asyncClient = asyncClient.removeAllListeners(splitEvent); +asyncClient = asyncClient.removeAllListeners(); +const b1: number = asyncClient.listenerCount(splitEvent); +nodeEventEmitter = asyncClient; + +// Ready and destroy (same as for sync client, just for interface checking) +const readyPromise1: Promise = asyncClient.ready(); +asyncClient.destroy(); + +// We can call getTreatment but always with a key. +asyncTreatment = asyncClient.getTreatment(splitKey, 'mySplit'); +// Attributes parameter is optional +asyncTreatment = asyncClient.getTreatment(splitKey, 'mySplit', attributes); + +// We can call getTreatments but always with a key. +asyncTreatments = asyncClient.getTreatments(splitKey, ['mySplit']); +// Attributes parameter is optional +asyncTreatments = asyncClient.getTreatments(splitKey, ['mySplit'], attributes); + +// We can call getTreatmentWithConfig but always with a key. +asyncTreatmentWithConfig = asyncClient.getTreatmentWithConfig(splitKey, 'mySplit'); +// Attributes parameter is optional +asyncTreatmentWithConfig = asyncClient.getTreatmentWithConfig(splitKey, 'mySplit', attributes); + +// We can call getTreatments but always with a key. +asyncTreatmentsWithConfig = asyncClient.getTreatmentsWithConfig(splitKey, ['mySplit']); +// Attributes parameter is optional +asyncTreatmentsWithConfig = asyncClient.getTreatmentsWithConfig(splitKey, ['mySplit'], attributes); + +// We can call track only with a key. +trackPromise = asyncClient.track(splitKey, 'myTrafficType', 'myEventType'); // all required params +// Value parameter is optional. +trackPromise = asyncClient.track(splitKey, 'myTrafficType', 'myEventType', 10); +// Properties parameter is optional +trackPromise = asyncClient.track(splitKey, 'myTrafficType', 'myEventType', 10, { prop1: 1, prop2: '2', prop3: true, prop4: null }); + +/**** Tests for IManager interface ****/ + +splitNames = manager.names(); +splitView = manager.split('mySplit'); +splitViews = manager.splits(); + +// Manager implements ready promise. +const managerReadyPromise: Promise = manager.ready(); + +// Manager implements methods from NodeJS.Events. Testing a few. +manager = manager.on(splitEvent, () => { }); +const aa: boolean = manager.emit(splitEvent); +manager = manager.removeAllListeners(splitEvent); +manager = manager.removeAllListeners(); +const bb: number = manager.listenerCount(splitEvent); +nodeEventEmitter = manager; + +// manager exposes Event constants too +const managerEventConsts: { [key: string]: SplitIO.Event } = manager.Event; +splitEvent = manager.Event.SDK_READY; +splitEvent = manager.Event.SDK_READY_FROM_CACHE; +splitEvent = manager.Event.SDK_READY_TIMED_OUT; +splitEvent = manager.Event.SDK_UPDATE; + +/*** Repeating tests for Async Manager ***/ + +splitNamesAsync = asyncManager.names(); +splitViewAsync = asyncManager.split('mySplit'); +splitViewsAsync = asyncManager.splits(); + +// asyncManager implements ready promise. +const asyncManagerReadyPromise: Promise = asyncManager.ready(); + +// asyncManager implements methods from NodeJS.Events. Testing a few. +asyncManager = asyncManager.on(splitEvent, () => { }); +const aaa: boolean = asyncManager.emit(splitEvent); +asyncManager = asyncManager.removeAllListeners(splitEvent); +asyncManager = asyncManager.removeAllListeners(); +const bbb: number = asyncManager.listenerCount(splitEvent); +nodeEventEmitter = asyncManager; + +// asyncManager exposes Event constants too +const asyncManagerEventConsts: { [key: string]: SplitIO.Event } = asyncManager.Event; +splitEvent = asyncManager.Event.SDK_READY; +splitEvent = asyncManager.Event.SDK_READY_FROM_CACHE; +splitEvent = asyncManager.Event.SDK_READY_TIMED_OUT; +splitEvent = asyncManager.Event.SDK_UPDATE; + +/*** Tests for IImpressionListener interface ***/ +class MyImprListener implements SplitIO.IImpressionListener { + logImpression(data: SplitIO.ImpressionData) { + impressionData = data; + } +} + +const MyImprListenerMap: SplitIO.IImpressionListener = { + logImpression: (data: SplitIO.ImpressionData) => { + impressionData = data; + } +}; + +impressionListener = MyImprListenerMap; +impressionListener = new MyImprListener(); +impressionListener.logImpression(impressionData); + +/**** Tests for attribute binding ****/ +let stored: boolean = browserClient.setAttribute('stringAttribute', 'value'); +stored = browserClient.setAttribute('numberAttribtue', 1); +stored = browserClient.setAttribute('booleanAttribute', true); +stored = browserClient.setAttribute('stringArrayAttribute', ['value1', 'value2']); +stored = browserClient.setAttribute('numberArrayAttribute', [1, 2]); + +let storedAttributeValue: SplitIO.AttributeType = browserClient.getAttribute('stringAttribute'); +storedAttributeValue = browserClient.getAttribute('numberAttribute'); +storedAttributeValue = browserClient.getAttribute('booleanAttribute'); +storedAttributeValue = browserClient.getAttribute('stringArrayAttribute'); +storedAttributeValue = browserClient.getAttribute('numberArrayAttribute'); + +let removed: boolean = browserClient.removeAttribute('numberAttribute'); +removed = browserClient.clearAttributes(); + +let attr: SplitIO.Attributes = { + stringAttribute: 'value', + numberAttribute: 1, + booleanAttribute: true, + stringArrayAttribute: ['value1', 'value2'], + numberArrayAttribute: [1, 2] +} + +stored = browserClient.setAttributes(attr); +let storedAttr: SplitIO.Attributes = browserClient.getAttributes(); +removed = browserClient.clearAttributes(); + +/**** Tests for user consent API ****/ + +let userConsent: SplitIO.ConsentStatus; +userConsent = BrowserSDK.UserConsent.getStatus(); +BrowserSDK.UserConsent.setStatus(true); +BrowserSDK.UserConsent.setStatus(false); +userConsent = BrowserSDK.UserConsent.Status.DECLINED; +userConsent = BrowserSDK.UserConsent.Status.GRANTED; +userConsent = BrowserSDK.UserConsent.Status.UNKNOWN; + +/**** Tests for fully crowded settings interfaces ****/ + +// Split filters +let splitFilters: SplitIO.SplitFilter[] = [{ type: 'byName', values: ['my_split_1', 'my_split_1'] }, { type: 'byPrefix', values: ['my_split', 'test_split_'] }] + +// Browser integrations +let fieldsObjectSample: UniversalAnalytics.FieldsObject = { hitType: 'event', eventAction: 'action' }; +let eventDataSample: SplitIO.EventData = { eventTypeId: 'someEventTypeId', value: 10, properties: {} } + +let googleAnalyticsToSplitConfig: SplitIO.IGoogleAnalyticsToSplitConfig = { + type: 'GOOGLE_ANALYTICS_TO_SPLIT', +}; +let splitToGoogleAnalyticsConfig: SplitIO.ISplitToGoogleAnalyticsConfig = { + type: 'SPLIT_TO_GOOGLE_ANALYTICS', +}; + +let customGoogleAnalyticsToSplitConfig: SplitIO.IGoogleAnalyticsToSplitConfig = { + type: 'GOOGLE_ANALYTICS_TO_SPLIT', + hits: false, + filter: function (model: UniversalAnalytics.Model): boolean { return true; }, + mapper: function (model: UniversalAnalytics.Model, defaultMapping: SplitIO.EventData): SplitIO.EventData { return eventDataSample; }, + prefix: 'PREFIX', + identities: [{ key: 'key1', trafficType: 'tt1' }, { key: 'key2', trafficType: 'tt2' }], + autoRequire: true +}; +let customSplitToGoogleAnalyticsConfig: SplitIO.ISplitToGoogleAnalyticsConfig = { + type: 'SPLIT_TO_GOOGLE_ANALYTICS', + events: false, + impressions: true, + filter: function (model: SplitIO.IntegrationData): boolean { return true; }, + mapper: function (model: SplitIO.IntegrationData, defaultMapping: UniversalAnalytics.FieldsObject): UniversalAnalytics.FieldsObject { return fieldsObjectSample; }, + trackerNames: ['t0', 'myTracker'], +} + +let fullBrowserSettings: SplitIO.IBrowserSettings = { + core: { + authorizationKey: 'asd', + key: 'asd', + trafficType: 'myTT', + labelsEnabled: false + }, + scheduler: { + featuresRefreshRate: 1, + impressionsRefreshRate: 1, + impressionsQueueSize: 1, + metricsRefreshRate: 1, + telemetryRefreshRate: 1, + segmentsRefreshRate: 1, + offlineRefreshRate: 1, + eventsPushRate: 1, + eventsQueueSize: 1, + pushRetryBackoffBase: 1 + }, + startup: { + readyTimeout: 1, + requestTimeoutBeforeReady: 1, + retriesOnFailureBeforeReady: 1, + eventsFirstPushWindow: 1 + }, + urls: { + sdk: 'https://asd.com/sdk', + events: 'https://asd.com/events', + auth: 'https://asd.com/auth', + streaming: 'https://asd.com/streaming', + telemetry: 'https://asd.com/telemetry' + }, + features: mockedFeaturesMap, + storage: { + type: 'LOCALSTORAGE', + prefix: 'PREFIX' + }, + impressionListener: impressionListener, + debug: true, + integrations: [googleAnalyticsToSplitConfig, splitToGoogleAnalyticsConfig, customGoogleAnalyticsToSplitConfig, customSplitToGoogleAnalyticsConfig], + streamingEnabled: true, + sync: { + splitFilters: splitFilters, + impressionsMode: 'DEBUG', + enabled: true + }, + userConsent: 'GRANTED' +}; +fullBrowserSettings.storage.type = 'MEMORY'; +fullBrowserSettings.integrations[0].type = 'GOOGLE_ANALYTICS_TO_SPLIT'; +fullBrowserSettings.userConsent = 'DECLINED'; +fullBrowserSettings.userConsent = 'UNKNOWN'; + +let fullNodeSettings: SplitIO.INodeSettings = { + core: { + authorizationKey: 'asd', + labelsEnabled: false, + IPAddressesEnabled: false + }, + scheduler: { + featuresRefreshRate: 1, + impressionsRefreshRate: 1, + impressionsQueueSize: 1, + metricsRefreshRate: 1, + telemetryRefreshRate: 1, + segmentsRefreshRate: 1, + offlineRefreshRate: 1, + eventsPushRate: 1, + eventsQueueSize: 1, + pushRetryBackoffBase: 1 + }, + startup: { + readyTimeout: 1, + requestTimeoutBeforeReady: 1, + retriesOnFailureBeforeReady: 1, + eventsFirstPushWindow: 1 + }, + urls: { + sdk: 'https://asd.com/sdk', + events: 'https://asd.com/events', + auth: 'https://asd.com/auth', + streaming: 'https://asd.com/streaming', + telemetry: 'https://asd.com/telemetry' + }, + features: mockedFeaturesPath, + storage: { + type: 'MEMORY' + }, + impressionListener: impressionListener, + mode: 'standalone', + debug: false, + streamingEnabled: false, + sync: { + splitFilters: splitFilters, + impressionsMode: 'OPTIMIZED', + enabled: true + } +}; +fullNodeSettings.storage.type = 'MEMORY'; +fullNodeSettings.mode = undefined; + +let fullAsyncSettings: SplitIO.INodeAsyncSettings = { + core: { + authorizationKey: 'asd', + labelsEnabled: false, + IPAddressesEnabled: false + }, + scheduler: { + featuresRefreshRate: 1, + impressionsRefreshRate: 1, + impressionsQueueSize: 1, + metricsRefreshRate: 1, + telemetryRefreshRate: 1, + segmentsRefreshRate: 1, + offlineRefreshRate: 1, + eventsPushRate: 1, + eventsQueueSize: 1 + }, + startup: { + readyTimeout: 1, + requestTimeoutBeforeReady: 1, + retriesOnFailureBeforeReady: 1 + }, + features: mockedFeaturesPath, + storage: { + type: 'REDIS', + options: { + url: 'url', + host: 'host', + port: 1234, + db: 0, + pass: 'pass', + connectionTimeout: 100, + operationTimeout: 100, + tls: { ca: ['ca'] } + }, + prefix: 'PREFIX' + }, + impressionListener: impressionListener, + mode: 'consumer', + debug: true, + sync: { + splitFilters: splitFilters + } +}; + +// debug property can be a log level +fullBrowserSettings.debug = 'ERROR'; +fullNodeSettings.debug = 'WARN'; +fullAsyncSettings.debug = 'INFO'; diff --git a/ts-tests/tsconfig.json b/ts-tests/tsconfig.json new file mode 100644 index 00000000..2c1ab20a --- /dev/null +++ b/ts-tests/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "noImplicitAny": true, + "target": "es5", + "module": "commonjs", + "noEmit": true, + }, + "files": [ + "index" + ] +} From 56ae5ed48b995ac094f576cf176b25e2f498e1f4 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Mon, 22 Aug 2022 18:58:40 +0200 Subject: [PATCH 2/2] add index.ts test script --- ts-tests/index.ts | 364 +++++++++------------------------------------- 1 file changed, 65 insertions(+), 299 deletions(-) diff --git a/ts-tests/index.ts b/ts-tests/index.ts index b17ee2c8..7149bfb7 100644 --- a/ts-tests/index.ts +++ b/ts-tests/index.ts @@ -13,6 +13,11 @@ /// +namespace SplitIO { + export interface ISDK extends SplitIO.IBasicSDK { } + export interface IBrowserSDK extends SplitIO.ISDKWithUserConsent { } +} + let stringPromise: Promise; let splitNamesPromise: Promise; let splitViewPromise: Promise; @@ -26,20 +31,17 @@ let trackPromise: Promise; // Facade return interface let SDK: SplitIO.ISDK; -let AsyncSDK: SplitIO.IAsyncSDK; +// let AsyncSDK: SplitIO.IAsyncSDK; let BrowserSDK: SplitIO.IBrowserSDK; -// Settings interfaces -let nodeSettings: SplitIO.INodeSettings; -let asyncSettings: SplitIO.INodeAsyncSettings; -let browserSettings: SplitIO.IBrowserSettings; +// let AsyncBrowserSDK: SplitIO.IAsyncSDKWithKey; + // Client & Manager APIs -let client: SplitIO.IClient; +let client: SplitIO.IClientSS; +let browserClient: SplitIO.IClientWithKey; let manager: SplitIO.IManager; -let asyncClient: SplitIO.IAsyncClient; +let asyncClient: SplitIO.IAsyncClientSS; +let asyncBrowserClient: SplitIO.IAsyncClientWithKey; let asyncManager: SplitIO.IAsyncManager; -let browserClient: SplitIO.IBrowserClient; -// Utility interfaces -let impressionListener: SplitIO.IImpressionListener; /**** Custom Types ****/ @@ -92,10 +94,6 @@ let splitViewAsync: SplitIO.SplitViewAsync; let splitViewsAsync: SplitIO.SplitViewsAsync; // Impression data let impressionData: SplitIO.ImpressionData; -// Storages -let nodeStorage: SplitIO.NodeSyncStorage; -let nodeAsyncStorage: SplitIO.NodeAsyncStorage; -let browserStorage: SplitIO.BrowserStorage; mockedFeaturesPath = 'path/to/file'; mockedFeaturesMap = { @@ -137,34 +135,6 @@ splitKey = splitKeyObj; /**** Tests for ISDK interface ****/ -// For node with sync storage -nodeSettings = { - core: { - authorizationKey: 'key' - } -}; -// For node with async storage -asyncSettings = { - core: { - authorizationKey: 'key' - }, - mode: 'consumer', - storage: { - type: 'REDIS' - } -}; -// For browser -browserSettings = { - core: { - authorizationKey: 'another-key', - key: 'customer-key' - } -}; -// With sync settings should return ISDK, if settings have async storage it should return IAsyncSDK -SDK = SplitFactory(nodeSettings); -AsyncSDK = SplitFactory(asyncSettings); -BrowserSDK = SplitFactory(browserSettings); - // The settings values the SDK expose. const instantiatedSettingsCore: { authorizationKey: string, @@ -190,17 +160,6 @@ instantiatedSettingsFeatures.something = 'something'; SDK.settings.features = 'new_file_path'; // Node SDK.settings.features = { 'split_x': 'on' }; // Browser -// Client and Manager in Node -client = SDK.client(); -manager = SDK.manager(); -// Today async clients are only possible on Node. Shared client creation not available here. -asyncClient = AsyncSDK.client(); -asyncManager = AsyncSDK.manager(); -// Browser client for attributes binding -browserClient = BrowserSDK.client(); -browserClient = BrowserSDK.client('a customer key'); -browserClient = BrowserSDK.client('a customer key', 'a traffic type'); - // Logger SDK.Logger.enable(); SDK.Logger.setLogLevel(SDK.Logger.LogLevel.DEBUG); @@ -210,13 +169,13 @@ SDK.Logger.setLogLevel(SDK.Logger.LogLevel.ERROR); SDK.Logger.setLogLevel(SDK.Logger.LogLevel.NONE); SDK.Logger.disable(); -AsyncSDK.Logger.enable(); -AsyncSDK.Logger.setLogLevel(AsyncSDK.Logger.LogLevel.DEBUG); -AsyncSDK.Logger.setLogLevel(AsyncSDK.Logger.LogLevel.INFO); -AsyncSDK.Logger.setLogLevel(AsyncSDK.Logger.LogLevel.WARN); -AsyncSDK.Logger.setLogLevel(AsyncSDK.Logger.LogLevel.ERROR); -AsyncSDK.Logger.setLogLevel(AsyncSDK.Logger.LogLevel.NONE); -AsyncSDK.Logger.disable(); +BrowserSDK.Logger.enable(); +BrowserSDK.Logger.setLogLevel(BrowserSDK.Logger.LogLevel.DEBUG); +BrowserSDK.Logger.setLogLevel(BrowserSDK.Logger.LogLevel.INFO); +BrowserSDK.Logger.setLogLevel(BrowserSDK.Logger.LogLevel.WARN); +BrowserSDK.Logger.setLogLevel(BrowserSDK.Logger.LogLevel.ERROR); +BrowserSDK.Logger.setLogLevel(BrowserSDK.Logger.LogLevel.NONE); +BrowserSDK.Logger.disable(); /**** Tests for IClient interface ****/ @@ -227,60 +186,58 @@ splitEvent = client.Event.SDK_READY_FROM_CACHE; splitEvent = client.Event.SDK_READY_TIMED_OUT; splitEvent = client.Event.SDK_UPDATE; -// Client implements methods from NodeJS.Events. Testing a few. -client = client.on(splitEvent, () => { }); -const a: boolean = client.emit(splitEvent); -client = client.removeAllListeners(splitEvent); -client = client.removeAllListeners(); -const b: number = client.listenerCount(splitEvent); -let nodeEventEmitter: NodeJS.EventEmitter = client; - // Ready and destroy const readyPromise: Promise = client.ready(); const destroyPromise: Promise = client.destroy(); -// We can call getTreatment with or without a key. +// We can call getTreatment treatment = client.getTreatment(splitKey, 'mySplit'); treatment = browserClient.getTreatment('mySplit'); -// Attributes parameter is optional on both signatures. + +// Attributes parameter is optional on both signatures treatment = client.getTreatment(splitKey, 'mySplit', attributes); treatment = browserClient.getTreatment('mySplit', attributes); -// We can call getTreatments with or without a key. +// We can call getTreatments treatments = client.getTreatments(splitKey, ['mySplit']); treatments = browserClient.getTreatments(['mySplit']); -// Attributes parameter is optional on both signatures. + +// Attributes parameter is optional on both signatures treatments = client.getTreatments(splitKey, ['mySplit'], attributes); treatments = browserClient.getTreatments(['mySplit'], attributes); -// We can call getTreatmentWithConfig with or without a key. +// We can call getTreatmentWithConfig treatmentWithConfig = client.getTreatmentWithConfig(splitKey, 'mySplit'); treatmentWithConfig = browserClient.getTreatmentWithConfig('mySplit'); -// Attributes parameter is optional on both signatures. + +// Attributes parameter is optional on both signatures treatmentWithConfig = client.getTreatmentWithConfig(splitKey, 'mySplit', attributes); treatmentWithConfig = browserClient.getTreatmentWithConfig('mySplit', attributes); -// We can call getTreatmentsWithConfig with or without a key. +// We can call getTreatmentsWithConfig treatmentsWithConfig = client.getTreatmentsWithConfig(splitKey, ['mySplit']); treatmentsWithConfig = browserClient.getTreatmentsWithConfig(['mySplit']); -// Attributes parameter is optional on both signatures. + +// Attributes parameter is optional on both signatures treatmentsWithConfig = client.getTreatmentsWithConfig(splitKey, ['mySplit'], attributes); treatmentsWithConfig = browserClient.getTreatmentsWithConfig(['mySplit'], attributes); -// We can call track with or without a key. Traffic type can also be binded to the client. +// We can call track tracked = client.track(splitKey, 'myTrafficType', 'myEventType'); // all params -tracked = browserClient.track('myTrafficType', 'myEventType'); // key binded, tt provided. -tracked = browserClient.track('myEventType'); // key and tt binded. -// Value parameter is optional on all signatures. +tracked = browserClient.track('myTrafficType', 'myEventType'); // key binded, tt provided +// tracked = browserClient.track('myEventType'); // key and tt binded only in JS SDK + +// Value parameter is optional on all signatures tracked = client.track(splitKey, 'myTrafficType', 'myEventType', 10); tracked = browserClient.track('myTrafficType', 'myEventType', 10); -tracked = browserClient.track('myEventType', 10); +// tracked = browserClient.track('myEventType', 10); // key and tt binded only in JS SDK + // Properties parameter is optional on all signatures. tracked = client.track(splitKey, 'myTrafficType', 'myEventType', 10, { prop1: 1, prop2: '2', prop3: false, prop4: null }); tracked = browserClient.track('myTrafficType', 'myEventType', null, { prop1: 1, prop2: '2', prop3: false, prop4: null }); -tracked = browserClient.track('myEventType', undefined, { prop1: 1, prop2: '2', prop3: false, prop4: null }); +// tracked = browserClient.track('myEventType', undefined, { prop1: 1, prop2: '2', prop3: false, prop4: null }); // key and tt binded only in JS SDK. -/*** Repeating tests for Async Client ***/ +/*** Repeating tests for Async Clients ***/ // Events constants we get (same as for sync client, just for interface checking) const eventConstsAsync: { [key: string]: SplitIO.Event } = asyncClient.Event; @@ -289,44 +246,53 @@ splitEvent = asyncClient.Event.SDK_READY_FROM_CACHE; splitEvent = asyncClient.Event.SDK_READY_TIMED_OUT; splitEvent = asyncClient.Event.SDK_UPDATE; -// Client implements methods from NodeJS.Events. (same as for sync client, just for interface checking) -asyncClient = asyncClient.on(splitEvent, () => { }); -const a1: boolean = asyncClient.emit(splitEvent); -asyncClient = asyncClient.removeAllListeners(splitEvent); -asyncClient = asyncClient.removeAllListeners(); -const b1: number = asyncClient.listenerCount(splitEvent); -nodeEventEmitter = asyncClient; - // Ready and destroy (same as for sync client, just for interface checking) const readyPromise1: Promise = asyncClient.ready(); asyncClient.destroy(); -// We can call getTreatment but always with a key. +// We can call getTreatment asyncTreatment = asyncClient.getTreatment(splitKey, 'mySplit'); +asyncTreatment = asyncBrowserClient.getTreatment('mySplit'); + // Attributes parameter is optional asyncTreatment = asyncClient.getTreatment(splitKey, 'mySplit', attributes); +asyncTreatment = asyncBrowserClient.getTreatment('mySplit', attributes); -// We can call getTreatments but always with a key. +// We can call getTreatments asyncTreatments = asyncClient.getTreatments(splitKey, ['mySplit']); +asyncTreatments = asyncBrowserClient.getTreatments(['mySplit']); + // Attributes parameter is optional asyncTreatments = asyncClient.getTreatments(splitKey, ['mySplit'], attributes); +asyncTreatments = asyncBrowserClient.getTreatments(['mySplit'], attributes); -// We can call getTreatmentWithConfig but always with a key. +// We can call getTreatmentWithConfig asyncTreatmentWithConfig = asyncClient.getTreatmentWithConfig(splitKey, 'mySplit'); +asyncTreatmentWithConfig = asyncBrowserClient.getTreatmentWithConfig('mySplit'); + // Attributes parameter is optional asyncTreatmentWithConfig = asyncClient.getTreatmentWithConfig(splitKey, 'mySplit', attributes); +asyncTreatmentWithConfig = asyncBrowserClient.getTreatmentWithConfig('mySplit', attributes); -// We can call getTreatments but always with a key. +// We can call getTreatmentsWithConfig asyncTreatmentsWithConfig = asyncClient.getTreatmentsWithConfig(splitKey, ['mySplit']); +asyncTreatmentsWithConfig = asyncBrowserClient.getTreatmentsWithConfig(['mySplit']); + // Attributes parameter is optional asyncTreatmentsWithConfig = asyncClient.getTreatmentsWithConfig(splitKey, ['mySplit'], attributes); +asyncTreatmentsWithConfig = asyncBrowserClient.getTreatmentsWithConfig(['mySplit'], attributes); -// We can call track only with a key. +// We can call track trackPromise = asyncClient.track(splitKey, 'myTrafficType', 'myEventType'); // all required params -// Value parameter is optional. +trackPromise = asyncBrowserClient.track('myTrafficType', 'myEventType'); // all required params + +// Value parameter is optional trackPromise = asyncClient.track(splitKey, 'myTrafficType', 'myEventType', 10); +trackPromise = asyncBrowserClient.track('myTrafficType', 'myEventType', 10); + // Properties parameter is optional trackPromise = asyncClient.track(splitKey, 'myTrafficType', 'myEventType', 10, { prop1: 1, prop2: '2', prop3: true, prop4: null }); +trackPromise = asyncBrowserClient.track('myTrafficType', 'myEventType', 10, { prop1: 1, prop2: '2', prop3: true, prop4: null }); /**** Tests for IManager interface ****/ @@ -337,14 +303,6 @@ splitViews = manager.splits(); // Manager implements ready promise. const managerReadyPromise: Promise = manager.ready(); -// Manager implements methods from NodeJS.Events. Testing a few. -manager = manager.on(splitEvent, () => { }); -const aa: boolean = manager.emit(splitEvent); -manager = manager.removeAllListeners(splitEvent); -manager = manager.removeAllListeners(); -const bb: number = manager.listenerCount(splitEvent); -nodeEventEmitter = manager; - // manager exposes Event constants too const managerEventConsts: { [key: string]: SplitIO.Event } = manager.Event; splitEvent = manager.Event.SDK_READY; @@ -361,14 +319,6 @@ splitViewsAsync = asyncManager.splits(); // asyncManager implements ready promise. const asyncManagerReadyPromise: Promise = asyncManager.ready(); -// asyncManager implements methods from NodeJS.Events. Testing a few. -asyncManager = asyncManager.on(splitEvent, () => { }); -const aaa: boolean = asyncManager.emit(splitEvent); -asyncManager = asyncManager.removeAllListeners(splitEvent); -asyncManager = asyncManager.removeAllListeners(); -const bbb: number = asyncManager.listenerCount(splitEvent); -nodeEventEmitter = asyncManager; - // asyncManager exposes Event constants too const asyncManagerEventConsts: { [key: string]: SplitIO.Event } = asyncManager.Event; splitEvent = asyncManager.Event.SDK_READY; @@ -389,6 +339,7 @@ const MyImprListenerMap: SplitIO.IImpressionListener = { } }; +let impressionListener: SplitIO.IImpressionListener; impressionListener = MyImprListenerMap; impressionListener = new MyImprListener(); impressionListener.logImpression(impressionData); @@ -415,7 +366,7 @@ let attr: SplitIO.Attributes = { booleanAttribute: true, stringArrayAttribute: ['value1', 'value2'], numberArrayAttribute: [1, 2] -} +}; stored = browserClient.setAttributes(attr); let storedAttr: SplitIO.Attributes = browserClient.getAttributes(); @@ -430,188 +381,3 @@ BrowserSDK.UserConsent.setStatus(false); userConsent = BrowserSDK.UserConsent.Status.DECLINED; userConsent = BrowserSDK.UserConsent.Status.GRANTED; userConsent = BrowserSDK.UserConsent.Status.UNKNOWN; - -/**** Tests for fully crowded settings interfaces ****/ - -// Split filters -let splitFilters: SplitIO.SplitFilter[] = [{ type: 'byName', values: ['my_split_1', 'my_split_1'] }, { type: 'byPrefix', values: ['my_split', 'test_split_'] }] - -// Browser integrations -let fieldsObjectSample: UniversalAnalytics.FieldsObject = { hitType: 'event', eventAction: 'action' }; -let eventDataSample: SplitIO.EventData = { eventTypeId: 'someEventTypeId', value: 10, properties: {} } - -let googleAnalyticsToSplitConfig: SplitIO.IGoogleAnalyticsToSplitConfig = { - type: 'GOOGLE_ANALYTICS_TO_SPLIT', -}; -let splitToGoogleAnalyticsConfig: SplitIO.ISplitToGoogleAnalyticsConfig = { - type: 'SPLIT_TO_GOOGLE_ANALYTICS', -}; - -let customGoogleAnalyticsToSplitConfig: SplitIO.IGoogleAnalyticsToSplitConfig = { - type: 'GOOGLE_ANALYTICS_TO_SPLIT', - hits: false, - filter: function (model: UniversalAnalytics.Model): boolean { return true; }, - mapper: function (model: UniversalAnalytics.Model, defaultMapping: SplitIO.EventData): SplitIO.EventData { return eventDataSample; }, - prefix: 'PREFIX', - identities: [{ key: 'key1', trafficType: 'tt1' }, { key: 'key2', trafficType: 'tt2' }], - autoRequire: true -}; -let customSplitToGoogleAnalyticsConfig: SplitIO.ISplitToGoogleAnalyticsConfig = { - type: 'SPLIT_TO_GOOGLE_ANALYTICS', - events: false, - impressions: true, - filter: function (model: SplitIO.IntegrationData): boolean { return true; }, - mapper: function (model: SplitIO.IntegrationData, defaultMapping: UniversalAnalytics.FieldsObject): UniversalAnalytics.FieldsObject { return fieldsObjectSample; }, - trackerNames: ['t0', 'myTracker'], -} - -let fullBrowserSettings: SplitIO.IBrowserSettings = { - core: { - authorizationKey: 'asd', - key: 'asd', - trafficType: 'myTT', - labelsEnabled: false - }, - scheduler: { - featuresRefreshRate: 1, - impressionsRefreshRate: 1, - impressionsQueueSize: 1, - metricsRefreshRate: 1, - telemetryRefreshRate: 1, - segmentsRefreshRate: 1, - offlineRefreshRate: 1, - eventsPushRate: 1, - eventsQueueSize: 1, - pushRetryBackoffBase: 1 - }, - startup: { - readyTimeout: 1, - requestTimeoutBeforeReady: 1, - retriesOnFailureBeforeReady: 1, - eventsFirstPushWindow: 1 - }, - urls: { - sdk: 'https://asd.com/sdk', - events: 'https://asd.com/events', - auth: 'https://asd.com/auth', - streaming: 'https://asd.com/streaming', - telemetry: 'https://asd.com/telemetry' - }, - features: mockedFeaturesMap, - storage: { - type: 'LOCALSTORAGE', - prefix: 'PREFIX' - }, - impressionListener: impressionListener, - debug: true, - integrations: [googleAnalyticsToSplitConfig, splitToGoogleAnalyticsConfig, customGoogleAnalyticsToSplitConfig, customSplitToGoogleAnalyticsConfig], - streamingEnabled: true, - sync: { - splitFilters: splitFilters, - impressionsMode: 'DEBUG', - enabled: true - }, - userConsent: 'GRANTED' -}; -fullBrowserSettings.storage.type = 'MEMORY'; -fullBrowserSettings.integrations[0].type = 'GOOGLE_ANALYTICS_TO_SPLIT'; -fullBrowserSettings.userConsent = 'DECLINED'; -fullBrowserSettings.userConsent = 'UNKNOWN'; - -let fullNodeSettings: SplitIO.INodeSettings = { - core: { - authorizationKey: 'asd', - labelsEnabled: false, - IPAddressesEnabled: false - }, - scheduler: { - featuresRefreshRate: 1, - impressionsRefreshRate: 1, - impressionsQueueSize: 1, - metricsRefreshRate: 1, - telemetryRefreshRate: 1, - segmentsRefreshRate: 1, - offlineRefreshRate: 1, - eventsPushRate: 1, - eventsQueueSize: 1, - pushRetryBackoffBase: 1 - }, - startup: { - readyTimeout: 1, - requestTimeoutBeforeReady: 1, - retriesOnFailureBeforeReady: 1, - eventsFirstPushWindow: 1 - }, - urls: { - sdk: 'https://asd.com/sdk', - events: 'https://asd.com/events', - auth: 'https://asd.com/auth', - streaming: 'https://asd.com/streaming', - telemetry: 'https://asd.com/telemetry' - }, - features: mockedFeaturesPath, - storage: { - type: 'MEMORY' - }, - impressionListener: impressionListener, - mode: 'standalone', - debug: false, - streamingEnabled: false, - sync: { - splitFilters: splitFilters, - impressionsMode: 'OPTIMIZED', - enabled: true - } -}; -fullNodeSettings.storage.type = 'MEMORY'; -fullNodeSettings.mode = undefined; - -let fullAsyncSettings: SplitIO.INodeAsyncSettings = { - core: { - authorizationKey: 'asd', - labelsEnabled: false, - IPAddressesEnabled: false - }, - scheduler: { - featuresRefreshRate: 1, - impressionsRefreshRate: 1, - impressionsQueueSize: 1, - metricsRefreshRate: 1, - telemetryRefreshRate: 1, - segmentsRefreshRate: 1, - offlineRefreshRate: 1, - eventsPushRate: 1, - eventsQueueSize: 1 - }, - startup: { - readyTimeout: 1, - requestTimeoutBeforeReady: 1, - retriesOnFailureBeforeReady: 1 - }, - features: mockedFeaturesPath, - storage: { - type: 'REDIS', - options: { - url: 'url', - host: 'host', - port: 1234, - db: 0, - pass: 'pass', - connectionTimeout: 100, - operationTimeout: 100, - tls: { ca: ['ca'] } - }, - prefix: 'PREFIX' - }, - impressionListener: impressionListener, - mode: 'consumer', - debug: true, - sync: { - splitFilters: splitFilters - } -}; - -// debug property can be a log level -fullBrowserSettings.debug = 'ERROR'; -fullNodeSettings.debug = 'WARN'; -fullAsyncSettings.debug = 'INFO';