Skip to content

Commit 29d56fd

Browse files
Update tests, changelog entry and prepare rc
1 parent 721a80a commit 29d56fd

File tree

11 files changed

+128
-43
lines changed

11 files changed

+128
-43
lines changed

.github/workflows/ci-cd.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ jobs:
4747
run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") npm run build
4848

4949
- name: Store assets
50-
if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/development' || github.ref == 'refs/heads/main') }}
50+
if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/cache_expiration' || github.ref == 'refs/heads/main') }}
5151
uses: actions/upload-artifact@v3
5252
with:
5353
name: assets
@@ -58,7 +58,7 @@ jobs:
5858
name: Upload assets
5959
runs-on: ubuntu-20.04
6060
needs: build
61-
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }}
61+
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/cache_expiration' }}
6262
strategy:
6363
matrix:
6464
environment:

CHANGES.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
1.1.0 (January XX, 2025)
2+
- Added two new configuration options for the SDK's `InLocalStorage` module to control the behavior of the persisted rollout plan cache in the browser:
3+
- `expirationDays` to specify the validity period of the rollout plan cache in days.
4+
- `clearOnInit` to clear the rollout plan cache on SDK initialization.
5+
- Updated @splitsoftware/splitio-commons package to version 2.1.0.
6+
17
1.0.1 (November 11, 2024)
28
- 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';`.
39

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,4 @@ For a comprehensive list of open source projects visit our [Github page](https:/
8383

8484
**Learn more about Split:**
8585

86-
Visit [split.io/product](https://www.split.io/product) for an overview of Split, or visit our documentation at [help.split.io](http://help.split.io) for more detailed information.
86+
Visit [split.io/product](https://www.split.io/product) for an overview of Split, or visit our documentation at [help.split.io](https://help.split.io) for more detailed information.

package-lock.json

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@splitsoftware/splitio-browserjs",
3-
"version": "1.0.1",
3+
"version": "1.1.0-rc.0",
44
"description": "Split SDK for JavaScript on Browser",
55
"main": "cjs/index.js",
66
"module": "esm/index.js",
@@ -59,7 +59,7 @@
5959
"bugs": "https://github.com/splitio/javascript-browser-client/issues",
6060
"homepage": "https://github.com/splitio/javascript-browser-client#readme",
6161
"dependencies": {
62-
"@splitsoftware/splitio-commons": "2.0.0",
62+
"@splitsoftware/splitio-commons": "2.1.0-rc.0",
6363
"tslib": "^2.3.1",
6464
"unfetch": "^4.2.0"
6565
},

src/__tests__/browserSuites/ready-from-cache.spec.js

Lines changed: 94 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1+
import sinon from 'sinon';
2+
import { nearlyEqual } from '../testUtils';
13
import { getStorageHash } from '@splitsoftware/splitio-commons/src/storages/KeyBuilder';
24
import { SplitFactory, InLocalStorage } from '../../';
35

46
import splitChangesMock1 from '../mocks/splitchanges.since.-1.json';
57
import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json';
68
import membershipsNicolas from '../mocks/memberships.nicolas@split.io.json';
79

8-
import { nearlyEqual } from '../testUtils';
9-
1010
const DEFAULT_CACHE_EXPIRATION_IN_MILLIS = 864000000; // 10 days
1111

1212
const alwaysOnSplitInverted = JSON.stringify({
@@ -177,7 +177,6 @@ export default function (fetchMock, assert) {
177177
readyTimeout: 0.85
178178
},
179179
urls: testUrls,
180-
debug: true
181180
});
182181
const client = splitio.client();
183182
const client2 = splitio.client('nicolas2@split.io');
@@ -245,7 +244,7 @@ export default function (fetchMock, assert) {
245244
});
246245
});
247246

248-
assert.test(t => { // Testing when we start with cached data and not expired (lastUpdate item higher than expirationTimestamp)
247+
assert.test(t => { // Testing when we start with cached data and not expired (lastUpdate timestamp higher than default (10) expirationDays ago)
249248
const testUrls = {
250249
sdk: 'https://sdk.baseurl/readyFromCacheWithData3',
251250
events: 'https://events.baseurl/readyFromCacheWithData3'
@@ -287,7 +286,6 @@ export default function (fetchMock, assert) {
287286
readyTimeout: 0.85
288287
},
289288
urls: testUrls,
290-
debug: true
291289
});
292290
const client = splitio.client();
293291
const client2 = splitio.client('nicolas2@split.io');
@@ -362,7 +360,7 @@ export default function (fetchMock, assert) {
362360
});
363361
});
364362

