Skip to content

Commit 28b7fb9

Browse files
Add unit test
1 parent 956c1df commit 28b7fb9

File tree

2 files changed

+125
-2
lines changed

2 files changed

+125
-2
lines changed

src/storages/inLocalStorage/SplitsCacheInLocal.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
7171
* We cannot simply call `localStorage.clear()` since that implies removing user items from the storage.
7272
*/
7373
clear() {
74-
this.log.info(LOG_PREFIX + 'Flushing Splits data from localStorage');
75-
7674
// collect item keys
7775
const len = localStorage.length;
7876
const accum = [];
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import { validateCache } from '../validateCache';
2+
3+
import { KeyBuilderCS } from '../../KeyBuilderCS';
4+
import { fullSettings } from '../../../utils/settingsValidation/__tests__/settings.mocks';
5+
import { SplitsCacheInLocal } from '../SplitsCacheInLocal';
6+
import { nearlyEqual } from '../../../__tests__/testUtils';
7+
import { MySegmentsCacheInLocal } from '../MySegmentsCacheInLocal';
8+
9+
const FULL_SETTINGS_HASH = '404832b3';
10+
11+
describe('validateCache', () => {
12+
const keys = new KeyBuilderCS('SPLITIO', 'user');
13+
const logSpy = jest.spyOn(fullSettings.log, 'info');
14+
const segments = new MySegmentsCacheInLocal(fullSettings.log, keys);
15+
const largeSegments = new MySegmentsCacheInLocal(fullSettings.log, keys);
16+
const splits = new SplitsCacheInLocal(fullSettings, keys);
17+
18+
jest.spyOn(splits, 'clear');
19+
jest.spyOn(splits, 'getChangeNumber');
20+
jest.spyOn(segments, 'clear');
21+
jest.spyOn(largeSegments, 'clear');
22+
23+
beforeEach(() => {
24+
jest.clearAllMocks();
25+
localStorage.clear();
26+
});
27+
28+
test('if there is no cache, it should return false', () => {
29+
expect(validateCache({}, fullSettings, keys, splits, segments, largeSegments)).toBe(false);
30+
31+
expect(logSpy).not.toHaveBeenCalled();
32+
33+
expect(splits.clear).not.toHaveBeenCalled();
34+
expect(segments.clear).not.toHaveBeenCalled();
35+
expect(largeSegments.clear).not.toHaveBeenCalled();
36+
expect(splits.getChangeNumber).toHaveBeenCalledTimes(1);
37+
38+
expect(localStorage.getItem(keys.buildHashKey())).toBe(FULL_SETTINGS_HASH);
39+
expect(localStorage.getItem(keys.buildLastClear())).toBeNull();
40+
});
41+
42+
test('if there is cache and it must not be cleared, it should return true', () => {
43+
localStorage.setItem(keys.buildSplitsTillKey(), '1');
44+
localStorage.setItem(keys.buildHashKey(), FULL_SETTINGS_HASH);
45+
46+
expect(validateCache({}, fullSettings, keys, splits, segments, largeSegments)).toBe(true);
47+
48+
expect(logSpy).not.toHaveBeenCalled();
49+
50+
expect(splits.clear).not.toHaveBeenCalled();
51+
expect(segments.clear).not.toHaveBeenCalled();
52+
expect(largeSegments.clear).not.toHaveBeenCalled();
53+
expect(splits.getChangeNumber).toHaveBeenCalledTimes(1);
54+
55+
expect(localStorage.getItem(keys.buildHashKey())).toBe(FULL_SETTINGS_HASH);
56+
expect(localStorage.getItem(keys.buildLastClear())).toBeNull();
57+
});
58+
59+
test('if there is cache and it has expired, it should clear cache and return false', () => {
60+
localStorage.setItem(keys.buildSplitsTillKey(), '1');
61+
localStorage.setItem(keys.buildHashKey(), FULL_SETTINGS_HASH);
62+
localStorage.setItem(keys.buildLastUpdatedKey(), Date.now() - 1000 * 60 * 60 * 24 * 2 + ''); // 2 days ago
63+
64+
expect(validateCache({ expirationDays: 1 }, fullSettings, keys, splits, segments, largeSegments)).toBe(false);
65+
66+
expect(logSpy).toHaveBeenCalledWith('storage:localstorage: Cache expired more than 1 days ago. Cleaning up cache');
67+
68+
expect(splits.clear).toHaveBeenCalledTimes(1);
69+
expect(segments.clear).toHaveBeenCalledTimes(1);
70+
expect(largeSegments.clear).toHaveBeenCalledTimes(1);
71+
72+
expect(localStorage.getItem(keys.buildHashKey())).toBe(FULL_SETTINGS_HASH);
73+
expect(nearlyEqual(parseInt(localStorage.getItem(keys.buildLastClear()) as string), Date.now())).toBe(true);
74+
});
75+
76+
test('if there is cache and its hash has changed, it should clear cache and return false', () => {
77+
localStorage.setItem(keys.buildSplitsTillKey(), '1');
78+
localStorage.setItem(keys.buildHashKey(), FULL_SETTINGS_HASH);
79+
80+
expect(validateCache({}, { ...fullSettings, core: { ...fullSettings.core, authorizationKey: 'another' } }, keys, splits, segments, largeSegments)).toBe(false);
81+
82+
expect(logSpy).toHaveBeenCalledWith('storage:localstorage: SDK key, flags filter criteria or flags spec version has changed. Cleaning up cache');
83+
84+
expect(splits.clear).toHaveBeenCalledTimes(1);
85+
expect(segments.clear).toHaveBeenCalledTimes(1);
86+
expect(largeSegments.clear).toHaveBeenCalledTimes(1);
87+
88+
expect(localStorage.getItem(keys.buildHashKey())).toBe('aa4877c2');
89+
expect(nearlyEqual(parseInt(localStorage.getItem(keys.buildLastClear()) as string), Date.now())).toBe(true);
90+
});
91+
92+
test('if there is cache and clearOnInit is true, it should clear cache and return false', () => {
93+
// Older cache version (without last clear)
94+
localStorage.setItem(keys.buildSplitsTillKey(), '1');
95+
localStorage.setItem(keys.buildHashKey(), FULL_SETTINGS_HASH);
96+
97+
expect(validateCache({ clearOnInit: true }, fullSettings, keys, splits, segments, largeSegments)).toBe(false);
98+
99+
expect(logSpy).toHaveBeenCalledWith('storage:localstorage: clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache');
100+
101+
expect(splits.clear).toHaveBeenCalledTimes(1);
102+
expect(segments.clear).toHaveBeenCalledTimes(1);
103+
expect(largeSegments.clear).toHaveBeenCalledTimes(1);
104+
105+
expect(localStorage.getItem(keys.buildHashKey())).toBe(FULL_SETTINGS_HASH);
106+
const lastClear = localStorage.getItem(keys.buildLastClear());
107+
expect(nearlyEqual(parseInt(lastClear as string), Date.now())).toBe(true);
108+
109+
// If cache is cleared, it should not clear again until a day has passed
110+
logSpy.mockClear();
111+
localStorage.setItem(keys.buildSplitsTillKey(), '1');
112+
expect(validateCache({ clearOnInit: true }, fullSettings, keys, splits, segments, largeSegments)).toBe(true);
113+
expect(logSpy).not.toHaveBeenCalled();
114+
expect(localStorage.getItem(keys.buildLastClear())).toBe(lastClear); // Last clear should not have changed
115+
116+
// If a day has passed, it should clear again
117+
localStorage.setItem(keys.buildLastClear(), (Date.now() - 1000 * 60 * 60 * 24 - 1) + '');
118+
expect(validateCache({ clearOnInit: true }, fullSettings, keys, splits, segments, largeSegments)).toBe(false);
119+
expect(logSpy).toHaveBeenCalledWith('storage:localstorage: clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache');
120+
expect(splits.clear).toHaveBeenCalledTimes(2);
121+
expect(segments.clear).toHaveBeenCalledTimes(2);
122+
expect(largeSegments.clear).toHaveBeenCalledTimes(2);
123+
expect(nearlyEqual(parseInt(localStorage.getItem(keys.buildLastClear()) as string), Date.now())).toBe(true);
124+
});
125+
});

0 commit comments

Comments
 (0)