Skip to content

Commit 40665ed

Browse files
committed
address review feedback
1 parent b1959fd commit 40665ed

3 files changed

Lines changed: 190 additions & 3 deletions

File tree

src/libs/actions/Session/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1331,7 +1331,7 @@ function validateTwoFactorAuth(twoFactorAuthCode: string, shouldClearData: boole
13311331
// Clear onyx data if the user has just signed in and is forced to add 2FA
13321332
if (shouldClearData) {
13331333
const keysToPreserveWithPrivatePersonalDetails = [...KEYS_TO_PRESERVE, ONYXKEYS.PRIVATE_PERSONAL_DETAILS];
1334-
Onyx.clear(keysToPreserveWithPrivatePersonalDetails).then(() => updateAuthTokenAndOpenApp(response.authToken, response.encryptedAuthToken));
1334+
clearOnyxAndSeedFullReconnect(keysToPreserveWithPrivatePersonalDetails).then(() => updateAuthTokenAndOpenApp(response.authToken, response.encryptedAuthToken));
13351335
return;
13361336
}
13371337

src/libs/actions/clearOnyxAndSeedFullReconnect.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import Onyx from 'react-native-onyx';
2-
import type {OnyxKey} from 'react-native-onyx';
3-
import type {OnyxMultiSetInput} from 'react-native-onyx/dist/types';
2+
import type {OnyxKey, OnyxMultiSetInput} from 'react-native-onyx';
43
import DateUtils from '@libs/DateUtils';
54
import ONYXKEYS from '@src/ONYXKEYS';
65

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
import Onyx from 'react-native-onyx';
2+
import clearOnyxAndSeedFullReconnect from '@libs/actions/clearOnyxAndSeedFullReconnect';
3+
import DateUtils from '@libs/DateUtils';
4+
import CONST from '@src/CONST';
5+
import OnyxUpdateManager from '@src/libs/actions/OnyxUpdateManager';
6+
import ONYXKEYS from '@src/ONYXKEYS';
7+
import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
8+
9+
OnyxUpdateManager();
10+
11+
describe('actions/clearOnyxAndSeedFullReconnect', () => {
12+
beforeAll(() => {
13+
Onyx.init({keys: ONYXKEYS});
14+
});
15+
16+
beforeEach(async () => {
17+
await Onyx.clear();
18+
await waitForBatchedUpdates();
19+
});
20+
21+
it('seeds LAST_FULL_RECONNECT_TIME with the current DB time so subscribeToFullReconnect does not fire a duplicate ReconnectApp before OpenApp successData arrives', async () => {
22+
await Onyx.set(ONYXKEYS.LAST_FULL_RECONNECT_TIME, null);
23+
await waitForBatchedUpdates();
24+
25+
const before = DateUtils.getDBTime();
26+
await clearOnyxAndSeedFullReconnect([]);
27+
await waitForBatchedUpdates();
28+
29+
await new Promise<void>((resolve) => {
30+
const connection = Onyx.connect({
31+
key: ONYXKEYS.LAST_FULL_RECONNECT_TIME,
32+
callback: (value) => {
33+
expect(typeof value).toBe('string');
34+
expect((value ?? '').length > 0).toBe(true);
35+
expect((value ?? '') >= before).toBe(true);
36+
Onyx.disconnect(connection);
37+
resolve();
38+
},
39+
});
40+
});
41+
});
42+
43+
it('preserves keys passed in keysToPreserve and clears everything else', async () => {
44+
await Onyx.multiSet({
45+
[ONYXKEYS.SESSION]: {accountID: 1, authToken: 'preserved-auth-token'},
46+
[ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
47+
});
48+
await waitForBatchedUpdates();
49+
50+
await clearOnyxAndSeedFullReconnect([ONYXKEYS.SESSION]);
51+
await waitForBatchedUpdates();
52+
53+
await new Promise<void>((resolve) => {
54+
const connection = Onyx.connect({
55+
key: ONYXKEYS.SESSION,
56+
callback: (value) => {
57+
expect(value?.authToken).toBe('preserved-auth-token');
58+
Onyx.disconnect(connection);
59+
resolve();
60+
},
61+
});
62+
});
63+
64+
await new Promise<void>((resolve) => {
65+
const connection = Onyx.connect({
66+
key: ONYXKEYS.NVP_PRIORITY_MODE,
67+
callback: (value) => {
68+
expect(value).toBeUndefined();
69+
Onyx.disconnect(connection);
70+
resolve();
71+
},
72+
});
73+
});
74+
});
75+
76+
it('applies extraSeeds atomically and keeps seeded keys after the clear', async () => {
77+
await Onyx.set(ONYXKEYS.IS_LOADING_APP, false);
78+
await waitForBatchedUpdates();
79+
80+
await clearOnyxAndSeedFullReconnect([], {
81+
[ONYXKEYS.IS_LOADING_APP]: true,
82+
});
83+
await waitForBatchedUpdates();
84+
85+
await new Promise<void>((resolve) => {
86+
const connection = Onyx.connect({
87+
key: ONYXKEYS.IS_LOADING_APP,
88+
callback: (value) => {
89+
expect(value).toBe(true);
90+
Onyx.disconnect(connection);
91+
resolve();
92+
},
93+
});
94+
});
95+
96+
await new Promise<void>((resolve) => {
97+
const connection = Onyx.connect({
98+
key: ONYXKEYS.LAST_FULL_RECONNECT_TIME,
99+
callback: (value) => {
100+
expect(typeof value).toBe('string');
101+
expect((value ?? '').length > 0).toBe(true);
102+
Onyx.disconnect(connection);
103+
resolve();
104+
},
105+
});
106+
});
107+
});
108+
109+
it('does not let extraSeeds override the LAST_FULL_RECONNECT_TIME seed', async () => {
110+
// Caller tries to override the timestamp seed with an empty string — the helper must win.
111+
await clearOnyxAndSeedFullReconnect([], {
112+
[ONYXKEYS.LAST_FULL_RECONNECT_TIME]: '',
113+
});
114+
await waitForBatchedUpdates();
115+
116+
await new Promise<void>((resolve) => {
117+
const connection = Onyx.connect({
118+
key: ONYXKEYS.LAST_FULL_RECONNECT_TIME,
119+
callback: (value) => {
120+
expect(typeof value).toBe('string');
121+
expect((value ?? '').length > 0).toBe(true);
122+
Onyx.disconnect(connection);
123+
resolve();
124+
},
125+
});
126+
});
127+
});
128+
129+
it('clears keys that were not in keysToPreserve and were not seeded', async () => {
130+
await Onyx.multiSet({
131+
[ONYXKEYS.SESSION]: {accountID: 1, authToken: 'preserved-auth-token'},
132+
[ONYXKEYS.IS_LOADING_APP]: false,
133+
[ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
134+
[ONYXKEYS.HAS_LOADED_APP]: true,
135+
});
136+
await waitForBatchedUpdates();
137+
138+
// Preserve SESSION, seed IS_LOADING_APP, leave the rest to be cleared.
139+
await clearOnyxAndSeedFullReconnect([ONYXKEYS.SESSION], {
140+
[ONYXKEYS.IS_LOADING_APP]: true,
141+
});
142+
await waitForBatchedUpdates();
143+
144+
await new Promise<void>((resolve) => {
145+
const connection = Onyx.connect({
146+
key: ONYXKEYS.NVP_PRIORITY_MODE,
147+
callback: (value) => {
148+
expect(value).toBeUndefined();
149+
Onyx.disconnect(connection);
150+
resolve();
151+
},
152+
});
153+
});
154+
155+
await new Promise<void>((resolve) => {
156+
const connection = Onyx.connect({
157+
key: ONYXKEYS.HAS_LOADED_APP,
158+
callback: (value) => {
159+
expect(value).toBeUndefined();
160+
Onyx.disconnect(connection);
161+
resolve();
162+
},
163+
});
164+
});
165+
166+
await new Promise<void>((resolve) => {
167+
const connection = Onyx.connect({
168+
key: ONYXKEYS.SESSION,
169+
callback: (value) => {
170+
expect(value?.authToken).toBe('preserved-auth-token');
171+
Onyx.disconnect(connection);
172+
resolve();
173+
},
174+
});
175+
});
176+
177+
await new Promise<void>((resolve) => {
178+
const connection = Onyx.connect({
179+
key: ONYXKEYS.IS_LOADING_APP,
180+
callback: (value) => {
181+
expect(value).toBe(true);
182+
Onyx.disconnect(connection);
183+
resolve();
184+
},
185+
});
186+
});
187+
});
188+
});

0 commit comments

Comments
 (0)