365-
assert.test(t => { // Testing when we start with cached data but expired (lastUpdate item lower than expirationTimestamp)
363+
assert.test(t => { // Testing when we start with cached data but expired (lastUpdate timestamp lower than custom (1) expirationDays ago)
366364
const testUrls = {
367365
sdk: 'https://sdk.baseurl/readyFromCacheWithData4',
368366
events: 'https://events.baseurl/readyFromCacheWithData4'
@@ -372,7 +370,8 @@ export default function (fetchMock, assert) {
372370
fetchMock.get(testUrls.sdk + '/splitChanges?s=1.2&since=-1', function () {
373371
t.equal(localStorage.getItem('some_user_item'), 'user_item', 'user items at localStorage must not be changed');
374372
t.equal(localStorage.getItem('readyFromCache_4.SPLITIO.hash'), expectedHashNullFilter, 'storage hash must not be changed');
375-
t.equal(localStorage.length, 2, 'feature flags cache data must be cleaned from localStorage');
373+
t.true(nearlyEqual(parseInt(localStorage.getItem('readyFromCache_4.SPLITIO.lastClear'), 10), Date.now()), 'storage lastClear timestamp must be updated');
374+
t.equal(localStorage.length, 3, 'feature flags cache data must be cleaned from localStorage');
376375
return { status: 200, body: splitChangesMock1 };
377376
});
378377
fetchMock.get(testUrls.sdk + '/splitChanges?s=1.2&since=1457552620999', { status: 200, body: splitChangesMock2 });
@@ -390,21 +389,21 @@ export default function (fetchMock, assert) {
390389

391390
localStorage.setItem('some_user_item', 'user_item');
392391
localStorage.setItem('readyFromCache_4.SPLITIO.splits.till', 25);
393-
localStorage.setItem('readyFromCache_4.SPLITIO.splits.lastUpdated', Date.now() - DEFAULT_CACHE_EXPIRATION_IN_MILLIS - 1); // -1 to ensure having an expired lastUpdated item
392+
localStorage.setItem('readyFromCache_4.SPLITIO.splits.lastUpdated', Date.now() - DEFAULT_CACHE_EXPIRATION_IN_MILLIS / 10 - 1); // -1 to ensure having an expired lastUpdated item
394393
localStorage.setItem('readyFromCache_4.SPLITIO.split.always_on', alwaysOnSplitInverted);
395394
localStorage.setItem('readyFromCache_4.SPLITIO.hash', expectedHashNullFilter);
396395

397396
const startTime = Date.now();
398397
const splitio = SplitFactory({
399398
...baseConfig,
400399
storage: InLocalStorage({
401-
prefix: 'readyFromCache_4'
400+
prefix: 'readyFromCache_4',
401+
expirationDays: 1
402402
}),
403403
startup: {
404404
readyTimeout: 0.85
405405
},
406406
urls: testUrls,
407-
debug: true
408407
});
409408
const client = splitio.client();
410409
const client2 = splitio.client('nicolas2@split.io');
@@ -502,7 +501,6 @@ export default function (fetchMock, assert) {
502501
sync: {
503502
splitFilters: [{ type: 'byName', values: ['p2__split', 'p1__split'] }, { type: 'byName', values: ['p2__split', null] }]
504503
},
505-
debug: true
506504
});
507505
const client = splitio.client();
508506
const manager = splitio.manager();
@@ -547,7 +545,6 @@ export default function (fetchMock, assert) {
547545
sync: {
548546
splitFilters: [{ type: 'byName', values: ['p2__split', 'p1__split'] }, { type: 'byName', values: ['p2__split', null] }]
549547
},
550-
debug: true
551548
});
552549
const client = splitio.client();
553550
const manager = splitio.manager();
@@ -597,7 +594,6 @@ export default function (fetchMock, assert) {
597594
sync: {
598595
splitFilters: [{ type: 'byName', values: [undefined, true, 'p2__split'] }, { type: 'byPrefix', values: ['p1'] }, { type: 'byName', values: ['p2__split'] }]
599596
},
600-
debug: true
601597
});
602598
const client = splitio.client();
603599
const manager = splitio.manager();
@@ -642,13 +638,13 @@ export default function (fetchMock, assert) {
642638
const splitio = SplitFactory({
643639
...baseConfig,
644640
storage: InLocalStorage({
645-
prefix: 'readyFromCache_7'
641+
prefix: 'readyFromCache_7',
642+
expirationDays: 0, // invalid value, will use default (10)
646643
}),
647644
urls: testUrls,
648645
sync: {
649646
splitFilters: [{ type: 'byPrefix', values: ['p2'] }, { type: 'byPrefix', values: ['p1', ''] }, { type: '', values: [] }, {}, { type: 'byPrefix' }]
650647
},
651-
debug: true
652648
});
653649
const client = splitio.client();
654650
const manager = splitio.manager();
@@ -710,7 +706,6 @@ export default function (fetchMock, assert) {
710706
}),
711707
urls: testUrls,
712708
sync: syncParam,
713-
debug: true
714709
});
715710
const client = splitio.client();
716711
const manager = splitio.manager();
@@ -764,7 +759,6 @@ export default function (fetchMock, assert) {
764759
sync: {
765760
splitFilters: [{ type: 'byName', values: ['p3__split'] }, { type: 'byPrefix', values: [' p2', ' p2', ' p2', ' p2', 'no exist trim '] }, { type: 'byName', values: ['no_exist', ' no exist trim '] }]
766761
},
767-
debug: true
768762
});
769763
const client = splitio.client();
770764
const manager = splitio.manager();
@@ -788,4 +782,87 @@ export default function (fetchMock, assert) {
788782
});
789783
});
790784

