From a4d5632a5608560cc3b8405255431e539c162267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Henriques?= Date: Mon, 4 May 2026 13:15:56 +0100 Subject: [PATCH 1/3] Remove initWithStoredValues from Onyx --- API-INTERNAL.md | 4 - lib/OnyxConnectionManager.ts | 11 +- lib/OnyxSnapshotCache.ts | 8 +- lib/OnyxUtils.ts | 11 +- lib/types.ts | 3 - lib/useOnyx.ts | 33 ++---- .../perf-test/OnyxSnapshotCache.perf-test.ts | 2 - tests/perf-test/OnyxUtils.perf-test.ts | 10 +- tests/perf-test/useOnyx.perf-test.tsx | 25 ---- tests/unit/OnyxConnectionManagerTest.ts | 50 +------- tests/unit/OnyxSnapshotCacheTest.ts | 12 +- tests/unit/onyxClearNativeStorageTest.ts | 2 - tests/unit/onyxClearWebStorageTest.ts | 2 - tests/unit/onyxTest.ts | 112 +++--------------- tests/unit/onyxUtilsTest.ts | 26 ++-- tests/unit/useOnyxTest.ts | 95 --------------- 16 files changed, 54 insertions(+), 352 deletions(-) diff --git a/API-INTERNAL.md b/API-INTERNAL.md index 933d536f5..c84d29afb 100644 --- a/API-INTERNAL.md +++ b/API-INTERNAL.md @@ -299,10 +299,6 @@ When a collection of keys change, search for any callbacks matching the collecti When a key change happens, search for any callbacks matching the key or collection key and trigger those callbacks **Kind**: global function -**Example** -```js -keyChanged(key, value, subscriber => subscriber.initWithStoredValues === false) -``` ## sendDataToConnection() diff --git a/lib/OnyxConnectionManager.ts b/lib/OnyxConnectionManager.ts index 2726efc26..5b0f32d01 100644 --- a/lib/OnyxConnectionManager.ts +++ b/lib/OnyxConnectionManager.ts @@ -115,7 +115,7 @@ class OnyxConnectionManager { * according to their purpose and effect they produce in the Onyx connection. */ private generateConnectionID(connectOptions: ConnectOptions): string { - const {key, initWithStoredValues, reuseConnection, waitForCollectionCallback} = connectOptions; + const {key, reuseConnection, waitForCollectionCallback} = connectOptions; // The current session ID is appended to the connection ID so we can have different connections // after an `Onyx.clear()` operation. @@ -123,18 +123,13 @@ class OnyxConnectionManager { // We will generate a unique ID in any of the following situations: // - `reuseConnection` is `false`. That means the subscriber explicitly wants the connection to not be reused. - // - `initWithStoredValues` is `false`. This flag changes the subscription flow when set to `false`, so the connection can't be reused. // - `key` is a collection key AND `waitForCollectionCallback` is `undefined/false`. This combination needs a new connection at every subscription // in order to send all the collection entries, so the connection can't be reused. - if ( - reuseConnection === false || - initWithStoredValues === false || - (OnyxKeys.isCollectionKey(key) && (waitForCollectionCallback === undefined || waitForCollectionCallback === false)) - ) { + if (reuseConnection === false || (OnyxKeys.isCollectionKey(key) && (waitForCollectionCallback === undefined || waitForCollectionCallback === false))) { suffix += `,uniqueID=${Str.guid()}`; } - return `onyxKey=${key},initWithStoredValues=${initWithStoredValues ?? true},waitForCollectionCallback=${waitForCollectionCallback ?? false}${suffix}`; + return `onyxKey=${key},waitForCollectionCallback=${waitForCollectionCallback ?? false}${suffix}`; } /** diff --git a/lib/OnyxSnapshotCache.ts b/lib/OnyxSnapshotCache.ts index d4921b716..717668492 100644 --- a/lib/OnyxSnapshotCache.ts +++ b/lib/OnyxSnapshotCache.ts @@ -58,17 +58,13 @@ class OnyxSnapshotCache { * according to their purpose and effect they produce in the useOnyx hook behavior: * * - `selector`: Different selectors produce different results, so each selector needs its own cache entry - * - `initWithStoredValues`: This flag changes the initial loading behavior and affects the returned fetch status * * Other options like `reuseConnection` don't affect the data transformation * or timing behavior of getSnapshot, so they're excluded from the cache key for better cache hit rates. */ - registerConsumer(options: Pick, 'selector' | 'initWithStoredValues'>): string { + registerConsumer(options: Pick, 'selector'>): string { const selectorID = options?.selector ? this.getSelectorID(options.selector) : 'no_selector'; - - // Create options hash without expensive JSON.stringify - const initWithStoredValues = options?.initWithStoredValues ?? true; - const cacheKey = `${selectorID}_${initWithStoredValues}`; + const cacheKey = `${selectorID}`; // Increment reference count for this cache key const currentCount = this.cacheKeyRefCounts.get(cacheKey) || 0; diff --git a/lib/OnyxUtils.ts b/lib/OnyxUtils.ts index 7f57fff82..32d46979c 100644 --- a/lib/OnyxUtils.ts +++ b/lib/OnyxUtils.ts @@ -613,9 +613,6 @@ function keysChanged( /** * When a key change happens, search for any callbacks matching the key or collection key and trigger those callbacks - * - * @example - * keyChanged(key, value, subscriber => subscriber.initWithStoredValues === false) */ function keyChanged( key: TKey, @@ -820,13 +817,11 @@ function retryOperation(error: Error, on * Notifies subscribers and writes current value to cache */ function broadcastUpdate(key: TKey, value: OnyxValue, hasChanged?: boolean): void { - // Update subscribers if the cached value has changed, or when the subscriber specifically requires - // all updates regardless of value changes (indicated by initWithStoredValues set to false). if (hasChanged) { cache.set(key, value); } - keyChanged(key, value, (subscriber) => hasChanged || subscriber?.initWithStoredValues === false); + keyChanged(key, value, () => !!hasChanged); } function hasPendingMergeForKey(key: OnyxKey): boolean { @@ -1070,10 +1065,6 @@ function subscribeToKey(connectOptions: ConnectOptions = Record<`${TKey}${strin /** Represents the base options used in `Onyx.connect()` method. */ // NOTE: Any changes to this type like adding or removing options must be accounted in OnyxConnectionManager's `generateConnectionID()` method! type BaseConnectOptions = { - /** If set to `false`, then the initial data will be only sent to the callback function if it changes. */ - initWithStoredValues?: boolean; - /** * If set to `false`, the connection won't be reused between other subscribers that are listening to the same Onyx key * with the same connect configurations. diff --git a/lib/useOnyx.ts b/lib/useOnyx.ts index 845013e10..7ac7233aa 100644 --- a/lib/useOnyx.ts +++ b/lib/useOnyx.ts @@ -13,12 +13,6 @@ import useLiveRef from './useLiveRef'; type UseOnyxSelector> = (data: OnyxValue | undefined) => TReturnValue; type UseOnyxOptions = { - /** - * If set to `false`, then no data will be prefilled into the component. - * @deprecated This param is going to be removed soon. Use RAM-only keys instead. - */ - initWithStoredValues?: boolean; - /** * If set to `false`, the connection won't be reused between other subscribers that are listening to the same Onyx key * with the same connect configurations. @@ -97,11 +91,10 @@ function useOnyx>( // Stores the previously result returned by the hook, containing the data from cache and the fetch status. // We initialize it to `undefined` and `loading` fetch status to simulate the initial result when the hook is loading from the cache. - // However, if `initWithStoredValues` is `false` we set the fetch status to `loaded` since we want to signal that data is ready. const resultRef = useRef>([ undefined, { - status: options?.initWithStoredValues === false ? 'loaded' : 'loading', + status: 'loading', }, ]); @@ -133,9 +126,8 @@ function useOnyx>( () => onyxSnapshotCache.registerConsumer({ selector: options?.selector, - initWithStoredValues: options?.initWithStoredValues, }), - [options?.selector, options?.initWithStoredValues], + [options?.selector], ); useEffect(() => () => onyxSnapshotCache.deregisterConsumer(key, cacheKey), [key, cacheKey]); @@ -174,10 +166,9 @@ function useOnyx>( const getSnapshot = useCallback(() => { // Check if we have any cache for this Onyx key - // Don't use cache for first connection with initWithStoredValues: false - // Also don't use cache during active data updates (when shouldGetCachedValueRef is true) + // Don't use cache during active data updates (when shouldGetCachedValueRef is true) const isFirstConnection = connectedKeyRef.current !== key; - if (!(isFirstConnection && options?.initWithStoredValues === false) && !shouldGetCachedValueRef.current) { + if (!shouldGetCachedValueRef.current) { const cachedResult = onyxSnapshotCache.getCachedResult>(key, cacheKey); if (cachedResult !== undefined) { resultRef.current = cachedResult; @@ -185,15 +176,6 @@ function useOnyx>( } } - // We return the initial result right away during the first connection if `initWithStoredValues` is set to `false`. - if (isFirstConnection && options?.initWithStoredValues === false) { - const result = resultRef.current; - - // Store result in snapshot cache - onyxSnapshotCache.setCachedResult>(key, cacheKey, result); - return result; - } - // We get the value from cache while the first connection to Onyx is being made or if the key has changed, // so we can return any cached value right away. For the case where the key has changed, If we don't return the cached value right away, then the UI will show the incorrect (previous) value for a brief period which looks like a UI glitch to the user. After the connection is made, we only // update `newValueRef` when `Onyx.connect()` callback is fired. @@ -255,7 +237,7 @@ function useOnyx>( } return resultRef.current; - }, [options?.initWithStoredValues, key, memoizedSelector, cacheKey]); + }, [key, memoizedSelector, cacheKey]); const subscribe = useCallback( (onStoreChange: () => void) => { @@ -266,7 +248,7 @@ function useOnyx>( previousValueRef.current = null; newValueRef.current = null; sourceValueRef.current = undefined; - resultRef.current = [undefined, {status: options?.initWithStoredValues === false ? 'loaded' : 'loading'}]; + resultRef.current = [undefined, {status: 'loading'}]; } // Force a cache re-read on every (re)subscription so any side effects from // subscribeToKey (e.g. addNullishStorageKey for skippable collection member ids) @@ -299,7 +281,6 @@ function useOnyx>( // Finally, we signal that the store changed, making `getSnapshot()` be called again. onStoreChange(); }, - initWithStoredValues: options?.initWithStoredValues, waitForCollectionCallback: OnyxKeys.isCollectionKey(key) as true, reuseConnection: options?.reuseConnection, }); @@ -315,7 +296,7 @@ function useOnyx>( onStoreChangeFnRef.current = null; }; }, - [key, options?.initWithStoredValues, options?.reuseConnection], + [key, options?.reuseConnection], ); const result = useSyncExternalStore>(subscribe, getSnapshot); diff --git a/tests/perf-test/OnyxSnapshotCache.perf-test.ts b/tests/perf-test/OnyxSnapshotCache.perf-test.ts index c80136afa..9d6aea838 100644 --- a/tests/perf-test/OnyxSnapshotCache.perf-test.ts +++ b/tests/perf-test/OnyxSnapshotCache.perf-test.ts @@ -37,12 +37,10 @@ const complexSelector: UseOnyxSelector = (data) const selectorOptions: UseOnyxOptions = { selector: simpleSelector, - initWithStoredValues: true, }; const complexSelectorOptions: UseOnyxOptions = { selector: complexSelector, - initWithStoredValues: true, }; // Mock results diff --git a/tests/perf-test/OnyxUtils.perf-test.ts b/tests/perf-test/OnyxUtils.perf-test.ts index afd03df7c..ae0df52e2 100644 --- a/tests/perf-test/OnyxUtils.perf-test.ts +++ b/tests/perf-test/OnyxUtils.perf-test.ts @@ -310,7 +310,7 @@ describe('OnyxUtils', () => { beforeEach: async () => { await Onyx.multiSet(mockedReportActionsMap); for (const key of mockedReportActionsKeys) { - const id = OnyxUtils.subscribeToKey({key, callback: jest.fn(), initWithStoredValues: false}); + const id = OnyxUtils.subscribeToKey({key, callback: jest.fn()}); subscriptionMap.set(key, id); } }, @@ -340,7 +340,7 @@ describe('OnyxUtils', () => { beforeEach: async () => { await Onyx.set(key, previousReportAction); for (let i = 0; i < 10000; i++) { - const id = OnyxUtils.subscribeToKey({key, callback: jest.fn(), initWithStoredValues: false}); + const id = OnyxUtils.subscribeToKey({key, callback: jest.fn()}); subscriptionIDs.add(id); } }, @@ -372,7 +372,7 @@ describe('OnyxUtils', () => { { beforeEach: async () => { await Onyx.multiSet(mockedReportActionsMap); - subscriptionID = OnyxUtils.subscribeToKey({key: collectionKey, callback: jest.fn(), initWithStoredValues: false}); + subscriptionID = OnyxUtils.subscribeToKey({key: collectionKey, callback: jest.fn()}); }, afterEach: async () => { if (subscriptionID) { @@ -402,7 +402,6 @@ describe('OnyxUtils', () => { subscriptionID = OnyxUtils.subscribeToKey({ key: collectionKey, callback: jest.fn(), - initWithStoredValues: false, }); OnyxUtils.getCollectionDataAndSendAsObject(mockedReportActionsKeys, { @@ -650,7 +649,6 @@ describe('OnyxUtils', () => { beforeEach: async () => { subscriptionID = OnyxUtils.subscribeToKey({ key, - initWithStoredValues: false, }); }, afterEach: clearOnyxAfterEachMeasure, @@ -692,7 +690,6 @@ describe('OnyxUtils', () => { beforeEach: async () => { subscriptionID = OnyxUtils.subscribeToKey({ key, - initWithStoredValues: false, }); }, afterEach: async () => { @@ -713,7 +710,6 @@ describe('OnyxUtils', () => { beforeEach: async () => { subscriptionID = OnyxUtils.subscribeToKey({ key, - initWithStoredValues: false, }); OnyxUtils.storeKeyBySubscriptions(key, subscriptionID); }, diff --git a/tests/perf-test/useOnyx.perf-test.tsx b/tests/perf-test/useOnyx.perf-test.tsx index 6cbc4159e..c183beb81 100644 --- a/tests/perf-test/useOnyx.perf-test.tsx +++ b/tests/perf-test/useOnyx.perf-test.tsx @@ -196,31 +196,6 @@ describe('useOnyx', () => { }); }); - describe('initWithStoredValues', () => { - /** - * Expected renders: 1. - */ - test('connecting with initWithStoredValues set to false', async () => { - const key = ONYXKEYS.TEST_KEY; - await measureRenders( - , - { - beforeEach: async () => { - await StorageMock.setItem(key, 'test'); - }, - scenario: async () => { - await screen.findByText(dataMatcher(key, undefined)); - await screen.findByText(metadataStatusMatcher(key, 'loaded')); - }, - afterEach: clearOnyxAfterEachMeasure, - }, - ); - }); - }); - describe('multiple calls', () => { /** * Expected renders: 2. diff --git a/tests/unit/OnyxConnectionManagerTest.ts b/tests/unit/OnyxConnectionManagerTest.ts index d32816e18..543dc23c1 100644 --- a/tests/unit/OnyxConnectionManagerTest.ts +++ b/tests/unit/OnyxConnectionManagerTest.ts @@ -39,23 +39,20 @@ describe('OnyxConnectionManager', () => { describe('generateConnectionID', () => { it('should generate a stable connection ID', async () => { const connectionID = generateConnectionID({key: ONYXKEYS.TEST_KEY}); - expect(connectionID).toEqual(`onyxKey=${ONYXKEYS.TEST_KEY},initWithStoredValues=true,waitForCollectionCallback=false,sessionID=${getSessionID()}`); + expect(connectionID).toEqual(`onyxKey=${ONYXKEYS.TEST_KEY},waitForCollectionCallback=false,sessionID=${getSessionID()}`); }); it("should generate a stable connection ID regardless of the order which the option's properties were passed", async () => { - const connectionID = generateConnectionID({key: ONYXKEYS.TEST_KEY, waitForCollectionCallback: true, initWithStoredValues: true}); - expect(connectionID).toEqual(`onyxKey=${ONYXKEYS.TEST_KEY},initWithStoredValues=true,waitForCollectionCallback=true,sessionID=${getSessionID()}`); + const connectionID = generateConnectionID({key: ONYXKEYS.TEST_KEY, waitForCollectionCallback: true}); + expect(connectionID).toEqual(`onyxKey=${ONYXKEYS.TEST_KEY},waitForCollectionCallback=true,sessionID=${getSessionID()}`); }); it('should generate unique connection IDs if certain options are passed', async () => { const connectionID1 = generateConnectionID({key: ONYXKEYS.TEST_KEY, reuseConnection: false}); const connectionID2 = generateConnectionID({key: ONYXKEYS.TEST_KEY, reuseConnection: false}); - expect(connectionID1.startsWith(`onyxKey=${ONYXKEYS.TEST_KEY},initWithStoredValues=true,waitForCollectionCallback=false,sessionID=${getSessionID()},uniqueID=`)).toBeTruthy(); - expect(connectionID2.startsWith(`onyxKey=${ONYXKEYS.TEST_KEY},initWithStoredValues=true,waitForCollectionCallback=false,sessionID=${getSessionID()},uniqueID=`)).toBeTruthy(); + expect(connectionID1.startsWith(`onyxKey=${ONYXKEYS.TEST_KEY},waitForCollectionCallback=false,sessionID=${getSessionID()},uniqueID=`)).toBeTruthy(); + expect(connectionID2.startsWith(`onyxKey=${ONYXKEYS.TEST_KEY},waitForCollectionCallback=false,sessionID=${getSessionID()},uniqueID=`)).toBeTruthy(); expect(connectionID1).not.toEqual(connectionID2); - - const connectionID3 = generateConnectionID({key: ONYXKEYS.TEST_KEY, initWithStoredValues: false}); - expect(connectionID3.startsWith(`onyxKey=${ONYXKEYS.TEST_KEY},initWithStoredValues=false,waitForCollectionCallback=false,sessionID=${getSessionID()},uniqueID=`)).toBeTruthy(); }); it('should generate an unique connection ID if the session ID is changed', async () => { @@ -222,43 +219,6 @@ describe('OnyxConnectionManager', () => { expect(connectionsMap.has(connection2.id)).toBeTruthy(); }); - it('should create a separate connection to the same key when setting initWithStoredValues to false', async () => { - await StorageMock.setItem(ONYXKEYS.TEST_KEY, 'test'); - - const callback1 = jest.fn(); - const connection1 = connectionManager.connect({key: ONYXKEYS.TEST_KEY, initWithStoredValues: false, callback: callback1}); - - await act(async () => waitForPromisesToResolve()); - - expect(callback1).not.toHaveBeenCalled(); - expect(connectionsMap.size).toEqual(1); - expect(connectionsMap.has(connection1.id)).toBeTruthy(); - - await Onyx.set(ONYXKEYS.TEST_KEY, 'test2'); - - expect(callback1).toHaveBeenCalledTimes(1); - expect(callback1).toHaveBeenCalledWith('test2', ONYXKEYS.TEST_KEY); - - const callback2 = jest.fn(); - const connection2 = connectionManager.connect({key: ONYXKEYS.TEST_KEY, initWithStoredValues: false, callback: callback2}); - - await act(async () => waitForPromisesToResolve()); - - expect(callback2).not.toHaveBeenCalled(); - expect(connectionsMap.size).toEqual(2); - expect(connectionsMap.has(connection2.id)).toBeTruthy(); - - await Onyx.set(ONYXKEYS.TEST_KEY, 'test3'); - - expect(callback2).toHaveBeenCalledTimes(1); - expect(callback2).toHaveBeenCalledWith('test3', ONYXKEYS.TEST_KEY); - - connectionManager.disconnect(connection1); - connectionManager.disconnect(connection2); - - expect(connectionsMap.size).toEqual(0); - }); - it("should create a separate connection to the same key when it's a collection one and waitForCollectionCallback is undefined/false", async () => { const collection = { [`${ONYXKEYS.COLLECTION.TEST_KEY}entry1`]: {id: 'entry1_id', name: 'entry1_name'}, diff --git a/tests/unit/OnyxSnapshotCacheTest.ts b/tests/unit/OnyxSnapshotCacheTest.ts index 21c6e5238..2ccd35754 100644 --- a/tests/unit/OnyxSnapshotCacheTest.ts +++ b/tests/unit/OnyxSnapshotCacheTest.ts @@ -38,22 +38,20 @@ describe('OnyxSnapshotCache', () => { }; const optionsWithSelector: UseOnyxOptions = { selector, - initWithStoredValues: true, - }; - const optionsWithoutSelector: UseOnyxOptions = { - initWithStoredValues: false, }; + const optionsWithoutSelector: UseOnyxOptions = {}; const keyWithSelector = cache.registerConsumer(optionsWithSelector); const keyWithoutSelector = cache.registerConsumer(optionsWithoutSelector); const keyWithUndefined = cache.registerConsumer({}); // Different option combinations should produce different cache keys - expect(keyWithSelector).toContain('0_'); // Should contain selector ID + expect(keyWithSelector).toContain('0'); // Should contain selector ID expect(keyWithoutSelector).toContain('no_selector'); // Should indicate no selector expect(keyWithUndefined).toContain('no_selector'); // Should indicate no selector - // All keys should be unique - expect(new Set([keyWithSelector, keyWithoutSelector, keyWithUndefined]).size).toBe(3); + // Selector key is unique; the two no-selector keys are equal + expect(keyWithSelector).not.toEqual(keyWithoutSelector); + expect(keyWithoutSelector).toEqual(keyWithUndefined); }); it('should store and retrieve cached results', () => { diff --git a/tests/unit/onyxClearNativeStorageTest.ts b/tests/unit/onyxClearNativeStorageTest.ts index 2a4979fda..902445870 100644 --- a/tests/unit/onyxClearNativeStorageTest.ts +++ b/tests/unit/onyxClearNativeStorageTest.ts @@ -34,7 +34,6 @@ describe('Set data while storage is clearing', () => { }); connection = Onyx.connect({ key: ONYX_KEYS.DEFAULT_KEY, - initWithStoredValues: false, callback: (val) => (onyxValue = val), }); return waitForPromisesToResolve(); @@ -86,7 +85,6 @@ describe('Set data while storage is clearing', () => { let regularKeyOnyxValue: unknown; Onyx.connect({ key: ONYX_KEYS.REGULAR_KEY, - initWithStoredValues: false, callback: (val) => (regularKeyOnyxValue = val), }); Onyx.set(ONYX_KEYS.REGULAR_KEY, SET_VALUE).then(() => { diff --git a/tests/unit/onyxClearWebStorageTest.ts b/tests/unit/onyxClearWebStorageTest.ts index 5089cc366..a9629ab3c 100644 --- a/tests/unit/onyxClearWebStorageTest.ts +++ b/tests/unit/onyxClearWebStorageTest.ts @@ -36,7 +36,6 @@ describe('Set data while storage is clearing', () => { }); connection = Onyx.connect({ key: ONYX_KEYS.DEFAULT_KEY, - initWithStoredValues: false, callback: (val) => (onyxValue = val), }); return waitForPromisesToResolve(); @@ -90,7 +89,6 @@ describe('Set data while storage is clearing', () => { let regularKeyOnyxValue: unknown; Onyx.connect({ key: ONYX_KEYS.REGULAR_KEY, - initWithStoredValues: false, callback: (val) => (regularKeyOnyxValue = val), }); Onyx.set(ONYX_KEYS.REGULAR_KEY, SET_VALUE).then(() => { diff --git a/tests/unit/onyxTest.ts b/tests/unit/onyxTest.ts index 5247cfc34..5ff5d6f96 100644 --- a/tests/unit/onyxTest.ts +++ b/tests/unit/onyxTest.ts @@ -92,7 +92,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -109,7 +108,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -132,7 +130,6 @@ describe('Onyx', () => { key: ONYX_KEYS.TEST_KEY, callback: mockCallback, // True is the default, just setting it here to be explicit - initWithStoredValues: true, }); return Onyx.set(ONYX_KEYS.TEST_KEY, 'test').then(() => { @@ -145,7 +142,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -166,7 +162,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -187,7 +182,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -204,7 +198,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -222,7 +215,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.TEST_KEY, - initWithStoredValues: false, waitForCollectionCallback: true, callback: (value) => { testKeyValue = value; @@ -240,7 +232,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -256,7 +247,6 @@ describe('Onyx', () => { let testKeyValue: unknown; connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -324,7 +314,6 @@ describe('Onyx', () => { let testKeyValue: unknown; connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -348,7 +337,6 @@ describe('Onyx', () => { let testKeyValue: unknown; connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -369,7 +357,6 @@ describe('Onyx', () => { let testKeyValue: unknown; connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -385,7 +372,6 @@ describe('Onyx', () => { let testKeyValue: unknown; connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -402,7 +388,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -463,7 +448,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -511,7 +495,6 @@ describe('Onyx', () => { let testKeyValue: unknown; connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -520,7 +503,6 @@ describe('Onyx', () => { let otherTestKeyValue: unknown; connection = Onyx.connect({ key: ONYX_KEYS.OTHER_TEST, - initWithStoredValues: false, callback: (value) => { otherTestKeyValue = value; }, @@ -570,7 +552,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -617,7 +598,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.TEST_KEY, - initWithStoredValues: false, callback: (value) => (result = value), waitForCollectionCallback: true, }); @@ -652,7 +632,6 @@ describe('Onyx', () => { let testKeyValue: unknown; connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -668,7 +647,6 @@ describe('Onyx', () => { let testKeyValue: unknown; connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -680,14 +658,17 @@ describe('Onyx', () => { }); }); - it('should properly set and merge when using mergeCollection', () => { + it('should properly set and merge when using mergeCollection', async () => { const valuesReceived: Record = {}; - const mockCallback = jest.fn((data) => (valuesReceived[data.ID] = data.value)); + const mockCallback = jest.fn(); connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.TEST_KEY, - initWithStoredValues: false, callback: mockCallback, }); + await waitForPromisesToResolve(); + + mockCallback.mockReset(); + mockCallback.mockImplementation((data) => (valuesReceived[data.ID] = data.value)); // The first time we call mergeCollection we'll be doing a multiSet internally return Onyx.mergeCollection(ONYX_KEYS.COLLECTION.TEST_KEY, { @@ -749,7 +730,6 @@ describe('Onyx', () => { const valuesReceived: Record = {}; connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.TEST_KEY, - initWithStoredValues: false, callback: (data, key) => (valuesReceived[key] = data), }); @@ -762,7 +742,6 @@ describe('Onyx', () => { const valuesReceived: Record = {}; connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.TEST_KEY, - initWithStoredValues: false, callback: (data, key) => (valuesReceived[key] = data), }); @@ -887,7 +866,6 @@ describe('Onyx', () => { let testKeyValue: unknown; connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -896,7 +874,6 @@ describe('Onyx', () => { let otherTestKeyValue: unknown; connection = Onyx.connect({ key: ONYX_KEYS.OTHER_TEST, - initWithStoredValues: false, callback: (value) => { otherTestKeyValue = value; }, @@ -936,15 +913,17 @@ describe('Onyx', () => { it('should use update data object to merge a collection of keys', () => { const valuesReceived: Record = {}; - const mockCallback = jest.fn((data) => (valuesReceived[data.ID] = data.value)); + const mockCallback = jest.fn(); connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.TEST_KEY, - initWithStoredValues: false, callback: mockCallback, }); return waitForPromisesToResolve() .then(() => { + mockCallback.mockReset(); + mockCallback.mockImplementation((data) => (valuesReceived[data.ID] = data.value)); + // Given the initial Onyx state: {test_1: {existingData: 'test',}, test_2: {existingData: 'test',}} Onyx.multiSet({ test_1: { @@ -1012,7 +991,6 @@ describe('Onyx', () => { const valuesReceived: Record = {}; connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.TEST_KEY, - initWithStoredValues: false, callback: (data, key) => (valuesReceived[key] = data), }); @@ -1228,47 +1206,6 @@ describe('Onyx', () => { ); }); - it('should update subscriber if the value in the cache has not changed at all but initWithStoredValues === false', () => { - const mockCallback = jest.fn(); - const collectionUpdate = { - testPolicy_1: {ID: 234, value: 'one'}, - }; - - // Given an Onyx.connect call with waitForCollectionCallback=true - connection = Onyx.connect({ - key: ONYX_KEYS.COLLECTION.TEST_POLICY, - waitForCollectionCallback: true, - callback: mockCallback, - initWithStoredValues: false, - }); - return ( - waitForPromisesToResolve() - // When merge is called with an updated collection - .then(() => Onyx.merge(`${ONYX_KEYS.COLLECTION.TEST_POLICY}${1}`, collectionUpdate.testPolicy_1)) - .then(() => { - // Then we expect the callback to have called once. 0 times the initial connect call + 1 time for the merge() - expect(mockCallback).toHaveBeenCalledTimes(1); - - // And the value for the second call should be collectionUpdate - expect(mockCallback).toHaveBeenNthCalledWith(1, collectionUpdate, ONYX_KEYS.COLLECTION.TEST_POLICY, {testPolicy_1: collectionUpdate.testPolicy_1}); - }) - - // When merge is called again with the same collection not modified - .then(() => Onyx.merge(`${ONYX_KEYS.COLLECTION.TEST_POLICY}${1}`, collectionUpdate.testPolicy_1)) - .then(() => { - // Then we should expect another invocation of the callback because initWithStoredValues = false - expect(mockCallback).toHaveBeenCalledTimes(2); - }) - - // When merge is called again with an object of equivalent value but not the same reference - .then(() => Onyx.merge(`${ONYX_KEYS.COLLECTION.TEST_POLICY}${1}`, lodashClone(collectionUpdate.testPolicy_1))) - .then(() => { - // Then we should expect another invocation of the callback because initWithStoredValues = false - expect(mockCallback).toHaveBeenCalledTimes(3); - }) - ); - }); - it('should return a promise that completes when all update() operations are done', () => { const connections: Connection[] = []; @@ -1308,7 +1245,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -1339,7 +1275,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -1366,7 +1301,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -1392,7 +1326,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -1418,7 +1351,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -1444,7 +1376,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -1480,7 +1411,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.TEST_KEY, - initWithStoredValues: false, callback: (value) => (result = value), waitForCollectionCallback: true, }); @@ -1837,7 +1767,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -2271,7 +2200,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.ROUTES, - initWithStoredValues: false, callback: (value) => { routesCollection = value; }, @@ -2311,7 +2239,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.ROUTES, - initWithStoredValues: false, callback: (value) => { routesCollection = value; }, @@ -2690,7 +2617,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => (result = value), }); @@ -2746,7 +2672,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.TEST_KEY, - initWithStoredValues: false, callback: (value) => { testKeyValue = value; }, @@ -2810,7 +2735,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.ROUTES, - initWithStoredValues: false, callback: (value) => (result = value), waitForCollectionCallback: true, }); @@ -2839,13 +2763,19 @@ describe('Onyx', () => { it('should replace the collection with empty values', async () => { let result: OnyxCollection; const routeA = `${ONYX_KEYS.COLLECTION.ROUTES}A`; + const callback = jest.fn(); connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.ROUTES, - initWithStoredValues: false, - callback: (value) => (result = value), + callback, waitForCollectionCallback: true, }); + await waitForPromisesToResolve(); + + callback.mockReset(); + callback.mockImplementation((value) => { + result = value; + }); await Onyx.mergeCollection(ONYX_KEYS.COLLECTION.ROUTES, { [routeA]: {name: 'Route A'}, @@ -2863,7 +2793,6 @@ describe('Onyx', () => { connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.ROUTES, - initWithStoredValues: false, callback: (value) => (result = value), waitForCollectionCallback: true, }); @@ -2935,7 +2864,6 @@ describe('Onyx', () => { let testKeyValue: unknown; connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.TEST_KEY, - initWithStoredValues: false, waitForCollectionCallback: true, callback: (value) => { testKeyValue = value; @@ -2954,7 +2882,6 @@ describe('Onyx', () => { let testKeyValue: unknown; connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.TEST_KEY, - initWithStoredValues: false, waitForCollectionCallback: true, callback: (value) => { testKeyValue = value; @@ -2973,7 +2900,6 @@ describe('Onyx', () => { let testKeyValue: unknown; connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.TEST_KEY, - initWithStoredValues: false, waitForCollectionCallback: true, callback: (value) => { testKeyValue = value; @@ -2996,7 +2922,6 @@ describe('Onyx', () => { let testKeyValue: unknown; connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.TEST_KEY, - initWithStoredValues: false, waitForCollectionCallback: true, callback: (value) => { testKeyValue = value; @@ -3019,7 +2944,6 @@ describe('Onyx', () => { let testKeyValue: unknown; connection = Onyx.connect({ key: ONYX_KEYS.COLLECTION.TEST_KEY, - initWithStoredValues: false, waitForCollectionCallback: true, callback: (value) => { testKeyValue = value; diff --git a/tests/unit/onyxUtilsTest.ts b/tests/unit/onyxUtilsTest.ts index b575cf78e..518f125f1 100644 --- a/tests/unit/onyxUtilsTest.ts +++ b/tests/unit/onyxUtilsTest.ts @@ -181,7 +181,6 @@ describe('OnyxUtils', () => { const connection = Onyx.connect({ key: ONYXKEYS.COLLECTION.ROUTES, - initWithStoredValues: false, callback: (value) => (result = value), waitForCollectionCallback: true, }); @@ -218,7 +217,6 @@ describe('OnyxUtils', () => { const connection = Onyx.connect({ key: ONYXKEYS.COLLECTION.ROUTES, - initWithStoredValues: false, callback: (value) => (result = value), waitForCollectionCallback: true, }); @@ -242,7 +240,6 @@ describe('OnyxUtils', () => { const connection = Onyx.connect({ key: ONYXKEYS.COLLECTION.ROUTES, - initWithStoredValues: false, callback: (value) => (result = value), waitForCollectionCallback: true, }); @@ -281,7 +278,6 @@ describe('OnyxUtils', () => { const connection = Onyx.connect({ key: entryKey, callback: callbackSpy, - initWithStoredValues: false, }); const entryData = {value: 'updated_data'}; @@ -313,7 +309,6 @@ describe('OnyxUtils', () => { const connection = await Onyx.connect({ key: entryKey, callback: callbackSpy, - initWithStoredValues: false, }); // Create partial collection data that includes our member key @@ -359,7 +354,6 @@ describe('OnyxUtils', () => { key: ONYXKEYS.COLLECTION.TEST_KEY, callback: collectionCallback, waitForCollectionCallback: true, - initWithStoredValues: false, }); await Onyx.set(entryKey, entryData); @@ -388,7 +382,6 @@ describe('OnyxUtils', () => { const connection = Onyx.connect({ key: entryKey, callback: callbackSpy, - initWithStoredValues: false, }); await waitForPromisesToResolve(); callbackSpy.mockClear(); @@ -416,9 +409,9 @@ describe('OnyxUtils', () => { const spyA = jest.fn(); const spyB = jest.fn(); const spyC = jest.fn(); - const connA = Onyx.connect({key: keyA, callback: spyA, initWithStoredValues: false}); - const connB = Onyx.connect({key: keyB, callback: spyB, initWithStoredValues: false}); - const connC = Onyx.connect({key: keyC, callback: spyC, initWithStoredValues: false}); + const connA = Onyx.connect({key: keyA, callback: spyA}); + const connB = Onyx.connect({key: keyB, callback: spyB}); + const connC = Onyx.connect({key: keyC, callback: spyC}); await waitForPromisesToResolve(); spyA.mockClear(); spyB.mockClear(); @@ -448,15 +441,16 @@ describe('OnyxUtils', () => { await Onyx.set(entryKey, entryData); - const failingCallback = jest.fn(() => { - throw new Error('subscriber failure'); - }); + const failingCallback = jest.fn(); const workingCallback = jest.fn(); - const connFailing = Onyx.connect({key: entryKey, callback: failingCallback, initWithStoredValues: false}); - const connWorking = Onyx.connect({key: entryKey, callback: workingCallback, initWithStoredValues: false}); + const connFailing = Onyx.connect({key: entryKey, callback: failingCallback, reuseConnection: false}); + const connWorking = Onyx.connect({key: entryKey, callback: workingCallback, reuseConnection: false}); await waitForPromisesToResolve(); - failingCallback.mockClear(); + failingCallback.mockReset(); + failingCallback.mockImplementation(() => { + throw new Error('subscriber failure'); + }); workingCallback.mockClear(); // Spy on Logger to verify the error is logged diff --git a/tests/unit/useOnyxTest.ts b/tests/unit/useOnyxTest.ts index 97a15115e..c5a5e8830 100644 --- a/tests/unit/useOnyxTest.ts +++ b/tests/unit/useOnyxTest.ts @@ -927,72 +927,6 @@ describe('useOnyx', () => { }); }); - describe('initWithStoredValues', () => { - it('should return `undefined` and loaded state, and after merge return updated value and loaded state', async () => { - await StorageMock.setItem(ONYXKEYS.TEST_KEY, 'test1'); - - const {result} = renderHook(() => useOnyx(ONYXKEYS.TEST_KEY, {initWithStoredValues: false})); - - await act(async () => waitForPromisesToResolve()); - - expect(result.current[0]).toBeUndefined(); - expect(result.current[1].status).toEqual('loaded'); - - await act(async () => Onyx.merge(ONYXKEYS.TEST_KEY, 'test2')); - - expect(result.current[0]).toEqual('test2'); - expect(result.current[1].status).toEqual('loaded'); - }); - - it('should return `undefined` value and loaded state if using `selector`, and after merge return selected value and loaded state', async () => { - await StorageMock.setItem(ONYXKEYS.TEST_KEY, 'test1'); - - const {result} = renderHook(() => - useOnyx(ONYXKEYS.TEST_KEY, { - initWithStoredValues: false, - selector: ((value: OnyxEntry) => `${value}_selected`) as UseOnyxSelector, - }), - ); - - await act(async () => waitForPromisesToResolve()); - - expect(result.current[0]).toBeUndefined(); - expect(result.current[1].status).toEqual('loaded'); - - await act(async () => Onyx.merge(ONYXKEYS.TEST_KEY, 'test')); - - expect(result.current[0]).toEqual('test_selected'); - expect(result.current[1].status).toEqual('loaded'); - }); - - it('should suppress stored values for the new key when switching keys with initWithStoredValues: false', async () => { - await StorageMock.setItem(ONYXKEYS.TEST_KEY, 'stored_value_one'); - await StorageMock.setItem(ONYXKEYS.TEST_KEY_2, 'stored_value_two'); - - const {result, rerender} = renderHook((key: string) => useOnyx(key, {initWithStoredValues: false}), {initialProps: ONYXKEYS.TEST_KEY as string}); - - await act(async () => waitForPromisesToResolve()); - - // initWithStoredValues: false — stored value should be suppressed - expect(result.current[0]).toBeUndefined(); - expect(result.current[1].status).toEqual('loaded'); - - rerender(ONYXKEYS.TEST_KEY_2); - - await act(async () => waitForPromisesToResolve()); - - // Stored value for the new key should also be suppressed - expect(result.current[0]).toBeUndefined(); - expect(result.current[1].status).toEqual('loaded'); - - // But live updates should still come through - await act(async () => Onyx.merge(ONYXKEYS.TEST_KEY_2, 'live_value')); - - expect(result.current[0]).toEqual('live_value'); - expect(result.current[1].status).toEqual('loaded'); - }); - }); - describe('multiple usage', () => { it('should connect to a key and load the value into cache, and return the value loaded in the next hook call', async () => { await StorageMock.setItem(ONYXKEYS.TEST_KEY, 'test'); @@ -1033,35 +967,6 @@ describe('useOnyx', () => { expect(result2.current[0]).toEqual('test'); expect(result2.current[1].status).toEqual('loaded'); }); - - it('"initWithStoredValues" should work correctly for the same key if more than one hook is using it', async () => { - await StorageMock.setItem(ONYXKEYS.TEST_KEY, 'test1'); - - const {result: result1} = renderHook(() => useOnyx(ONYXKEYS.TEST_KEY, {initWithStoredValues: false})); - - await act(async () => waitForPromisesToResolve()); - - expect(result1.current[0]).toBeUndefined(); - expect(result1.current[1].status).toEqual('loaded'); - - await act(async () => Onyx.merge(ONYXKEYS.TEST_KEY, 'test2')); - - expect(result1.current[0]).toEqual('test2'); - expect(result1.current[1].status).toEqual('loaded'); - - // Second hook - const {result: result2} = renderHook(() => useOnyx(ONYXKEYS.TEST_KEY, {initWithStoredValues: false})); - - await act(async () => waitForPromisesToResolve()); - - expect(result2.current[0]).toBeUndefined(); - expect(result2.current[1].status).toEqual('loaded'); - - await act(async () => Onyx.merge(ONYXKEYS.TEST_KEY, 'test3')); - - expect(result2.current[0]).toEqual('test3'); - expect(result2.current[1].status).toEqual('loaded'); - }); }); describe('dependencies', () => { From d83e8b75700f0c81fde0621ada17612753e37ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Henriques?= Date: Thu, 7 May 2026 09:08:07 +0100 Subject: [PATCH 2/3] Address comments --- lib/OnyxSnapshotCache.ts | 2 +- lib/OnyxUtils.ts | 7 ++++--- tests/unit/OnyxSnapshotCacheTest.ts | 12 ++++-------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/lib/OnyxSnapshotCache.ts b/lib/OnyxSnapshotCache.ts index 717668492..b1968a2ca 100644 --- a/lib/OnyxSnapshotCache.ts +++ b/lib/OnyxSnapshotCache.ts @@ -64,7 +64,7 @@ class OnyxSnapshotCache { */ registerConsumer(options: Pick, 'selector'>): string { const selectorID = options?.selector ? this.getSelectorID(options.selector) : 'no_selector'; - const cacheKey = `${selectorID}`; + const cacheKey = String(selectorID); // Increment reference count for this cache key const currentCount = this.cacheKeyRefCounts.get(cacheKey) || 0; diff --git a/lib/OnyxUtils.ts b/lib/OnyxUtils.ts index 32d46979c..b2149c947 100644 --- a/lib/OnyxUtils.ts +++ b/lib/OnyxUtils.ts @@ -817,11 +817,12 @@ function retryOperation(error: Error, on * Notifies subscribers and writes current value to cache */ function broadcastUpdate(key: TKey, value: OnyxValue, hasChanged?: boolean): void { - if (hasChanged) { - cache.set(key, value); + if (!hasChanged) { + return; } - keyChanged(key, value, () => !!hasChanged); + cache.set(key, value); + keyChanged(key, value); } function hasPendingMergeForKey(key: OnyxKey): boolean { diff --git a/tests/unit/OnyxSnapshotCacheTest.ts b/tests/unit/OnyxSnapshotCacheTest.ts index 2ccd35754..35b46a5cb 100644 --- a/tests/unit/OnyxSnapshotCacheTest.ts +++ b/tests/unit/OnyxSnapshotCacheTest.ts @@ -44,14 +44,10 @@ describe('OnyxSnapshotCache', () => { const keyWithoutSelector = cache.registerConsumer(optionsWithoutSelector); const keyWithUndefined = cache.registerConsumer({}); - // Different option combinations should produce different cache keys - expect(keyWithSelector).toContain('0'); // Should contain selector ID - expect(keyWithoutSelector).toContain('no_selector'); // Should indicate no selector - expect(keyWithUndefined).toContain('no_selector'); // Should indicate no selector - - // Selector key is unique; the two no-selector keys are equal - expect(keyWithSelector).not.toEqual(keyWithoutSelector); - expect(keyWithoutSelector).toEqual(keyWithUndefined); + // Selector cache keys are the selector ID as a string; no-selector consumers share the same key + expect(keyWithSelector).toBe('0'); + expect(keyWithoutSelector).toBe('no_selector'); + expect(keyWithUndefined).toBe('no_selector'); }); it('should store and retrieve cached results', () => { From 9f327de7ec78b012b8f9bac56244db42f93d36d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Henriques?= Date: Thu, 7 May 2026 18:43:21 +0100 Subject: [PATCH 3/3] Fix tests --- tests/unit/onyxUtilsTest.ts | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/tests/unit/onyxUtilsTest.ts b/tests/unit/onyxUtilsTest.ts index 2836e6964..cc1568365 100644 --- a/tests/unit/onyxUtilsTest.ts +++ b/tests/unit/onyxUtilsTest.ts @@ -271,7 +271,6 @@ describe('OnyxUtils', () => { key: ONYXKEYS.COLLECTION.TEST_KEY, callback: collectionCallback, waitForCollectionCallback: true, - initWithStoredValues: false, }); await waitForPromisesToResolve(); @@ -299,9 +298,9 @@ describe('OnyxUtils', () => { const spy2 = jest.fn(); const spy3 = jest.fn(); - const conn1 = Onyx.connect({key: `${ONYXKEYS.COLLECTION.TEST_KEY}1`, callback: spy1, initWithStoredValues: false}); - const conn2 = Onyx.connect({key: `${ONYXKEYS.COLLECTION.TEST_KEY}2`, callback: spy2, initWithStoredValues: false}); - const conn3 = Onyx.connect({key: `${ONYXKEYS.COLLECTION.TEST_KEY}3`, callback: spy3, initWithStoredValues: false}); + const conn1 = Onyx.connect({key: `${ONYXKEYS.COLLECTION.TEST_KEY}1`, callback: spy1}); + const conn2 = Onyx.connect({key: `${ONYXKEYS.COLLECTION.TEST_KEY}2`, callback: spy2}); + const conn3 = Onyx.connect({key: `${ONYXKEYS.COLLECTION.TEST_KEY}3`, callback: spy3}); await waitForPromisesToResolve(); spy1.mockClear(); spy2.mockClear(); @@ -333,12 +332,10 @@ describe('OnyxUtils', () => { key: ONYXKEYS.COLLECTION.TEST_KEY, callback: collectionCallback, waitForCollectionCallback: true, - initWithStoredValues: false, }); const connSingle = Onyx.connect({ key: ONYXKEYS.TEST_KEY, callback: singleKeyCallback, - initWithStoredValues: false, }); await waitForPromisesToResolve(); collectionCallback.mockClear(); @@ -369,13 +366,11 @@ describe('OnyxUtils', () => { key: ONYXKEYS.COLLECTION.TEST_KEY, callback: testCallback, waitForCollectionCallback: true, - initWithStoredValues: false, }); const connRoutes = Onyx.connect({ key: ONYXKEYS.COLLECTION.ROUTES, callback: routesCallback, waitForCollectionCallback: true, - initWithStoredValues: false, }); await waitForPromisesToResolve(); testCallback.mockClear(); @@ -408,8 +403,8 @@ describe('OnyxUtils', () => { const spy1 = jest.fn(); const spy2 = jest.fn(); - const conn1 = Onyx.connect({key: `${ONYXKEYS.COLLECTION.TEST_KEY}1`, callback: spy1, initWithStoredValues: false}); - const conn2 = Onyx.connect({key: `${ONYXKEYS.COLLECTION.TEST_KEY}2`, callback: spy2, initWithStoredValues: false}); + const conn1 = Onyx.connect({key: `${ONYXKEYS.COLLECTION.TEST_KEY}1`, callback: spy1}); + const conn2 = Onyx.connect({key: `${ONYXKEYS.COLLECTION.TEST_KEY}2`, callback: spy2}); await waitForPromisesToResolve(); spy1.mockClear(); spy2.mockClear(); @@ -437,24 +432,16 @@ describe('OnyxUtils', () => { // it receives the first member. Subsequent changed members in the same batch must NOT // trigger further callbacks for this subscriber. const callback = jest.fn(); - let connection: ReturnType; - - callback.mockImplementation(() => { - if (!connection) { - return; - } - - Onyx.disconnect(connection); - }); - - connection = Onyx.connect({ + const connection = Onyx.connect({ key: ONYXKEYS.COLLECTION.TEST_KEY, callback, waitForCollectionCallback: false, - initWithStoredValues: false, }); await waitForPromisesToResolve(); - callback.mockClear(); + callback.mockReset(); + callback.mockImplementation(() => { + Onyx.disconnect(connection); + }); await Onyx.multiSet({ [`${ONYXKEYS.COLLECTION.TEST_KEY}1`]: {id: 1}, @@ -486,12 +473,10 @@ describe('OnyxUtils', () => { const connA = Onyx.connect({ key: ONYXKEYS.TEST_KEY, callback: callbackA, - initWithStoredValues: false, }); const connB = Onyx.connect({ key: ONYXKEYS.TEST_KEY_2, callback: callbackB, - initWithStoredValues: false, }); await waitForPromisesToResolve(); callbackA.mockClear();