From 62c71c50d3fd81e283e1a1044ee2d9744b6a3d3a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jan 2025 03:11:03 +0000 Subject: [PATCH 1/4] Updated License Year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index c022e92..df08de3 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright © 2024 Split Software, Inc. +Copyright © 2025 Split Software, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 7ccc80a441379a82fe3e836942e2b4b3311791e1 Mon Sep 17 00:00:00 2001 From: Melina Urruchua Date: Thu, 9 Jan 2025 10:56:15 -0300 Subject: [PATCH 2/4] Bump artifact actions --- .github/workflows/ci-cd.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index f55585a..c94916b 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -48,7 +48,7 @@ jobs: - name: Store assets if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/development' || github.ref == 'refs/heads/main') }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: assets path: umd/ @@ -74,7 +74,7 @@ jobs: steps: - name: Download assets - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: assets path: umd @@ -84,7 +84,7 @@ jobs: working-directory: umd - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v1-node16 + uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::${{ matrix.account_id }}:role/gha-public-assets-role aws-region: us-east-1 @@ -117,7 +117,7 @@ jobs: steps: - name: Download assets - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: assets path: umd @@ -127,7 +127,7 @@ jobs: working-directory: umd - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v1-node16 + uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::${{ matrix.account_id }}:role/gha-public-assets-role aws-region: us-east-1 From 27894b05ea0a19ec74d32c30e6f258a287668608 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 17 Jan 2025 17:33:43 -0300 Subject: [PATCH 3/4] Stable version --- CHANGES.txt | 4 ++++ package-lock.json | 30 +++++++++++++++--------------- package.json | 4 ++-- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index aa54aa4..f267b97 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,7 @@ +1.1.0 (January 17, 2025) + - Added support for the new impressions tracking toggle available on feature flags, both respecting the setting and including the new field being returned on `SplitView` type objects. Read more in our docs. + - Bugfixing - Updated @splitsoftware/splitio-commons package to version 2.1.0, which properly handles rejected promises when using targeting rules with segment matchers in consumer modes (e.g., Redis and Pluggable storages). + 1.0.1 (November 11, 2024) - Bugfixing - Revert removal of TypeScript `SplitIO` namespace at `/types/splitio.d.ts` to allow explicit imports of types from the Browser SDK package. E.g., `import type { IClientSideSettings } from '@splitsoftware/splitio-browserjs/types/splitio';`. diff --git a/package-lock.json b/package-lock.json index 5485e80..9b030df 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@splitsoftware/splitio-browserjs", - "version": "1.0.1", + "version": "1.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio-browserjs", - "version": "1.0.1", + "version": "1.1.0", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.0.0", + "@splitsoftware/splitio-commons": "2.1.0", "tslib": "^2.3.1", "unfetch": "^4.2.0" }, @@ -1542,9 +1542,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0.tgz", - "integrity": "sha512-Sz4+vFacl29xw3451z9IUgB4zBFKUWZdCnmOB0DDXA803YKPqjXphdAwN6nV+1vsX9pXV/OS6UaNC4oUICa6PA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.0.tgz", + "integrity": "sha512-7SJRBia0Pi72s76drH8kG2cVnCqkjMHMJQWJSFnG+rE/UOx9AROmuviOkY6tv6qYPJFqFQQGHGX6lXjxZhYzkw==", "dependencies": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" @@ -3039,9 +3039,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "dependencies": { "path-key": "^3.1.0", @@ -10688,9 +10688,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0.tgz", - "integrity": "sha512-Sz4+vFacl29xw3451z9IUgB4zBFKUWZdCnmOB0DDXA803YKPqjXphdAwN6nV+1vsX9pXV/OS6UaNC4oUICa6PA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.1.0.tgz", + "integrity": "sha512-7SJRBia0Pi72s76drH8kG2cVnCqkjMHMJQWJSFnG+rE/UOx9AROmuviOkY6tv6qYPJFqFQQGHGX6lXjxZhYzkw==", "requires": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" @@ -11788,9 +11788,9 @@ } }, "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "requires": { "path-key": "^3.1.0", diff --git a/package.json b/package.json index 322a961..6213ced 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-browserjs", - "version": "1.0.1", + "version": "1.1.0", "description": "Split SDK for JavaScript on Browser", "main": "cjs/index.js", "module": "esm/index.js", @@ -59,7 +59,7 @@ "bugs": "https://github.com/splitio/javascript-browser-client/issues", "homepage": "https://github.com/splitio/javascript-browser-client#readme", "dependencies": { - "@splitsoftware/splitio-commons": "2.0.0", + "@splitsoftware/splitio-commons": "2.1.0", "tslib": "^2.3.1", "unfetch": "^4.2.0" }, From b43c8f0c9bd000b1b1f7708ed3404760f81144c5 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 17 Jan 2025 18:31:18 -0300 Subject: [PATCH 4/4] Update tests --- .../impressions-listener.spec.js | 8 ++- .../browserSuites/impressions.debug.spec.js | 66 ++++++++++--------- .../browserSuites/impressions.spec.js | 41 ++++++++---- src/__tests__/browserSuites/manager.spec.js | 3 +- src/__tests__/browserSuites/telemetry.spec.js | 4 +- .../consumer/browser_consumer.spec.js | 15 +++-- .../consumer/browser_consumer_partial.spec.js | 28 ++++++-- src/__tests__/consumer/wrapper-commands.js | 3 +- .../mocks/splitchanges.since.-1.json | 41 ++++++++++++ src/__tests__/offline/browser.spec.js | 6 +- src/settings/defaults.ts | 2 +- ts-tests/index.ts | 3 +- 12 files changed, 149 insertions(+), 71 deletions(-) diff --git a/src/__tests__/browserSuites/impressions-listener.spec.js b/src/__tests__/browserSuites/impressions-listener.spec.js index 299daca..ca47995 100644 --- a/src/__tests__/browserSuites/impressions-listener.spec.js +++ b/src/__tests__/browserSuites/impressions-listener.spec.js @@ -57,17 +57,21 @@ export default function (assert) { keyName: 'marcio@split.io', treatment: 'no', bucketingKey: 'impr_bucketing_2', - label: 'default rule' + label: 'default rule', + pt: undefined }; assert.equal(listener.logImpression.callCount, 4, 'Impression listener logImpression method should be called after we call client.getTreatment, once per each impression generated.'); - assert.true(listener.logImpression.getCall(0).calledWithMatch({ + assert.true(listener.logImpression.getCall(0).calledWithExactly({ impression: { feature: 'hierarchical_splits_test', keyName: 'nicolas@split.io', treatment: 'on', + time: listener.logImpression.getCall(0).args[0].impression.time, bucketingKey: undefined, label: 'expected label', + changeNumber: 2828282828, + pt: undefined }, attributes: undefined, ...metaData diff --git a/src/__tests__/browserSuites/impressions.debug.spec.js b/src/__tests__/browserSuites/impressions.debug.spec.js index 18d875b..5f90b70 100644 --- a/src/__tests__/browserSuites/impressions.debug.spec.js +++ b/src/__tests__/browserSuites/impressions.debug.spec.js @@ -4,6 +4,7 @@ import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json'; import membershipsFacundo from '../mocks/memberships.facundo@split.io.json'; import { DEBUG } from '@splitsoftware/splitio-commons/src/utils/constants'; +import { truncateTimeFrame } from '@splitsoftware/splitio-commons/src/utils/time'; import { url } from '../testUtils'; const baseUrls = { @@ -19,6 +20,8 @@ const settings = settingsFactory({ streamingEnabled: false }); +let truncatedTimeFrame; + export default function (fetchMock, assert) { // Mocking this specific route to make sure we only get the items we want to test from the handlers. fetchMock.getOnce(url(settings, '/splitChanges?s=1.2&since=-1'), { status: 200, body: splitChangesMock1 }); @@ -47,41 +50,21 @@ export default function (fetchMock, assert) { }); const client = splitio.client(); - const assertPayload = req => { - const resp = JSON.parse(req.body); - - assert.equal(resp.length, 1, 'We performed three evaluations so we should have 1 impressions type'); - - const alwaysOnWithConfigImpr = resp.filter(e => e.f === 'split_with_config')[0]; - - assert.equal(alwaysOnWithConfigImpr.i.length, 3); - - function validateImpressionData(output, expected) { - assert.equal(output.k, expected.keyName, 'Present impressions should have the correct key.'); - assert.equal(output.b, expected.bucketingKey, 'Present impressions should have the correct bucketingKey.'); - assert.equal(output.t, expected.treatment, 'Present impressions should have the correct treatment.'); - assert.equal(output.r, expected.label, 'Present impressions should have the correct label.'); - assert.equal(output.c, expected.changeNumber, 'Present impressions should have the correct changeNumber.'); - assert.equal(output.pt, expected.pt, 'Present impressions should have the correct previousTime.'); - } - - validateImpressionData(alwaysOnWithConfigImpr.i[0], { - keyName: 'facundo@split.io', label: 'another expected label', treatment: 'o.n', - bucketingKey: undefined, changeNumber: 828282828282, pt: undefined - }); - validateImpressionData(alwaysOnWithConfigImpr.i[1], { - keyName: 'facundo@split.io', label: 'another expected label', treatment: 'o.n', - bucketingKey: undefined, changeNumber: 828282828282, pt: alwaysOnWithConfigImpr.i[0].m - }); - validateImpressionData(alwaysOnWithConfigImpr.i[2], { - keyName: 'facundo@split.io', label: 'another expected label', treatment: 'o.n', - bucketingKey: undefined, changeNumber: 828282828282, pt: alwaysOnWithConfigImpr.i[1].m - }); - }; fetchMock.postOnce(url(settings, '/testImpressions/bulk'), (url, req) => { assert.equal(req.headers.SplitSDKImpressionsMode, DEBUG); - assertPayload(req); + const data = JSON.parse(req.body); + + assert.deepEqual(data, [{ + f: 'split_with_config', + i: [{ + k: 'facundo@split.io', t: 'o.n', m: data[0].i[0].m, c: 828282828282, r: 'another expected label' + }, { + k: 'facundo@split.io', t: 'o.n', m: data[0].i[1].m, c: 828282828282, r: 'another expected label', pt: data[0].i[0].m, + }, { + k: 'facundo@split.io', t: 'o.n', m: data[0].i[2].m, c: 828282828282, r: 'another expected label', pt: data[0].i[1].m + }] + }]); client.destroy().then(() => { assert.end(); @@ -90,9 +73,28 @@ export default function (fetchMock, assert) { return 200; }); + fetchMock.postOnce(url(settings, '/testImpressions/count'), (url, opts) => { + assert.deepEqual(JSON.parse(opts.body), { + pf: [{ f: 'always_on_track_impressions_false', m: truncatedTimeFrame, rc: 1 }] + }, 'We should generate impression count for the feature with track impressions disabled.'); + + return 200; + }); + + fetchMock.postOnce(url(settings, '/v1/keys/cs'), (url, opts) => { + assert.deepEqual(JSON.parse(opts.body), { + keys: [{ fs: ['always_on_track_impressions_false'], k: 'facundo@split.io' }] + }, 'We should track unique keys for the feature with track impressions disabled.'); + + return 200; + }); + client.ready().then(() => { + truncatedTimeFrame = truncateTimeFrame(Date.now()); + client.getTreatment('split_with_config'); client.getTreatment('split_with_config'); client.getTreatment('split_with_config'); + assert.equal(client.getTreatment('always_on_track_impressions_false'), 'on'); }); } diff --git a/src/__tests__/browserSuites/impressions.spec.js b/src/__tests__/browserSuites/impressions.spec.js index aa4cff4..33e6010 100644 --- a/src/__tests__/browserSuites/impressions.spec.js +++ b/src/__tests__/browserSuites/impressions.spec.js @@ -49,17 +49,19 @@ export default function (fetchMock, assert) { const assertPayload = req => { const resp = JSON.parse(req.body); - assert.equal(resp.length, 2, 'We performed three evaluations so we should have 2 impressions type'); + assert.equal(resp.length, 2, 'We performed evaluations for 3 features, but one with `impressionsDisabled` true, so we should have 2 items total'); const dependencyChildImpr = resp.filter(e => e.f === 'hierarchical_splits_test')[0]; - const alwaysOnWithConfigImpr = resp.filter(e => e.f === 'split_with_config')[0]; + const splitWithConfigImpr = resp.filter(e => e.f === 'split_with_config')[0]; + const alwaysOnWithTrackImpressionsFalse = resp.filter(e => e.f === 'always_on_track_impressions_false'); assert.true(dependencyChildImpr, 'Split we wanted to evaluate should be present on the impressions.'); assert.false(resp.some(e => e.f === 'hierarchical_dep_always_on'), 'Parent split evaluations should not result in impressions.'); assert.false(resp.some(e => e.f === 'hierarchical_dep_hierarchical'), 'No matter how deep is the chain.'); - assert.true(alwaysOnWithConfigImpr, 'Split evaluated with config should have generated an impression too.'); - assert.false(Object.prototype.hasOwnProperty.call(alwaysOnWithConfigImpr.i[0], 'configuration'), 'Impressions do not change with configuration evaluations.'); - assert.false(Object.prototype.hasOwnProperty.call(alwaysOnWithConfigImpr.i[0], 'config'), 'Impressions do not change with configuration evaluations.'); + assert.true(splitWithConfigImpr, 'Split evaluated with config should have generated an impression too.'); + assert.false(Object.prototype.hasOwnProperty.call(splitWithConfigImpr.i[0], 'configuration'), 'Impressions do not change with configuration evaluations.'); + assert.false(Object.prototype.hasOwnProperty.call(splitWithConfigImpr.i[0], 'config'), 'Impressions do not change with configuration evaluations.'); + assert.equal(alwaysOnWithTrackImpressionsFalse.length, 0); const { k, @@ -94,18 +96,26 @@ export default function (fetchMock, assert) { fetchMock.postOnce(url(settings, '/testImpressions/count'), (url, opts) => { const data = JSON.parse(opts.body); - assert.equal(data.pf.length, 1, 'We should generate impressions count for one feature.'); + assert.equal(data.pf.length, 2, 'We should generate impressions count for 2 features.'); // finding these validate the feature names collection too - const dependencyChildImpr = data.pf.filter(e => e.f === 'hierarchical_splits_test')[0]; - const alwaysOnWithConfigImpr = data.pf.filter(e => e.f === 'split_with_config')[0]; + const splitWithConfigImpr = data.pf.filter(e => e.f === 'split_with_config')[0]; + const alwaysOnWithTrackImpressionsFalse = data.pf.filter(e => e.f === 'always_on_track_impressions_false')[0]; - assert.equal(dependencyChildImpr.rc, 1); - assert.equal(typeof dependencyChildImpr.m, 'number'); - assert.equal(dependencyChildImpr.m, truncatedTimeFrame); - assert.equal(alwaysOnWithConfigImpr.rc, 3); - assert.equal(typeof alwaysOnWithConfigImpr.m, 'number'); - assert.equal(alwaysOnWithConfigImpr.m, truncatedTimeFrame); + assert.equal(splitWithConfigImpr.rc, 2); + assert.equal(typeof splitWithConfigImpr.m, 'number'); + assert.equal(splitWithConfigImpr.m, truncatedTimeFrame); + assert.equal(alwaysOnWithTrackImpressionsFalse.rc, 1); + assert.equal(typeof alwaysOnWithTrackImpressionsFalse.m, 'number'); + assert.equal(alwaysOnWithTrackImpressionsFalse.m, truncatedTimeFrame); + + return 200; + }); + + fetchMock.postOnce(url(settings, '/v1/keys/cs'), (url, opts) => { + assert.deepEqual(JSON.parse(opts.body), { + keys: [{ fs: [ 'always_on_track_impressions_false' ], k: 'facundo@split.io' }] + }, 'We should only track unique keys for features flags with track impressions disabled.'); return 200; }); @@ -120,5 +130,8 @@ export default function (fetchMock, assert) { }, 'We should get an evaluation as always.'); client.getTreatmentWithConfig('split_with_config'); client.getTreatmentWithConfig('split_with_config'); + + // Impression should not be tracked + assert.equal(client.getTreatment('always_on_track_impressions_false'), 'on'); }); } diff --git a/src/__tests__/browserSuites/manager.spec.js b/src/__tests__/browserSuites/manager.spec.js index 81143c9..3f6b0c5 100644 --- a/src/__tests__/browserSuites/manager.spec.js +++ b/src/__tests__/browserSuites/manager.spec.js @@ -41,7 +41,8 @@ export default async function (settings, fetchMock, assert) { 'treatments': map(mockSplits.splits[index].conditions[0].partitions, partition => partition.treatment), 'configs': mockSplits.splits[index].configurations || {}, 'sets': mockSplits.splits[index].sets, - 'defaultTreatment': mockSplits.splits[index].defaultTreatment + 'defaultTreatment': mockSplits.splits[index].defaultTreatment, + 'impressionsDisabled': false }); assert.equal(manager.split('non_existent'), null, 'Trying to get a manager.split() of a Split that does not exist returns null.'); diff --git a/src/__tests__/browserSuites/telemetry.spec.js b/src/__tests__/browserSuites/telemetry.spec.js index bef7e77..4e91211 100644 --- a/src/__tests__/browserSuites/telemetry.spec.js +++ b/src/__tests__/browserSuites/telemetry.spec.js @@ -71,7 +71,7 @@ export default async function telemetryBrowserSuite(fetchMock, assert) { // @TODO check if iDe value is correct assert.deepEqual(data, { - mE: {}, hE: { sp: { 500: 1 }, ms: { 500: 1 } }, tR: 0, aR: 0, iQ: 4, iDe: 1, iDr: 0, spC: 32, seC: 1, skC: 1, eQ: 1, eD: 0, sE: [], t: [], ufs: {} + mE: {}, hE: { sp: { 500: 1 }, ms: { 500: 1 } }, tR: 0, aR: 0, iQ: 4, iDe: 1, iDr: 0, spC: 33, seC: 1, skC: 1, eQ: 1, eD: 0, sE: [], t: [], ufs: {} }, 'metrics/usage JSON payload should be the expected'); finish.next(); @@ -91,7 +91,7 @@ export default async function telemetryBrowserSuite(fetchMock, assert) { // @TODO check if iDe value is correct assert.deepEqual(data, { mL: {}, mE: {}, hE: {}, hL: {}, // errors and latencies were popped - tR: 0, aR: 0, iQ: 4, iDe: 1, iDr: 0, spC: 32, seC: 1, skC: 1, eQ: 1, eD: 0, sE: [], t: [], ufs: {} + tR: 0, aR: 0, iQ: 4, iDe: 1, iDr: 0, spC: 33, seC: 1, skC: 1, eQ: 1, eD: 0, sE: [], t: [], ufs: {} }, '2nd metrics/usage JSON payload should be the expected'); return 200; }); diff --git a/src/__tests__/consumer/browser_consumer.spec.js b/src/__tests__/consumer/browser_consumer.spec.js index a24f53c..1c90f3a 100644 --- a/src/__tests__/consumer/browser_consumer.spec.js +++ b/src/__tests__/consumer/browser_consumer.spec.js @@ -10,7 +10,7 @@ import { version } from '../../../package.json'; 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: {}, sets: [], defaultTreatment: 'off' }; +const expectedSplitView = { name: 'hierarchical_splits_testing_on', trafficType: 'user', killed: false, changeNumber: 1487277320548, treatments: ['on', 'off'], configs: {}, sets: [], defaultTreatment: 'off', impressionsDisabled: false }; const wrapperPrefix = 'PLUGGABLE_STORAGE_UT'; const wrapperInstance = inMemoryWrapperFactory(); @@ -111,11 +111,12 @@ tape('Browser Consumer mode with pluggable storage', function (t) { assert.equal(await client.getTreatment('always-on'), 'on', 'Evaluations using pluggable storage should be correct.'); - // Below splits were added manually. + // Below feature flags were added manually. // They are all_keys (always evaluate to on) which depend from always-on split. the _on/off is what treatment they are expecting there. assert.equal(await client.getTreatment('hierarchical_splits_testing_on'), 'on', 'Evaluations using pluggable storage should be correct.'); assert.equal(await client.getTreatment('hierarchical_splits_testing_off'), 'off', 'Evaluations using pluggable storage should be correct.'); assert.equal(await client.getTreatment('hierarchical_splits_testing_on_negated'), 'off', 'Evaluations using pluggable storage should be correct.'); + assert.equal(await client.getTreatment('always-on-impressions-disabled-true'), 'on', 'Evaluations using pluggable storage should be correct.'); assert.equal(typeof client.track('user', 'test.event', 18).then, 'function', 'Track calls should always return a promise on Consumer mode.'); assert.equal(typeof client.track().then, 'function', 'Track calls should always return a promise on Consumer mode, even when parameters are incorrect.'); @@ -125,11 +126,11 @@ tape('Browser Consumer mode with pluggable storage', function (t) { // Manager methods const splitNames = await manager.names(); - assert.equal(splitNames.length, 25, 'manager `names` method returns the list of split names asynchronously'); + assert.equal(splitNames.length, 26, 'manager `names` method returns the list of split names asynchronously'); assert.equal(splitNames.indexOf(expectedSplitName) > -1, true, 'list of split names should contain expected splits'); assert.deepEqual(await manager.split(expectedSplitName), expectedSplitView, 'manager `split` method returns the split view of the given split name asynchronously'); const splitViews = await manager.splits(); - assert.equal(splitViews.length, 25, 'manager `splits` method returns the list of split views asynchronously'); + assert.equal(splitViews.length, 26, 'manager `splits` method returns the list of split views asynchronously'); assert.deepEqual(splitViews.find(splitView => splitView.name === expectedSplitName), expectedSplitView, 'manager `split` method returns the split view of the given split name asynchronously'); // New shared client created @@ -164,7 +165,7 @@ tape('Browser Consumer mode with pluggable storage', function (t) { // Assert impressionsListener setTimeout(() => { - assert.equal(impressions.length, TOTAL_RAW_IMPRESSIONS, 'Each evaluation has its corresponding impression'); + assert.equal(impressions.length, TOTAL_RAW_IMPRESSIONS + 1 /* One evaluation with impressionsDisabled true */, 'Each evaluation has its corresponding impression'); assert.equal(impressions[0].impression.label, SDK_NOT_READY, 'The first impression is control with label "sdk not ready"'); assert.end(); @@ -251,7 +252,7 @@ tape('Browser Consumer mode with pluggable storage', function (t) { assert.equal(await client.getTreatment('always-on'), 'on', 'Evaluations using pluggable storage should be correct.'); - // Below splits were added manually. + // Below feature flags were added manually. // They are all_keys (always evaluate to on) which depend from always-on split. the _on/off is what treatment they are expecting there. assert.equal(await client.getTreatment('hierarchical_splits_testing_on'), 'on', 'Evaluations using pluggable storage should be correct.'); assert.equal(await client.getTreatment('hierarchical_splits_testing_off'), 'off', 'Evaluations using pluggable storage should be correct.'); @@ -383,7 +384,7 @@ tape('Browser Consumer mode with pluggable storage', function (t) { assert.equal(await client.getTreatment('always-on'), 'on', 'Evaluations using pluggable storage should be correct.'); - // Below splits were added manually. + // Below feature flags were added manually. // They are all_keys (always evaluate to on) which depend from always-on split. the _on/off is what treatment they are expecting there. assert.equal(await client.getTreatment('hierarchical_splits_testing_on'), 'on', 'Evaluations using pluggable storage should be correct.'); assert.equal(await client.getTreatment('hierarchical_splits_testing_off'), 'off', 'Evaluations using pluggable storage should be correct.'); diff --git a/src/__tests__/consumer/browser_consumer_partial.spec.js b/src/__tests__/consumer/browser_consumer_partial.spec.js index bca4eff..cb35cef 100644 --- a/src/__tests__/consumer/browser_consumer_partial.spec.js +++ b/src/__tests__/consumer/browser_consumer_partial.spec.js @@ -10,7 +10,7 @@ import { applyOperations } from './wrapper-commands'; 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: {}, sets: [], defaultTreatment: 'off' }; +const expectedSplitView = { name: 'hierarchical_splits_testing_on', trafficType: 'user', killed: false, changeNumber: 1487277320548, treatments: ['on', 'off'], configs: {}, sets: [], defaultTreatment: 'off', impressionsDisabled: false }; const wrapperPrefix = 'PLUGGABLE_STORAGE_UT'; const wrapperInstance = inMemoryWrapperFactory(); @@ -52,6 +52,19 @@ tape('Browser Consumer Partial mode with pluggable storage', function (t) { return 200; }); + fetchMock.postOnce(url(config, '/v1/keys/cs'), (url, req) => { + const data = JSON.parse(req.body); + + assert.deepEqual(data, { + keys: [{ + k: 'UT_Segment_member', + fs: ['always-on-impressions-disabled-true'] + }] + }, 'Unique keys for the evaluation with impressions disabled true.'); + + return 200; + }); + fetchMock.postOnce(url(config, '/testImpressions/count'), 200); fetchMock.postOnce(url(config, '/v1/metrics/config'), 200); fetchMock.postOnce(url(config, '/v1/metrics/usage'), 200); @@ -133,11 +146,12 @@ tape('Browser Consumer Partial mode with pluggable storage', function (t) { assert.equal(await client.getTreatment('always-on'), 'on', 'Evaluations using pluggable storage should be correct.'); - // Below splits were added manually. + // Below feature flags were added manually. // They are all_keys (always evaluate to on) which depend from always-on split. the _on/off is what treatment they are expecting there. assert.equal(await client.getTreatment('hierarchical_splits_testing_on'), 'on', 'Evaluations using pluggable storage should be correct.'); assert.equal(await client.getTreatment('hierarchical_splits_testing_off'), 'off', 'Evaluations using pluggable storage should be correct.'); assert.equal(await client.getTreatment('hierarchical_splits_testing_on_negated'), 'off', 'Evaluations using pluggable storage should be correct.'); + assert.equal(await client.getTreatment('always-on-impressions-disabled-true'), 'on', 'Evaluations using pluggable storage should be correct.'); assert.equal(typeof client.track('user', 'test.event', 18).then, 'function', 'Track calls should always return a promise on Consumer mode.'); assert.equal(typeof client.track().then, 'function', 'Track calls should always return a promise on Consumer mode, even when parameters are incorrect.'); @@ -147,11 +161,11 @@ tape('Browser Consumer Partial mode with pluggable storage', function (t) { // Manager methods const splitNames = await manager.names(); - assert.equal(splitNames.length, 25, 'manager `names` method returns the list of split names asynchronously'); + assert.equal(splitNames.length, 26, 'manager `names` method returns the list of split names asynchronously'); assert.equal(splitNames.indexOf(expectedSplitName) > -1, true, 'list of split names should contain expected splits'); assert.deepEqual(await manager.split(expectedSplitName), expectedSplitView, 'manager `split` method returns the split view of the given split name asynchronously'); const splitViews = await manager.splits(); - assert.equal(splitViews.length, 25, 'manager `splits` method returns the list of split views asynchronously'); + assert.equal(splitViews.length, 26, 'manager `splits` method returns the list of split views asynchronously'); assert.deepEqual(splitViews.find(splitView => splitView.name === expectedSplitName), expectedSplitView, 'manager `split` method returns the split view of the given split name asynchronously'); // New shared client created @@ -169,13 +183,13 @@ tape('Browser Consumer Partial mode with pluggable storage', function (t) { assert.equal(fetchMock.calls().length, 1, 'fetch has been called once for posting telemetry config stats'); await client.destroy(); - assert.equal(fetchMock.calls().length, 5, 'fetch has been called 5 times after main client is destroyed, for posting events, impressions, impression counts, telemetry config and usage stats'); + assert.equal(fetchMock.calls().length, 6, 'fetch has been called 6 times after main client is destroyed, for posting events, impressions, impression counts, unique keys, telemetry config and usage stats'); assert.equal(disconnectSpy.callCount, 1, 'Wrapper disconnect method should be called only once, when the main client is destroyed'); // Assert impressionsListener setTimeout(() => { - assert.equal(impressions.length, TOTAL_RAW_IMPRESSIONS, 'Each evaluation has its corresponding impression'); + assert.equal(impressions.length, TOTAL_RAW_IMPRESSIONS + 1 /* One evaluation with impressionsDisabled true */, 'Each evaluation has its corresponding impression'); assert.equal(impressions[0].impression.label, SDK_NOT_READY, 'The first impression is control with label "sdk not ready"'); assert.end(); @@ -291,7 +305,7 @@ tape('Browser Consumer Partial mode with pluggable storage', function (t) { assert.equal(await client.getTreatment('always-on'), 'on', 'Evaluations using pluggable storage should be correct.'); - // Below splits were added manually. + // Below feature flags were added manually. // They are all_keys (always evaluate to on) which depend from always-on split. the _on/off is what treatment they are expecting there. assert.equal(await client.getTreatment('hierarchical_splits_testing_on'), 'on', 'Evaluations using pluggable storage should be correct.'); assert.equal(await client.getTreatment('hierarchical_splits_testing_off'), 'off', 'Evaluations using pluggable storage should be correct.'); diff --git a/src/__tests__/consumer/wrapper-commands.js b/src/__tests__/consumer/wrapper-commands.js index b0398c5..f7095a3 100644 --- a/src/__tests__/consumer/wrapper-commands.js +++ b/src/__tests__/consumer/wrapper-commands.js @@ -28,7 +28,7 @@ const OPERATIONS = [ ['set', 'PLUGGABLE_STORAGE_UT.SPLITIO.split.always-on', '{"changeNumber":1487277320548,"trafficTypeName":"user","name":"always-on","seed":1684183541,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}'], ['set', 'PLUGGABLE_STORAGE_UT.SPLITIO.split.always-o.n-with-config', '{"changeNumber":1487277320548,"trafficTypeName":"user","name":"always-o.n-with-config","seed":1684183541,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"o.n","size":100},{"treatment":"off","size":0}],"label":"in segment all"}],"configurations":{"o.n":"{\\"color\\":\\"brown\\"}"}}'], ['set', 'PLUGGABLE_STORAGE_UT.SPLITIO.split.hierarchical_splits_testing_off', '{"changeNumber":1487277320548,"trafficTypeName":"user","name":"hierarchical_splits_testing_off","seed":1684183541,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}},{"keySelector":{"trafficType":"user","attribute":""},"dependencyMatcherData":{"split":"always-on","treatments":["off"]},"matcherType":"IN_SPLIT_TREATMENT","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":null,"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}'], - ['set', 'PLUGGABLE_STORAGE_UT.SPLITIO.split.hierarchical_splits_testing_on', '{"changeNumber":1487277320548,"trafficTypeName":"user","name":"hierarchical_splits_testing_on","seed":1684183541,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}},{"keySelector":{"trafficType":"user","attribute":""},"dependencyMatcherData":{"split":"always-on","treatments":["on"]},"matcherType":"IN_SPLIT_TREATMENT","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":null,"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}'], + ['set', 'PLUGGABLE_STORAGE_UT.SPLITIO.split.hierarchical_splits_testing_on', '{"changeNumber":1487277320548,"trafficTypeName":"user","name":"hierarchical_splits_testing_on","impressionsDisabled":false,"seed":1684183541,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}},{"keySelector":{"trafficType":"user","attribute":""},"dependencyMatcherData":{"split":"always-on","treatments":["on"]},"matcherType":"IN_SPLIT_TREATMENT","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":null,"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}'], ['set', 'PLUGGABLE_STORAGE_UT.SPLITIO.split.hierarchical_splits_testing_on_negated', '{"changeNumber":1487277320548,"trafficTypeName":"user","name":"hierarchical_splits_testing_on","seed":1684183541,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":true,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}},{"keySelector":{"trafficType":"user","attribute":""},"dependencyMatcherData":{"split":"always-on","treatments":["on"]},"matcherType":"IN_SPLIT_TREATMENT","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":null,"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}'], ['set', 'PLUGGABLE_STORAGE_UT.SPLITIO.split.labels', '{"changeNumber":1492023661334,"trafficTypeName":"user","name":"labels","seed":-1240661267,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}},{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"IN_SEGMENT","negate":false,"userDefinedSegmentMatcherData":{"segmentName":"demo"},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}},{"keySelector":{"trafficType":"user","attribute":"n"},"matcherType":"EQUAL_TO","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"NUMBER","value":123},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":0},{"treatment":"off","size":100}],"label":"in segment all and in segment demo and n = 123"}]}'], ['set', 'PLUGGABLE_STORAGE_UT.SPLITIO.split.nico_not', '{"changeNumber":1489412422181,"trafficTypeName":"user","name":"nico_not","seed":-788702424,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"IN_SEGMENT","negate":false,"userDefinedSegmentMatcherData":{"segmentName":"qa"},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":0},{"treatment":"off","size":100}],"label":"in segment qa"}]}'], @@ -46,6 +46,7 @@ const OPERATIONS = [ ['set', 'PLUGGABLE_STORAGE_UT.SPLITIO.split.testing_traffic_types', '{"changeNumber":1490974465415,"trafficTypeName":"machine","name":"testing_traffic_types","seed":475616886,"status":"ACTIVE","killed":false,"defaultTreatment":"on","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"","attribute":""},"matcherType":"WHITELIST","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":["sarasa"]},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100}],"label":"whitelisted"},{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"","attribute":""},"matcherType":"WHITELIST","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":["excluded"]},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"off","size":100}],"label":"whitelisted"},{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}},{"keySelector":{"trafficType":"machine","attribute":""},"matcherType":"IN_SEGMENT","negate":false,"userDefinedSegmentMatcherData":{"segmentName":"testing_traffic_type"},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":0},{"treatment":"off","size":100}],"label":"in segment all and in segment testing_traffic_type"}]}'], ['set', 'PLUGGABLE_STORAGE_UT.SPLITIO.split.traffic_allocation_testing', '{"changeNumber":1490974123779,"trafficTypeName":"user","name":"traffic_allocation_testing","seed":1716284102,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}'], ['set', 'PLUGGABLE_STORAGE_UT.SPLITIO.splits.till', '1492723024413'], + ['set', 'PLUGGABLE_STORAGE_UT.SPLITIO.split.always-on-impressions-disabled-true', '{"changeNumber":1487277320548,"trafficTypeName":"user","name":"always-on-impressions-disabled-true","impressionsDisabled":true,"seed":1684183541,"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}'] ]; export const OPERATIONS_FLAG_SETS = [ diff --git a/src/__tests__/mocks/splitchanges.since.-1.json b/src/__tests__/mocks/splitchanges.since.-1.json index ee21cf9..372b030 100644 --- a/src/__tests__/mocks/splitchanges.since.-1.json +++ b/src/__tests__/mocks/splitchanges.since.-1.json @@ -1265,6 +1265,7 @@ "trafficTypeId": null, "trafficTypeName": null, "name": "hierarchical_splits_test", + "impressionsDisabled": false, "seed": 1276793945, "changeNumber": 2828282828, "status": "ACTIVE", @@ -1381,6 +1382,45 @@ } ] }, + { + "orgId": null, + "environment": null, + "trafficTypeId": null, + "trafficTypeName": null, + "name": "always_on_track_impressions_false", + "impressionsDisabled": true, + "seed": -790401604, + "status": "ACTIVE", + "killed": false, + "defaultTreatment": "off", + "conditions": [ + { + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user", + "attribute": null + }, + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 100 + } + ] + } + ] + }, { "orgId": null, "environment": null, @@ -1426,6 +1466,7 @@ { "trafficTypeName": null, "name": "split_with_config", + "impressionsDisabled": false, "algo": 2, "seed": -1222652064, "trafficAllocation": 100, diff --git a/src/__tests__/offline/browser.spec.js b/src/__tests__/offline/browser.spec.js index 6b2d981..dcca73c 100644 --- a/src/__tests__/offline/browser.spec.js +++ b/src/__tests__/offline/browser.spec.js @@ -178,10 +178,10 @@ tape('Browser offline mode', function (assert) { // Manager tests const expectedSplitView1 = { - name: 'testing_split', trafficType: 'localhost', killed: false, changeNumber: 0, treatments: ['on'], configs: {}, sets: [], defaultTreatment: 'control' + name: 'testing_split', trafficType: 'localhost', killed: false, changeNumber: 0, treatments: ['on'], configs: {}, sets: [], defaultTreatment: 'control', impressionsDisabled: false }; const expectedSplitView2 = { - name: 'testing_split_with_config', trafficType: 'localhost', killed: false, changeNumber: 0, treatments: ['off'], configs: { off: '{ "color": "blue" }' }, sets: [], defaultTreatment: 'control' + name: 'testing_split_with_config', trafficType: 'localhost', killed: false, changeNumber: 0, treatments: ['off'], configs: { off: '{ "color": "blue" }' }, sets: [], defaultTreatment: 'control', impressionsDisabled: false }; assert.deepEqual(manager.names(), ['testing_split', 'testing_split_with_config']); assert.deepEqual(manager.split('testing_split'), expectedSplitView1); @@ -292,7 +292,7 @@ tape('Browser offline mode', function (assert) { // Manager tests const expectedSplitView3 = { - name: 'testing_split_with_config', trafficType: 'localhost', killed: false, changeNumber: 0, treatments: ['nope'], configs: {}, sets: [], defaultTreatment: 'control' + name: 'testing_split_with_config', trafficType: 'localhost', killed: false, changeNumber: 0, treatments: ['nope'], configs: {}, sets: [], defaultTreatment: 'control', impressionsDisabled: false }; assert.deepEqual(manager.names(), ['testing_split', 'testing_split_2', 'testing_split_3', 'testing_split_with_config']); assert.deepEqual(manager.split('testing_split'), expectedSplitView1); diff --git a/src/settings/defaults.ts b/src/settings/defaults.ts index 7d76258..be04ade 100644 --- a/src/settings/defaults.ts +++ b/src/settings/defaults.ts @@ -2,7 +2,7 @@ import type SplitIO from '@splitsoftware/splitio-commons/types/splitio'; import { LogLevels, isLogLevelString } from '@splitsoftware/splitio-commons/src/logger/index'; import { CONSENT_GRANTED } from '@splitsoftware/splitio-commons/src/utils/constants'; -const packageVersion = '1.0.1'; +const packageVersion = '1.1.0'; /** * In browser, the default debug level, can be set via the `localStorage.splitio_debug` item. diff --git a/ts-tests/index.ts b/ts-tests/index.ts index bdc4073..8c6dbb6 100644 --- a/ts-tests/index.ts +++ b/ts-tests/index.ts @@ -142,7 +142,8 @@ splitView = { off: '{"dimensions":"{\"height\":20,\"width\":40}"}' }, sets: ['set_a', 'set_b'], - defaultTreatment: 'off' + defaultTreatment: 'off', + impressionsDisabled: false }; splitViews = [splitView];