From 6ba2711a7cecc0af821ef54e6c2e76e8fb79897f Mon Sep 17 00:00:00 2001 From: kirillzyusko Date: Thu, 29 Feb 2024 13:36:10 +0100 Subject: [PATCH] feat: use MemoryProvider in unit-tests --- lib/storage/__mocks__/index.ts | 107 ++++-------------- tests/unit/onyxMultiMergeWebStorageTest.js | 36 +++--- .../providers/IDBKeyvalProviderTest.js | 8 +- 3 files changed, 44 insertions(+), 107 deletions(-) diff --git a/lib/storage/__mocks__/index.ts b/lib/storage/__mocks__/index.ts index 87b6712bd..8d279abb5 100644 --- a/lib/storage/__mocks__/index.ts +++ b/lib/storage/__mocks__/index.ts @@ -1,90 +1,27 @@ -import utils from '../../utils'; -import type {Key, KeyValuePairList, Value} from '../providers/types'; -import type StorageProvider from '../providers/types'; +import MemoryOnlyProvider, {mockStore, mockSet, setMockStore} from '../providers/MemoryOnlyProvider'; -let storageMapInternal: Record = {}; +const init = jest.fn(MemoryOnlyProvider.init); -const set = jest.fn((key, value) => { - storageMapInternal[key] = value; - return Promise.resolve(value); -}); +init(); -const idbKeyvalMock: StorageProvider = { - name: 'KeyValMockProvider', - init: () => undefined, - setItem(key, value) { - return set(key, value); - }, - multiSet(pairs) { - const setPromises = pairs.map(([key, value]) => this.setItem(key, value)); - return new Promise((resolve) => Promise.all(setPromises).then(() => resolve(storageMapInternal))); - }, - getItem(key) { - return Promise.resolve(storageMapInternal[key]); - }, - multiGet(keys) { - const getPromises = keys.map((key) => new Promise((resolve) => this.getItem(key).then((value) => resolve([key, value])))); - return Promise.all(getPromises) as Promise; - }, - multiMerge(pairs) { - pairs.forEach(([key, value]) => { - const existingValue = storageMapInternal[key]; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const newValue = utils.fastMerge(existingValue as any, value); - - set(key, newValue); - }); - - return Promise.resolve(storageMapInternal); - }, - mergeItem(key, _changes, modifiedData) { - return this.setItem(key, modifiedData); - }, - removeItem(key) { - delete storageMapInternal[key]; - return Promise.resolve(); - }, - removeItems(keys) { - keys.forEach((key) => { - delete storageMapInternal[key]; - }); - return Promise.resolve(); - }, - clear() { - storageMapInternal = {}; - return Promise.resolve(); - }, - getAllKeys() { - return Promise.resolve(Object.keys(storageMapInternal)); - }, - getDatabaseSize() { - return Promise.resolve({bytesRemaining: 0, bytesUsed: 99999}); - }, - // eslint-disable-next-line @typescript-eslint/no-empty-function - setMemoryOnlyKeys() {}, - keepInstancesSync: () => undefined, -}; - -const idbKeyvalMockSpy = { - idbKeyvalSet: set, - init: jest.fn(idbKeyvalMock.init), - setItem: jest.fn(idbKeyvalMock.setItem), - getItem: jest.fn(idbKeyvalMock.getItem), - removeItem: jest.fn(idbKeyvalMock.removeItem), - removeItems: jest.fn(idbKeyvalMock.removeItems), - clear: jest.fn(idbKeyvalMock.clear), - getAllKeys: jest.fn(idbKeyvalMock.getAllKeys), - multiGet: jest.fn(idbKeyvalMock.multiGet), - multiSet: jest.fn(idbKeyvalMock.multiSet), - multiMerge: jest.fn(idbKeyvalMock.multiMerge), - mergeItem: jest.fn(idbKeyvalMock.mergeItem), - getStorageMap: jest.fn(() => storageMapInternal), - setInitialMockData: jest.fn((data) => { - storageMapInternal = data; - }), - getDatabaseSize: jest.fn(idbKeyvalMock.getDatabaseSize), - setMemoryOnlyKeys: jest.fn(idbKeyvalMock.setMemoryOnlyKeys), - keepInstancesSync: jest.fn(idbKeyvalMock.keepInstancesSync), +const StorageMock = { + init, + getItem: jest.fn(MemoryOnlyProvider.getItem), + multiGet: jest.fn(MemoryOnlyProvider.multiGet), + setItem: jest.fn(MemoryOnlyProvider.setItem), + multiSet: jest.fn(MemoryOnlyProvider.multiSet), + mergeItem: jest.fn(MemoryOnlyProvider.mergeItem), + multiMerge: jest.fn(MemoryOnlyProvider.multiMerge), + removeItem: jest.fn(MemoryOnlyProvider.removeItem), + removeItems: jest.fn(MemoryOnlyProvider.removeItems), + clear: jest.fn(MemoryOnlyProvider.clear), + setMemoryOnlyKeys: jest.fn(MemoryOnlyProvider.setMemoryOnlyKeys), + getAllKeys: jest.fn(MemoryOnlyProvider.getAllKeys), + getDatabaseSize: jest.fn(MemoryOnlyProvider.getDatabaseSize), + keepInstancesSync: jest.fn(), + mockSet, + getMockStore: jest.fn(() => mockStore), + setMockStore: jest.fn((data) => setMockStore(data)), }; -export default idbKeyvalMockSpy; +export default StorageMock; diff --git a/tests/unit/onyxMultiMergeWebStorageTest.js b/tests/unit/onyxMultiMergeWebStorageTest.js index 618b68d00..f1091bc6b 100644 --- a/tests/unit/onyxMultiMergeWebStorageTest.js +++ b/tests/unit/onyxMultiMergeWebStorageTest.js @@ -32,12 +32,12 @@ describe('Onyx.mergeCollection() and WebStorage', () => { afterEach(() => Onyx.clear()); it('merges two sets of data consecutively', () => { - StorageMock.setInitialMockData(initialData); + StorageMock.setMockStore(initialData); // Given initial data in storage - expect(StorageMock.getStorageMap().test_1).toEqual(initialTestObject); - expect(StorageMock.getStorageMap().test_2).toEqual(initialTestObject); - expect(StorageMock.getStorageMap().test_3).toEqual(initialTestObject); + expect(StorageMock.getMockStore().test_1).toEqual(initialTestObject); + expect(StorageMock.getMockStore().test_2).toEqual(initialTestObject); + expect(StorageMock.getMockStore().test_3).toEqual(initialTestObject); // And an empty cache values for the collection keys expect(OnyxCache.getValue('test_1')).not.toBeDefined(); @@ -75,17 +75,17 @@ describe('Onyx.mergeCollection() and WebStorage', () => { expect(OnyxCache.getValue('test_3')).toEqual(finalObject); // And the storage should reflect the same state - expect(StorageMock.getStorageMap().test_1).toEqual(finalObject); - expect(StorageMock.getStorageMap().test_2).toEqual(finalObject); - expect(StorageMock.getStorageMap().test_3).toEqual(finalObject); + expect(StorageMock.getMockStore().test_1).toEqual(finalObject); + expect(StorageMock.getMockStore().test_2).toEqual(finalObject); + expect(StorageMock.getMockStore().test_3).toEqual(finalObject); }); }); it('cache updates correctly when accessed again if keys are removed or evicted', () => { // Given empty storage - expect(StorageMock.getStorageMap().test_1).toBeFalsy(); - expect(StorageMock.getStorageMap().test_2).toBeFalsy(); - expect(StorageMock.getStorageMap().test_3).toBeFalsy(); + expect(StorageMock.getMockStore().test_1).toBeFalsy(); + expect(StorageMock.getMockStore().test_2).toBeFalsy(); + expect(StorageMock.getMockStore().test_3).toBeFalsy(); // And an empty cache values for the collection keys expect(OnyxCache.getValue('test_1')).toBeFalsy(); @@ -106,9 +106,9 @@ describe('Onyx.mergeCollection() and WebStorage', () => { expect(OnyxCache.getValue('test_1')).toEqual(data); expect(OnyxCache.getValue('test_2')).toEqual(data); expect(OnyxCache.getValue('test_3')).toEqual(data); - expect(StorageMock.getStorageMap().test_1).toEqual(data); - expect(StorageMock.getStorageMap().test_2).toEqual(data); - expect(StorageMock.getStorageMap().test_3).toEqual(data); + expect(StorageMock.getMockStore().test_1).toEqual(data); + expect(StorageMock.getMockStore().test_2).toEqual(data); + expect(StorageMock.getMockStore().test_3).toEqual(data); // When we drop all the cache keys (but do not modify the underlying storage) and merge another object OnyxCache.drop('test_1'); @@ -137,15 +137,15 @@ describe('Onyx.mergeCollection() and WebStorage', () => { expect(OnyxCache.getValue('test_3')).toEqual(finalObject); // And the storage should reflect the same state - expect(StorageMock.getStorageMap().test_1).toEqual(finalObject); - expect(StorageMock.getStorageMap().test_2).toEqual(finalObject); - expect(StorageMock.getStorageMap().test_3).toEqual(finalObject); + expect(StorageMock.getMockStore().test_1).toEqual(finalObject); + expect(StorageMock.getMockStore().test_2).toEqual(finalObject); + expect(StorageMock.getMockStore().test_3).toEqual(finalObject); }); }); it('setItem() and multiMerge()', () => { // Onyx should be empty after clear() is called - expect(StorageMock.getStorageMap()).toEqual({}); + expect(StorageMock.getMockStore()).toEqual({}); // Given no previous data and several calls to setItem and call to mergeCollection to update a given key @@ -174,7 +174,7 @@ describe('Onyx.mergeCollection() and WebStorage', () => { }; expect(OnyxCache.getValue('test_1')).toEqual(finalObject); - expect(StorageMock.getStorageMap().test_1).toEqual(finalObject); + expect(StorageMock.getMockStore().test_1).toEqual(finalObject); }); }); }); diff --git a/tests/unit/storage/providers/IDBKeyvalProviderTest.js b/tests/unit/storage/providers/IDBKeyvalProviderTest.js index 9fa895d51..c511cd0a3 100644 --- a/tests/unit/storage/providers/IDBKeyvalProviderTest.js +++ b/tests/unit/storage/providers/IDBKeyvalProviderTest.js @@ -64,7 +64,7 @@ describe('storage/providers/IDBKeyVal', () => { ]); return waitForPromisesToResolve().then(() => { - IDBKeyValProviderMock.idbKeyvalSet.mockClear(); + IDBKeyValProviderMock.mockSet.mockClear(); // Given deltas matching existing structure const USER_1_DELTA = { @@ -83,7 +83,7 @@ describe('storage/providers/IDBKeyVal', () => { ['@USER_2', USER_2_DELTA], ]).then(() => { // Then each existing item should be set with the merged content - expect(IDBKeyValProviderMock.idbKeyvalSet).toHaveBeenNthCalledWith(1, '@USER_1', { + expect(IDBKeyValProviderMock.mockSet).toHaveBeenNthCalledWith(1, '@USER_1', { name: 'Tom', age: 31, traits: { @@ -92,7 +92,7 @@ describe('storage/providers/IDBKeyVal', () => { }, }); - expect(IDBKeyValProviderMock.idbKeyvalSet).toHaveBeenNthCalledWith(2, '@USER_2', { + expect(IDBKeyValProviderMock.mockSet).toHaveBeenNthCalledWith(2, '@USER_2', { name: 'Sarah', age: 26, traits: { @@ -131,7 +131,7 @@ describe('storage/providers/IDBKeyVal', () => { // If StorageProvider.clear() does not abort the queue, more idbKeyval.setItem calls would be executed because they would // be sitting in the setItemQueue return waitForPromisesToResolve().then(() => { - expect(IDBKeyValProviderMock.idbKeyvalSet).toHaveBeenCalledTimes(0); + expect(IDBKeyValProviderMock.mockSet).toHaveBeenCalledTimes(0); expect(IDBKeyValProviderMock.clear).toHaveBeenCalledTimes(1); }); });