diff --git a/lib/Onyx.js b/lib/Onyx.js index d6a2d13a..fadd81e4 100644 --- a/lib/Onyx.js +++ b/lib/Onyx.js @@ -731,7 +731,10 @@ function init({ initializeWithDefaultKeyStates(); // Update any key whose value changes in storage - registerStorageEventListener((key, newValue) => keyChanged(key, newValue)); + registerStorageEventListener((key, newValue) => { + cache.set(key, newValue); + keyChanged(key, newValue); + }); } const Onyx = { diff --git a/lib/OnyxCache.js b/lib/OnyxCache.js index 841f6bc9..b2d521a1 100644 --- a/lib/OnyxCache.js +++ b/lib/OnyxCache.js @@ -98,11 +98,15 @@ class OnyxCache { } /** - * Deep merge data to cache, any non existing keys will be crated + * Deep merge data to cache, any non existing keys will be created * @param {Record} data - a map of (cache) key - values */ merge(data) { this.storageMap = lodashMerge({}, this.storageMap, data); + + const storageKeys = this.getAllKeys(); + const mergedKeys = _.keys(data); + this.storageKeys = new Set([...storageKeys, ...mergedKeys]); } /** diff --git a/lib/decorateWithMetrics.js b/lib/decorateWithMetrics.js index e9b7a852..26f2c12d 100644 --- a/lib/decorateWithMetrics.js +++ b/lib/decorateWithMetrics.js @@ -26,7 +26,7 @@ function decorateWithMetrics(func, alias = func.name) { /* * Then handlers added here are not affecting the original promise - * They crate a separate chain that's not exposed (returned) to the original caller + * They create a separate chain that's not exposed (returned) to the original caller * */ originalPromise .finally(() => { diff --git a/tests/unit/onyxCacheTest.js b/tests/unit/onyxCacheTest.js index de5f0a35..f188ebc5 100644 --- a/tests/unit/onyxCacheTest.js +++ b/tests/unit/onyxCacheTest.js @@ -318,6 +318,22 @@ describe('Onyx', () => { expect(cache.hasCacheForKey('mockKey')).toBe(true); expect(cache.getValue('mockKey')).toEqual({ID: 5}); }); + + it('Should update storageKeys when new keys are created', () => { + // GIVEN cache with some items + cache.set('mockKey', {value: 'mockValue'}); + cache.set('mockKey2', {other: 'otherMockValue', mock: 'mock', items: [3, 4, 5]}); + + // WHEN merge is called with existing key value pairs + cache.merge({ + mockKey: {mockItems: []}, + mockKey3: {ID: 3}, + mockKey4: {ID: 4}, + }); + + // THEN getAllStorage keys should return updated storage keys + expect(cache.getAllKeys()).toEqual(['mockKey', 'mockKey2', 'mockKey3', 'mockKey4']); + }); }); describe('hasPendingTask', () => { @@ -377,6 +393,7 @@ describe('Onyx', () => { describe('Onyx with Cache', () => { let Onyx; let withOnyx; + let AsyncStorageMock; /** @type OnyxCache */ let cache; @@ -393,6 +410,7 @@ describe('Onyx', () => { const OnyxModule = require('../../index'); Onyx = OnyxModule.default; withOnyx = OnyxModule.withOnyx; + AsyncStorageMock = require('@react-native-community/async-storage').default; cache = require('../../lib/OnyxCache').default; Onyx.init({ @@ -413,8 +431,6 @@ describe('Onyx', () => { }); it('Expect a single call to getItem when multiple components use the same key', () => { - const AsyncStorageMock = require('@react-native-community/async-storage/jest/async-storage-mock'); - // GIVEN a component connected to Onyx const TestComponentWithOnyx = withOnyx({ text: { @@ -444,8 +460,6 @@ describe('Onyx', () => { }); it('Expect a single call to getAllKeys when multiple components use the same key', () => { - const AsyncStorageMock = require('@react-native-community/async-storage/jest/async-storage-mock'); - // GIVEN a component connected to Onyx const TestComponentWithOnyx = withOnyx({ text: { @@ -476,8 +490,6 @@ describe('Onyx', () => { }); it('Expect multiple calls to getItem when no existing component is using a key', () => { - const AsyncStorageMock = require('@react-native-community/async-storage/jest/async-storage-mock'); - // GIVEN a component connected to Onyx const TestComponentWithOnyx = withOnyx({ text: { @@ -509,8 +521,6 @@ describe('Onyx', () => { }); it('Expect multiple calls to getItem when multiple keys are used', () => { - const AsyncStorageMock = require('@react-native-community/async-storage/jest/async-storage-mock'); - // GIVEN two component const TestComponentWithOnyx = withOnyx({ testObject: { @@ -550,8 +560,6 @@ describe('Onyx', () => { }); it('Expect a single call to getItem when at least one component is still subscribed to a key', () => { - const AsyncStorageMock = require('@react-native-community/async-storage/jest/async-storage-mock'); - // GIVEN a component connected to Onyx const TestComponentWithOnyx = withOnyx({ text: { @@ -589,8 +597,6 @@ describe('Onyx', () => { }); it('Should remove collection items from cache when collection is disconnected', () => { - const AsyncStorageMock = require('@react-native-community/async-storage/jest/async-storage-mock'); - // GIVEN a component subscribing to a collection const TestComponentWithOnyx = withOnyx({ collections: { @@ -638,8 +644,6 @@ describe('Onyx', () => { }); it('Should not remove item from cache when it still used in a collection', () => { - const AsyncStorageMock = require('@react-native-community/async-storage/jest/async-storage-mock'); - // GIVEN component that uses a collection and a component that uses a collection item const COLLECTION_ITEM_KEY = `${ONYX_KEYS.COLLECTION.MOCK_COLLECTION}10`; const TestComponentWithOnyx = withOnyx({ diff --git a/tests/unit/withOnyxTest.js b/tests/unit/withOnyxTest.js index 79d1351e..6053bac4 100644 --- a/tests/unit/withOnyxTest.js +++ b/tests/unit/withOnyxTest.js @@ -43,7 +43,6 @@ describe('withOnyx', () => { }); it('should update withOnyx subscriber multiple times when merge is used', () => { - // Todo: ViewWithCollections does not expect a `text` prop const TestComponentWithOnyx = withOnyx({ text: { key: ONYX_KEYS.COLLECTION.TEST_KEY, @@ -62,7 +61,6 @@ describe('withOnyx', () => { }); it('should update withOnyx subscriber just once when mergeCollection is used', () => { - // Todo: ViewWithCollections does not expect a `text` prop const TestComponentWithOnyx = withOnyx({ text: { key: ONYX_KEYS.COLLECTION.TEST_KEY, @@ -79,7 +77,6 @@ describe('withOnyx', () => { }); it('should update withOnyx subscribing to individual key if mergeCollection is used', () => { - // Todo: ViewWithCollections does not expect a `text` prop const collectionItemID = 1; const TestComponentWithOnyx = withOnyx({ text: { @@ -97,7 +94,6 @@ describe('withOnyx', () => { }); it('should update withOnyx subscribing to individual key with merged value if mergeCollection is used', () => { - // Todo: ViewWithCollections does not expect a `text` prop const collectionItemID = 4; const TestComponentWithOnyx = withOnyx({ text: {