785+
assert.test(async t => { // Testing clearOnInit config true
786+
sinon.spy(console, 'log');
787+
788+
const testUrls = {
789+
sdk: 'https://sdk.baseurl/readyFromCache_10',
790+
events: 'https://events.baseurl/readyFromCache_10'
791+
};
792+
const clearOnInitConfig = {
793+
...baseConfig,
794+
storage: InLocalStorage({
795+
type: 'LOCALSTORAGE',
796+
prefix: 'readyFromCache_10',
797+
clearOnInit: true
798+
}),
799+
urls: testUrls,
800+
debug: true
801+
};
802+
803+
// Start with cached data but without lastClear item (JS SDK below 11.1.0) -> cache cleanup
804+
localStorage.clear();
805+
localStorage.setItem('readyFromCache_10.SPLITIO.splits.till', 25);
806+
localStorage.setItem('readyFromCache_10.SPLITIO.split.p1__split', JSON.stringify(splitDeclarations.p1__split));
807+
localStorage.setItem('readyFromCache_10.SPLITIO.split.p2__split', JSON.stringify(splitDeclarations.p2__split));
808+
localStorage.setItem('readyFromCache_10.SPLITIO.hash', expectedHashNullFilter);
809+
810+
fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.2&since=-1', { status: 200, body: splitChangesMock1 });
811+
fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.2&since=1457552620999', { status: 200, body: splitChangesMock2 });
812+
fetchMock.get(testUrls.sdk + '/memberships/nicolas%40split.io', { status: 200, body: { ms: {} } });
813+
814+
let splitio = SplitFactory(clearOnInitConfig);
815+
let client = splitio.client();
816+
let manager = splitio.manager();
817+
818+
t.true(console.log.calledWithMatch('clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache'), 'It should log a message about cleaning up cache');
819+
820+
client.once(client.Event.SDK_READY_FROM_CACHE, () => t.fail('It should not emit SDK_READY_FROM_CACHE because clearOnInit is true.'));
821+
822+
await client.ready();
823+
t.equal(manager.names().sort().length, 32, 'active splits should be present for evaluation');
824+
825+
await splitio.destroy();
826+
t.equal(localStorage.getItem('readyFromCache_10.SPLITIO.splits.till'), '1457552620999', 'splits.till must correspond to the till of the last successfully fetched Splits');
827+
t.equal(localStorage.getItem('readyFromCache_10.SPLITIO.hash'), expectedHashNullFilter, 'Storage hash must not be changed');
828+
t.true(nearlyEqual(parseInt(localStorage.getItem('readyFromCache_10.SPLITIO.lastClear')), Date.now()), 'lastClear timestamp must be set');
829+
830+
// Start again with cached data and lastClear item within the last 24 hours -> no cache cleanup
831+
console.log.resetHistory();
832+
fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.2&since=1457552620999', { status: 200, body: splitChangesMock2 });
833+
834+
splitio = SplitFactory(clearOnInitConfig);
835+
client = splitio.client();
836+
manager = splitio.manager();
837+
838+
await new Promise(res => client.once(client.Event.SDK_READY_FROM_CACHE, res));
839+
840+
t.equal(manager.names().sort().length, 32, 'active splits should be present for evaluation');
841+
t.false(console.log.calledWithMatch('clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache'), 'It should log a message about cleaning up cache');
842+
843+
await splitio.destroy();
844+
845+
// Start again with cached data and lastClear item older than 24 hours -> cache cleanup
846+
console.log.resetHistory();
847+
localStorage.setItem('readyFromCache_10.SPLITIO.lastClear', Date.now() - 25 * 60 * 60 * 1000); // 25 hours ago
848+
fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.2&since=-1', { status: 200, body: splitChangesMock1 });
849+
fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.2&since=1457552620999', { status: 200, body: splitChangesMock2 });
850+
851+
splitio = SplitFactory(clearOnInitConfig);
852+
client = splitio.client();
853+
manager = splitio.manager();
854+
855+
client.once(client.Event.SDK_READY_FROM_CACHE, () => t.fail('It should not emit SDK_READY_FROM_CACHE because clearOnInit is true.'));
856+
857+
await new Promise(res => client.once(client.Event.SDK_READY, res));
858+
859+
t.equal(manager.names().sort().length, 32, 'active splits should be present for evaluation');
860+
t.true(console.log.calledWithMatch('clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache'), 'It should log a message about cleaning up cache');
861+
862+
await splitio.destroy();
863+
864+
console.log.restore();
865+
t.end();
866+
});
867+
791868
}

