Skip to content

Commit a9666ec

Browse files
MelvinBotmkhutornyi
andcommitted
Treat /Home as empty route instead of guarding with route truthiness
Reverts the route truthiness guard and getAdaptedStateFromPath normalization. Instead, normalizes the /Home route to empty string early in openReportFromDeepLink, matching the existing pattern for /signin route handling. This prevents the "not found" page when React Navigation generates /Home for the root URL. Co-authored-by: mkhutornyi <mkhutornyi@users.noreply.github.com>
1 parent f9b88ee commit a9666ec

3 files changed

Lines changed: 7 additions & 32 deletions

File tree

src/libs/Navigation/helpers/getAdaptedStateFromPath.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -411,12 +411,6 @@ const getAdaptedStateFromPath: GetAdaptedStateFromPath = (path, options, shouldR
411411
normalizedPath = '/';
412412
}
413413

414-
// React Navigation generates /Home (capitalized) for the sign-in page because PublicScreens uses SCREENS.HOME ('Home')
415-
// at the root level without a path mapping. Normalize it to the correct lowercase route to avoid “not found” pages.
416-
if (normalizedPath.toLowerCase() === `/${ROUTES.HOME}`) {
417-
normalizedPath = `/${ROUTES.HOME}`;
418-
}
419-
420414
const state = getStateFromPath(normalizedPath as RoutePath) as PartialState<NavigationState<RootNavigatorParamList>>;
421415
if (shouldReplacePathInNestedState) {
422416
replacePathInNestedState(state, normalizedPath);

src/libs/actions/Link.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,12 @@ function openReportFromDeepLink(
262262
route = '';
263263
}
264264

265+
// React Navigation generates /Home (capitalized) for the root URL because PublicScreens uses SCREENS.HOME ('Home')
266+
// at the root level without a path mapping. Treat it as empty route to avoid showing a “not found” page after sign-in.
267+
if (normalizePath(route).toLowerCase() === `/${ROUTES.HOME}`) {
268+
route = '';
269+
}
270+
265271
// If we are not authenticated and are navigating to a public screen, we don't want to navigate again to the screen after sign-in/sign-up
266272
if (!isAuthenticated && isPublicScreenRoute(route)) {
267273
return;
@@ -364,11 +370,7 @@ function openReportFromDeepLink(
364370
}
365371
};
366372

367-
// Guard deeplink navigation with a route truthiness check to prevent navigating to an
368-
// empty route when the user visits the root URL (e.g. new.expensify.com) and then signs in.
369-
// Without this, hasCompletedGuidedSetupFlowSelector returns true for empty onboarding objects
370-
// and Navigation.navigate('') fires, showing a "not found" page.
371-
if ((route && hasCompletedGuidedSetupFlowSelector(val)) || isAnonymousUser()) {
373+
if (hasCompletedGuidedSetupFlowSelector(val) || isAnonymousUser()) {
372374
handleDeeplinkNavigation();
373375
}
374376
});

tests/unit/OnboardingSelectorsTest.ts

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,6 @@ describe('onboardingSelectors', () => {
77
// Not all users have this NVP defined as we did not run a migration to backfill it for existing accounts, hence we need to make sure
88
// the onboarding flow is only showed to the users with `hasCompletedGuidedSetupFlow` set to false
99
describe('hasCompletedGuidedSetupFlowSelector', () => {
10-
// Regression test: hasCompletedGuidedSetupFlowSelector returns true for empty onboarding objects (the pre-login default state).
11-
// The deeplink guard in Link.ts must combine this with a route truthiness check to prevent navigating to an empty route
12-
// when the user visits the root URL and signs in (issue #90880).
13-
it('Should return true for empty onboarding (pre-login default), confirming the need for a route check in deeplink navigation', () => {
14-
const emptyOnboarding = {} as OnyxValue<typeof ONYXKEYS.NVP_ONBOARDING>;
15-
const selectorResult = hasCompletedGuidedSetupFlowSelector(emptyOnboarding);
16-
17-
// The selector returns true for empty objects (old/migrated accounts), which is correct for its own purpose.
18-
expect(selectorResult).toBe(true);
19-
20-
// The deeplink guard must NOT navigate when the route is empty (root URL produces ''),
21-
// even if the selector returns true. This is the condition from openReportFromDeepLink:
22-
// (route && hasCompletedGuidedSetupFlowSelector(val))
23-
const emptyRoute = ''; // root URL produces empty string via getRouteFromLink
24-
expect(emptyRoute && selectorResult).toBeFalsy();
25-
26-
// But when a real deeplink route exists, navigation should proceed
27-
const deeplinkRoute = 'concierge';
28-
expect(deeplinkRoute && selectorResult).toBeTruthy();
29-
});
30-
3110
it('Should return true if onboarding NVP is an empty object', () => {
3211
const onboarding = {} as OnyxValue<typeof ONYXKEYS.NVP_ONBOARDING>;
3312
expect(hasCompletedGuidedSetupFlowSelector(onboarding)).toBe(true);

0 commit comments

Comments
 (0)