@@ -12,6 +12,8 @@ import { clerkMiddleware } from '../clerkMiddleware';
1212import { createRouteMatcher } from '../routeMatcher' ;
1313import { decryptClerkRequestData } from '../utils' ;
1414
15+ vi . mock ( '../clerkClient' ) ;
16+
1517const publishableKey = 'pk_test_Y2xlcmsuaW5jbHVkZWQua2F0eWRpZC05Mi5sY2wuZGV2JA' ;
1618const authenticateRequestMock = vi . fn ( ) . mockResolvedValue ( {
1719 toAuth : ( ) => ( {
@@ -21,15 +23,6 @@ const authenticateRequestMock = vi.fn().mockResolvedValue({
2123 publishableKey,
2224} ) ;
2325
24- vi . mock ( '../clerkClient' , ( ) => {
25- return {
26- clerkClient : ( ) => ( {
27- authenticateRequest : authenticateRequestMock ,
28- telemetry : { record : vi . fn ( ) } ,
29- } ) ,
30- } ;
31- } ) ;
32-
3326/**
3427 * Disable console warnings about config matchers
3528 */
@@ -45,6 +38,14 @@ afterAll(() => {
4538 global . console . log = consoleLog ;
4639} ) ;
4740
41+ beforeEach ( ( ) => {
42+ vi . mocked ( clerkClient ) . mockResolvedValue ( {
43+ authenticateRequest : authenticateRequestMock ,
44+ // @ts -expect-error - mock
45+ telemetry : { record : vi . fn ( ) } ,
46+ } ) ;
47+ } ) ;
48+
4849// Removing this mock will cause the clerkMiddleware tests to fail due to missing publishable key
4950// This mock SHOULD exist before the imports
5051vi . mock ( import ( '../constants.js' ) , async importOriginal => {
@@ -301,84 +302,121 @@ describe('clerkMiddleware(params)', () => {
301302 } ) ;
302303 } ) ;
303304
304- describe ( 'auth().redirectToSignIn()' , ( ) => {
305- it ( 'redirects to sign-in url when redirectToSignIn is called and the request is a page request' , async ( ) => {
305+ describe . each ( [
306+ {
307+ name : 'auth().redirectToSignIn()' ,
308+ util : 'redirectToSignIn' ,
309+ locationHeader : 'sign-in' ,
310+ } as const ,
311+ {
312+ name : 'auth().redirectToSignUp()' ,
313+ util : 'redirectToSignUp' ,
314+ locationHeader : 'sign-up' ,
315+ } as const ,
316+ ] ) ( '$name' , ( { util, locationHeader } ) => {
317+ it ( `redirects to ${ locationHeader } url when ${ util } is called and the request is a page request` , async ( ) => {
306318 const req = mockRequest ( {
307319 url : '/protected' ,
308320 headers : new Headers ( { [ constants . Headers . SecFetchDest ] : 'document' } ) ,
309321 appendDevBrowserCookie : true ,
310322 } ) ;
311323
312324 const resp = await clerkMiddleware ( async auth => {
313- const { redirectToSignIn } = await auth ( ) ;
314- redirectToSignIn ( ) ;
325+ ( await auth ( ) ) [ util ] ( ) ;
315326 } ) ( req , { } as NextFetchEvent ) ;
316327
317328 expect ( resp ?. status ) . toEqual ( 307 ) ;
318- expect ( resp ?. headers . get ( 'location' ) ) . toContain ( 'sign-in' ) ;
329+ expect ( resp ?. headers . get ( 'location' ) ) . toContain ( locationHeader ) ;
319330 expect ( ( await clerkClient ( ) ) . authenticateRequest ) . toBeCalled ( ) ;
320331 } ) ;
321332
322- it ( ' redirects to sign-in url when redirectToSignIn is called with the correct returnBackUrl' , async ( ) => {
333+ it ( ` redirects to ${ locationHeader } url when redirectToSignIn is called with the correct returnBackUrl` , async ( ) => {
323334 const req = mockRequest ( {
324335 url : '/protected' ,
325336 headers : new Headers ( { [ constants . Headers . SecFetchDest ] : 'document' } ) ,
326337 appendDevBrowserCookie : true ,
327338 } ) ;
328339
329340 const resp = await clerkMiddleware ( async auth => {
330- const { redirectToSignIn } = await auth ( ) ;
331- redirectToSignIn ( ) ;
341+ ( await auth ( ) ) [ util ] ( ) ;
332342 } ) ( req , { } as NextFetchEvent ) ;
333343
334- expect ( resp ?. status ) . toEqual ( 307 ) ;
335344 expect ( resp ?. status ) . toEqual ( 307 ) ;
336345 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
337346 expect ( new URL ( resp ! . headers . get ( 'location' ) ! ) . searchParams . get ( 'redirect_url' ) ) . toContain ( '/protected' ) ;
338347 expect ( ( await clerkClient ( ) ) . authenticateRequest ) . toBeCalled ( ) ;
339348 } ) ;
340349
341- it ( ' redirects to sign-in url with redirect_url set to the provided returnBackUrl param' , async ( ) => {
350+ it ( ` redirects to ${ locationHeader } url with redirect_url set to the provided returnBackUrl param` , async ( ) => {
342351 const req = mockRequest ( {
343352 url : '/protected' ,
344353 headers : new Headers ( { [ constants . Headers . SecFetchDest ] : 'document' } ) ,
345354 appendDevBrowserCookie : true ,
346355 } ) ;
347356
348357 const resp = await clerkMiddleware ( async auth => {
349- const { redirectToSignIn } = await auth ( ) ;
350- redirectToSignIn ( { returnBackUrl : 'https://www.clerk.com/hello' } ) ;
358+ ( await auth ( ) ) [ util ] ( { returnBackUrl : 'https://www.clerk.com/hello' } ) ;
351359 } ) ( req , { } as NextFetchEvent ) ;
352360
353361 expect ( resp ?. status ) . toEqual ( 307 ) ;
354- expect ( resp ?. headers . get ( 'location' ) ) . toContain ( 'sign-in' ) ;
362+ expect ( resp ?. headers . get ( 'location' ) ) . toContain ( locationHeader ) ;
355363 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
356364 expect ( new URL ( resp ! . headers . get ( 'location' ) ! ) . searchParams . get ( 'redirect_url' ) ) . toEqual (
357365 'https://www.clerk.com/hello' ,
358366 ) ;
359367 expect ( ( await clerkClient ( ) ) . authenticateRequest ) . toBeCalled ( ) ;
360368 } ) ;
361369
362- it ( ' redirects to sign-in url without a redirect_url when returnBackUrl is null' , async ( ) => {
370+ it ( ` redirects to ${ locationHeader } url without a redirect_url when returnBackUrl is null` , async ( ) => {
363371 const req = mockRequest ( {
364372 url : '/protected' ,
365373 headers : new Headers ( { [ constants . Headers . SecFetchDest ] : 'document' } ) ,
366374 appendDevBrowserCookie : true ,
367375 } ) ;
368376
369377 const resp = await clerkMiddleware ( async auth => {
370- const { redirectToSignIn } = await auth ( ) ;
371- redirectToSignIn ( { returnBackUrl : null } ) ;
378+ ( await auth ( ) ) [ util ] ( { returnBackUrl : null } ) ;
372379 } ) ( req , { } as NextFetchEvent ) ;
373380
374381 expect ( resp ?. status ) . toEqual ( 307 ) ;
375- expect ( resp ?. headers . get ( 'location' ) ) . toContain ( 'sign-in' ) ;
382+ expect ( resp ?. headers . get ( 'location' ) ) . toContain ( locationHeader ) ;
376383 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
377384 expect ( new URL ( resp ! . headers . get ( 'location' ) ! ) . searchParams . get ( 'redirect_url' ) ) . toBeNull ( ) ;
378385 expect ( ( await clerkClient ( ) ) . authenticateRequest ) . toBeCalled ( ) ;
379386 } ) ;
380387 } ) ;
381388
389+ describe ( 'auth().redirectToSignUp()' , ( ) => {
390+ it ( 'to support signInOrUp' , async ( ) => {
391+ vi . mocked ( clerkClient ) . mockResolvedValue ( {
392+ authenticateRequest : vi . fn ( ) . mockResolvedValue ( {
393+ toAuth : ( ) => ( {
394+ debug : ( d : any ) => d ,
395+ } ) ,
396+ headers : new Headers ( ) ,
397+ publishableKey,
398+ signInUrl : '/hello' ,
399+ } ) ,
400+ // @ts -expect-error - mock
401+ telemetry : { record : vi . fn ( ) } ,
402+ } ) ;
403+
404+ const req = mockRequest ( {
405+ url : '/protected' ,
406+ headers : new Headers ( { [ constants . Headers . SecFetchDest ] : 'document' } ) ,
407+ appendDevBrowserCookie : true ,
408+ } ) ;
409+
410+ const resp = await clerkMiddleware ( async auth => {
411+ ( await auth ( ) ) . redirectToSignUp ( ) ;
412+ } ) ( req , { } as NextFetchEvent ) ;
413+
414+ expect ( resp ?. status ) . toEqual ( 307 ) ;
415+ expect ( resp ?. headers . get ( 'location' ) ) . toContain ( `/hello/create` ) ;
416+ expect ( ( await clerkClient ( ) ) . authenticateRequest ) . toBeCalled ( ) ;
417+ } ) ;
418+ } ) ;
419+
382420 describe ( 'auth.protect()' , ( ) => {
383421 it ( 'redirects to sign-in url when protect is called, the user is signed out and the request is a page request' , async ( ) => {
384422 const req = mockRequest ( {
0 commit comments