diff --git a/packages/clerk-js/src/ui/common/__tests__/withRedirect.test.tsx b/packages/clerk-js/src/ui/common/__tests__/withRedirect.test.tsx index e823455c560..793b4d0e9fc 100644 --- a/packages/clerk-js/src/ui/common/__tests__/withRedirect.test.tsx +++ b/packages/clerk-js/src/ui/common/__tests__/withRedirect.test.tsx @@ -3,6 +3,7 @@ import React from 'react'; import { render } from '../../../testUtils'; import { bindCreateFixtures } from '../../utils/test/createFixtures'; import { withRedirect } from '../withRedirect'; +import { sessionExistsAndRedirectUrlPresent } from '../../../utils/componentGuards'; const { createFixtures } = bindCreateFixtures('SignIn'); @@ -41,3 +42,91 @@ describe('withRedirect', () => { expect(fixtures.router.navigate).not.toHaveBeenCalledWith('/'); }); }); + +describe('sessionExistsAndRedirectUrlPresent', () => { + beforeEach(() => { + // Set up window.location.href for tests + Object.defineProperty(window, 'location', { + value: { href: 'http://test.host/' }, + writable: true, + }); + }); + + it('returns true when user is signed in and redirect_url is present', async () => { + const { wrapper, fixtures } = await createFixtures(f => { + f.withUser({}); + }); + + // Mock window.location.search to include redirect_url + Object.defineProperty(window, 'location', { + value: { + href: 'http://test.host/', + search: '?redirect_url=https%3A%2F%2Fexample.com' + }, + writable: true, + }); + + const TestComponent = () =>
(Com const HOC = (props: P) => { const signInCtx = useSignInContext(); + + // Combined guard: redirect if user is signed in AND either: + // 1. Single session mode is enabled, OR + // 2. There's a redirect_url in the query parameters + const combinedGuard: ComponentGuard = (clerk, environment) => { + return sessionExistsAndSingleSessionModeEnabled(clerk, environment) || + sessionExistsAndRedirectUrlPresent(clerk); + }; + return withRedirect( Component, - sessionExistsAndSingleSessionModeEnabled, + combinedGuard, ({ clerk }) => signInCtx.sessionTaskUrl || signInCtx.afterSignInUrl || clerk.buildAfterSignInUrl(), signInCtx.sessionTaskUrl ? warnings.cannotRenderSignInComponentWhenTaskExists @@ -79,9 +88,18 @@ export const withRedirectToAfterSignUp =
(Com const HOC = (props: P) => { const signUpCtx = useSignUpContext(); + + // Combined guard: redirect if user is signed in AND either: + // 1. Single session mode is enabled, OR + // 2. There's a redirect_url in the query parameters + const combinedGuard: ComponentGuard = (clerk, environment) => { + return sessionExistsAndSingleSessionModeEnabled(clerk, environment) || + sessionExistsAndRedirectUrlPresent(clerk); + }; + return withRedirect( Component, - sessionExistsAndSingleSessionModeEnabled, + combinedGuard, ({ clerk }) => signUpCtx.sessionTaskUrl || signUpCtx.afterSignUpUrl || clerk.buildAfterSignUpUrl(), signUpCtx.sessionTaskUrl ? warnings.cannotRenderSignUpComponentWhenTaskExists diff --git a/packages/clerk-js/src/utils/componentGuards.ts b/packages/clerk-js/src/utils/componentGuards.ts index baf23904b17..d9f7a72d6aa 100644 --- a/packages/clerk-js/src/utils/componentGuards.ts +++ b/packages/clerk-js/src/utils/componentGuards.ts @@ -10,6 +10,17 @@ export const sessionExistsAndSingleSessionModeEnabled: ComponentGuard = (clerk, return !!(clerk.session && environment?.authConfig.singleSessionMode); }; +export const sessionExistsAndRedirectUrlPresent: ComponentGuard = (clerk) => { + if (!clerk.session) { + return false; + } + + const urlParams = new URLSearchParams(window.location.search); + const redirectUrl = urlParams.get('redirect_url'); + + return !!redirectUrl; +}; + export const noUserExists: ComponentGuard = clerk => { return !clerk.user; };