@@ -10,12 +10,14 @@ import type {WithOnyxInstance} from '../../lib/withOnyx/types';
1010import type GenericCollection from '../utils/GenericCollection' ;
1111import waitForPromisesToResolve from '../utils/waitForPromisesToResolve' ;
1212
13- // We need access to `connectionsMap` and `generateConnectionID ` during the tests but the properties are private,
13+ // We need access to some internal properties of `connectionManager ` during the tests but they are private,
1414// so this workaround allows us to have access to them.
1515// eslint-disable-next-line dot-notation
1616const connectionsMap = connectionManager [ 'connectionsMap' ] ;
1717// eslint-disable-next-line dot-notation
1818const generateConnectionID = connectionManager [ 'generateConnectionID' ] ;
19+ // eslint-disable-next-line dot-notation
20+ const getSessionID = ( ) => connectionManager [ 'sessionID' ] ;
1921
2022function generateEmptyWithOnyxInstance ( ) {
2123 return new ( class {
@@ -51,31 +53,39 @@ describe('OnyxConnectionManager', () => {
5153 describe ( 'generateConnectionID' , ( ) => {
5254 it ( 'should generate a stable connection ID' , async ( ) => {
5355 const connectionID = generateConnectionID ( { key : ONYXKEYS . TEST_KEY } ) ;
54- expect ( connectionID ) . toEqual ( `onyxKey=${ ONYXKEYS . TEST_KEY } ,initWithStoredValues=true,waitForCollectionCallback=false` ) ;
56+ expect ( connectionID ) . toEqual ( `onyxKey=${ ONYXKEYS . TEST_KEY } ,initWithStoredValues=true,waitForCollectionCallback=false,sessionID= ${ getSessionID ( ) } ` ) ;
5557 } ) ;
5658
5759 it ( "should generate a stable connection ID regardless of the order which the option's properties were passed" , async ( ) => {
5860 const connectionID = generateConnectionID ( { key : ONYXKEYS . TEST_KEY , waitForCollectionCallback : true , initWithStoredValues : true } ) ;
59- expect ( connectionID ) . toEqual ( `onyxKey=${ ONYXKEYS . TEST_KEY } ,initWithStoredValues=true,waitForCollectionCallback=true` ) ;
61+ expect ( connectionID ) . toEqual ( `onyxKey=${ ONYXKEYS . TEST_KEY } ,initWithStoredValues=true,waitForCollectionCallback=true,sessionID= ${ getSessionID ( ) } ` ) ;
6062 } ) ;
6163
6264 it ( 'should generate unique connection IDs if certain options are passed' , async ( ) => {
6365 const connectionID1 = generateConnectionID ( { key : ONYXKEYS . TEST_KEY , reuseConnection : false } ) ;
6466 const connectionID2 = generateConnectionID ( { key : ONYXKEYS . TEST_KEY , reuseConnection : false } ) ;
65- expect ( connectionID1 . startsWith ( `onyxKey=${ ONYXKEYS . TEST_KEY } ,initWithStoredValues=true,waitForCollectionCallback=false,uniqueID=` ) ) . toBeTruthy ( ) ;
66- expect ( connectionID2 . startsWith ( `onyxKey=${ ONYXKEYS . TEST_KEY } ,initWithStoredValues=true,waitForCollectionCallback=false,uniqueID=` ) ) . toBeTruthy ( ) ;
67+ expect ( connectionID1 . startsWith ( `onyxKey=${ ONYXKEYS . TEST_KEY } ,initWithStoredValues=true,waitForCollectionCallback=false,sessionID= ${ getSessionID ( ) } , uniqueID=` ) ) . toBeTruthy ( ) ;
68+ expect ( connectionID2 . startsWith ( `onyxKey=${ ONYXKEYS . TEST_KEY } ,initWithStoredValues=true,waitForCollectionCallback=false,sessionID= ${ getSessionID ( ) } , uniqueID=` ) ) . toBeTruthy ( ) ;
6769 expect ( connectionID1 ) . not . toEqual ( connectionID2 ) ;
6870
6971 const connectionID3 = generateConnectionID ( { key : ONYXKEYS . TEST_KEY , initWithStoredValues : false } ) ;
70- expect ( connectionID3 . startsWith ( `onyxKey=${ ONYXKEYS . TEST_KEY } ,initWithStoredValues=false,waitForCollectionCallback=false,uniqueID=` ) ) . toBeTruthy ( ) ;
72+ expect ( connectionID3 . startsWith ( `onyxKey=${ ONYXKEYS . TEST_KEY } ,initWithStoredValues=false,waitForCollectionCallback=false,sessionID= ${ getSessionID ( ) } , uniqueID=` ) ) . toBeTruthy ( ) ;
7173
7274 const connectionID4 = generateConnectionID ( {
7375 key : ONYXKEYS . TEST_KEY ,
7476 displayName : 'Component1' ,
7577 statePropertyName : 'prop1' ,
7678 withOnyxInstance : generateEmptyWithOnyxInstance ( ) ,
7779 } as WithOnyxConnectOptions < OnyxKey > ) ;
78- expect ( connectionID4 . startsWith ( `onyxKey=${ ONYXKEYS . TEST_KEY } ,initWithStoredValues=true,waitForCollectionCallback=false,uniqueID=` ) ) . toBeTruthy ( ) ;
80+ expect ( connectionID4 . startsWith ( `onyxKey=${ ONYXKEYS . TEST_KEY } ,initWithStoredValues=true,waitForCollectionCallback=false,sessionID=${ getSessionID ( ) } ,uniqueID=` ) ) . toBeTruthy ( ) ;
81+ } ) ;
82+
83+ it ( 'should generate an unique connection ID if the session ID is changed' , async ( ) => {
84+ const connectionID1 = generateConnectionID ( { key : ONYXKEYS . TEST_KEY } ) ;
85+ connectionManager . refreshSessionID ( ) ;
86+ const connectionID2 = generateConnectionID ( { key : ONYXKEYS . TEST_KEY } ) ;
87+
88+ expect ( connectionID1 ) . not . toEqual ( connectionID2 ) ;
7989 } ) ;
8090 } ) ;
8191
@@ -320,6 +330,56 @@ describe('OnyxConnectionManager', () => {
320330 } ) . not . toThrow ( ) ;
321331 } ) ;
322332
333+ it ( 'should create a separate connection for the same key after a Onyx.clear() call' , async ( ) => {
334+ await StorageMock . setItem ( ONYXKEYS . TEST_KEY , 'test' ) ;
335+
336+ const callback1 = jest . fn ( ) ;
337+ connectionManager . connect ( { key : ONYXKEYS . TEST_KEY , callback : callback1 } ) ;
338+ expect ( connectionsMap . size ) . toEqual ( 1 ) ;
339+
340+ await act ( async ( ) => waitForPromisesToResolve ( ) ) ;
341+
342+ expect ( callback1 ) . toHaveBeenCalledTimes ( 1 ) ;
343+ expect ( callback1 ) . toHaveBeenCalledWith ( 'test' , ONYXKEYS . TEST_KEY ) ;
344+ callback1 . mockReset ( ) ;
345+
346+ await act ( async ( ) => Onyx . clear ( ) ) ;
347+
348+ expect ( callback1 ) . toHaveBeenCalledTimes ( 1 ) ;
349+ expect ( callback1 ) . toHaveBeenCalledWith ( undefined , ONYXKEYS . TEST_KEY ) ;
350+ callback1 . mockReset ( ) ;
351+
352+ const callback2 = jest . fn ( ) ;
353+ connectionManager . connect ( { key : ONYXKEYS . TEST_KEY , callback : callback2 } ) ;
354+
355+ const callback3 = jest . fn ( ) ;
356+ connectionManager . connect ( { key : ONYXKEYS . TEST_KEY , callback : callback3 } ) ;
357+
358+ // We expect to have two connections for ONYXKEYS.TEST_KEY, one for the first subscription before Onyx.clear(),
359+ // and the other for the two subscriptions with the same key after Onyx.clear().
360+ expect ( connectionsMap . size ) . toEqual ( 2 ) ;
361+
362+ await act ( async ( ) => waitForPromisesToResolve ( ) ) ;
363+
364+ expect ( callback2 ) . toHaveBeenCalledTimes ( 1 ) ;
365+ expect ( callback2 ) . toHaveBeenCalledWith ( undefined , undefined ) ;
366+ expect ( callback3 ) . toHaveBeenCalledTimes ( 1 ) ;
367+ expect ( callback3 ) . toHaveBeenCalledWith ( undefined , undefined ) ;
368+ callback1 . mockReset ( ) ;
369+ callback2 . mockReset ( ) ;
370+ callback3 . mockReset ( ) ;
371+
372+ Onyx . merge ( ONYXKEYS . TEST_KEY , 'test2' ) ;
373+ await act ( async ( ) => waitForPromisesToResolve ( ) ) ;
374+
375+ expect ( callback1 ) . toHaveBeenCalledTimes ( 1 ) ;
376+ expect ( callback1 ) . toHaveBeenCalledWith ( 'test2' , ONYXKEYS . TEST_KEY ) ;
377+ expect ( callback2 ) . toHaveBeenCalledTimes ( 1 ) ;
378+ expect ( callback2 ) . toHaveBeenCalledWith ( 'test2' , ONYXKEYS . TEST_KEY ) ;
379+ expect ( callback3 ) . toHaveBeenCalledTimes ( 1 ) ;
380+ expect ( callback3 ) . toHaveBeenCalledWith ( 'test2' , ONYXKEYS . TEST_KEY ) ;
381+ } ) ;
382+
323383 describe ( 'withOnyx' , ( ) => {
324384 it ( 'should connect to a key two times with withOnyx and create two connections instead of one' , async ( ) => {
325385 await StorageMock . setItem ( ONYXKEYS . TEST_KEY , 'test' ) ;
@@ -406,6 +466,25 @@ describe('OnyxConnectionManager', () => {
406466 } ) ;
407467 } ) ;
408468
469+ describe ( 'refreshSessionID' , ( ) => {
470+ it ( 'should create a separate connection for the same key if the session ID changes' , async ( ) => {
471+ await StorageMock . setItem ( ONYXKEYS . TEST_KEY , 'test' ) ;
472+ await StorageMock . setItem ( ONYXKEYS . TEST_KEY_2 , 'test2' ) ;
473+
474+ const connection1 = connectionManager . connect ( { key : ONYXKEYS . TEST_KEY , callback : jest . fn ( ) } ) ;
475+
476+ expect ( connectionsMap . size ) . toEqual ( 1 ) ;
477+
478+ connectionManager . refreshSessionID ( ) ;
479+
480+ const connection2 = connectionManager . connect ( { key : ONYXKEYS . TEST_KEY , callback : jest . fn ( ) } ) ;
481+
482+ expect ( connectionsMap . size ) . toEqual ( 2 ) ;
483+ expect ( connectionsMap . has ( connection1 . id ) ) . toBeTruthy ( ) ;
484+ expect ( connectionsMap . has ( connection2 . id ) ) . toBeTruthy ( ) ;
485+ } ) ;
486+ } ) ;
487+
409488 describe ( 'addToEvictionBlockList / removeFromEvictionBlockList' , ( ) => {
410489 it ( 'should add and remove connections from the eviction block list correctly' , async ( ) => {
411490 const evictionBlocklist = OnyxUtils . getEvictionBlocklist ( ) ;
0 commit comments