@@ -252,6 +252,38 @@ describe('SignInStart', () => {
252252 expect ( icon . length ) . toEqual ( 1 ) ;
253253 } ) ;
254254 } ) ;
255+
256+ it ( 'redirects user when session_exists error is returned during OAuth sign-in' , async ( ) => {
257+ const { wrapper, fixtures } = await createFixtures ( f => {
258+ f . withSocialProvider ( { provider : 'google' } ) ;
259+ } ) ;
260+
261+ const sessionExistsError = new ClerkAPIResponseError ( 'Error' , {
262+ data : [
263+ {
264+ code : 'session_exists' ,
265+ long_message : 'A session already exists' ,
266+ message : 'Session exists' ,
267+ } ,
268+ ] ,
269+ status : 422 ,
270+ } ) ;
271+
272+ fixtures . clerk . client . lastActiveSessionId = 'sess_123' ;
273+ fixtures . signIn . authenticateWithRedirect . mockRejectedValueOnce ( sessionExistsError ) ;
274+
275+ const { userEvent } = render ( < SignInStart /> , { wrapper } ) ;
276+
277+ const googleButton = screen . getByText ( 'Continue with Google' ) ;
278+ await userEvent . click ( googleButton ) ;
279+
280+ await waitFor ( ( ) => {
281+ expect ( fixtures . clerk . setActive ) . toHaveBeenCalledWith ( {
282+ session : 'sess_123' ,
283+ navigate : expect . any ( Function ) ,
284+ } ) ;
285+ } ) ;
286+ } ) ;
255287 } ) ;
256288
257289 describe ( 'navigation' , ( ) => {
@@ -523,6 +555,76 @@ describe('SignInStart', () => {
523555 } ) ;
524556 } ) ;
525557
558+ describe ( 'Session already exists error handling' , ( ) => {
559+ it ( 'redirects user when session_exists error is returned during sign-in' , async ( ) => {
560+ const { wrapper, fixtures } = await createFixtures ( f => {
561+ f . withEmailAddress ( ) ;
562+ } ) ;
563+
564+ const sessionExistsError = new ClerkAPIResponseError ( 'Error' , {
565+ data : [
566+ {
567+ code : 'session_exists' ,
568+ long_message : 'A session already exists' ,
569+ message : 'Session exists' ,
570+ } ,
571+ ] ,
572+ status : 422 ,
573+ } ) ;
574+
575+ fixtures . clerk . client . lastActiveSessionId = 'sess_123' ;
576+ fixtures . signIn . create . mockRejectedValueOnce ( sessionExistsError ) ;
577+
578+ const { userEvent } = render ( < SignInStart /> , { wrapper } ) ;
579+
580+ await userEvent . type ( screen . getByLabelText ( / e m a i l a d d r e s s / i) , '[email protected] ' ) ; 581+ await userEvent . click ( screen . getByText ( 'Continue' ) ) ;
582+
583+ await waitFor ( ( ) => {
584+ expect ( fixtures . clerk . setActive ) . toHaveBeenCalledWith ( {
585+ session : 'sess_123' ,
586+ navigate : expect . any ( Function ) ,
587+ } ) ;
588+ } ) ;
589+ } ) ;
590+
591+ it ( 'calls navigate after setting session active on session_exists error' , async ( ) => {
592+ const { wrapper, fixtures } = await createFixtures ( f => {
593+ f . withEmailAddress ( ) ;
594+ } ) ;
595+
596+ const sessionExistsError = new ClerkAPIResponseError ( 'Error' , {
597+ data : [
598+ {
599+ code : 'session_exists' ,
600+ long_message : 'A session already exists' ,
601+ message : 'Session exists' ,
602+ } ,
603+ ] ,
604+ status : 422 ,
605+ } ) ;
606+
607+ fixtures . clerk . client . lastActiveSessionId = 'sess_123' ;
608+ fixtures . signIn . create . mockRejectedValueOnce ( sessionExistsError ) ;
609+
610+ const mockSession = { id : 'sess_123' } as any ;
611+ ( fixtures . clerk . setActive as any ) . mockImplementation (
612+ async ( { navigate } : { navigate : ( { session } : { session : any } ) => Promise < void > } ) => {
613+ await navigate ( { session : mockSession } ) ;
614+ } ,
615+ ) ;
616+
617+ const { userEvent } = render ( < SignInStart /> , { wrapper } ) ;
618+
619+ await userEvent . type ( screen . getByLabelText ( / e m a i l a d d r e s s / i) , '[email protected] ' ) ; 620+ await userEvent . click ( screen . getByText ( 'Continue' ) ) ;
621+
622+ await waitFor ( ( ) => {
623+ expect ( fixtures . clerk . setActive ) . toHaveBeenCalled ( ) ;
624+ } ) ;
625+ } ) ;
626+ } ) ;
627+
526628 describe ( 'ticket flow' , ( ) => {
527629 it ( 'calls the appropriate resource function upon detecting the ticket' , async ( ) => {
528630 const { wrapper, fixtures } = await createFixtures ( f => {
0 commit comments