src/__tests__/testUtils/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ export function nearlyEqual(actual, expected, epsilon = DEFAULT_ERROR_MARGIN) {
1818
* - when `?since=-1`, it returns the given segment `keys` in `added` list.
1919
* - otherwise, it returns empty `added` and `removed` lists, and the same since and till values.
2020
*
21-
* @param {Object} fetchMock see http://www.wheresrhys.co.uk/fetch-mock
22-
* @param {string|RegExp|...} matcher see http://www.wheresrhys.co.uk/fetch-mock/#api-mockingmock_matcher
21+
* @param {Object} fetchMock see https://www.wheresrhys.co.uk/fetch-mock
22+
* @param {string|RegExp|...} matcher see https://www.wheresrhys.co.uk/fetch-mock/#api-mockingmock_matcher
2323
* @param {string[]} keys array of segment keys to fetch
2424
* @param {number} changeNumber optional changeNumber
2525
*/

src/settings/defaults.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type SplitIO from '@splitsoftware/splitio-commons/types/splitio';
22
import { LogLevels, isLogLevelString } from '@splitsoftware/splitio-commons/src/logger/index';
33
import { CONSENT_GRANTED } from '@splitsoftware/splitio-commons/src/utils/constants';
44

5-
const packageVersion = '1.0.1';
5+
const packageVersion = '1.1.0-rc.0';
66

77
/**
88
* In browser, the default debug level, can be set via the `localStorage.splitio_debug` item.

ts-tests/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,9 @@ let impressionData: SplitIO.ImpressionData;
110110
let syncStorage: SplitIO.StorageSync;
111111
let syncStorageFactory: SplitIO.StorageSyncFactory = InLocalStorage();
112112
let localStorageOptions: SplitIO.InLocalStorageOptions = {
113-
prefix: 'PREFIX'
113+
prefix: 'PREFIX',
114+
expirationDays: 1,
115+
clearOnInit: true
114116
};
115117
syncStorageFactory = InLocalStorage(localStorageOptions);
116118

types/full/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Declaration file for JavaScript Browser Split Software SDK
2-
// Project: http://www.split.io/
2+
// Project: https://www.split.io/
33
// Definitions by: Nico Zelaya <https://github.com/NicoZelaya/>
44

55
/// <reference path="../splitio.d.ts" />

0 commit comments

Comments
 (0)