@@ -6,6 +6,8 @@ test.setTimeout(60_000);
66
77const framework = process . env . JOURNEY_FRAMEWORK ?? "next" ;
88const expectsProtectedRouteRedirect = framework === "next" || framework === "nuxt" ;
9+ const loginUrl = / \/ l o g i n (?: [ / ? # ] | $ ) / ;
10+ const profileUrl = / \/ p r o f i l e (?: [ / ? # ] | $ ) / ;
911
1012test ( `password-only registration, logout, and password login work in a fresh ${ framework } app` , async ( {
1113 page,
@@ -50,11 +52,10 @@ if (process.env.JOURNEY_ENABLE_PASSKEY !== "0") {
5052
5153async function expectProtectedRouteToRedirect ( page : Page ) : Promise < void > {
5254 await page . goto ( "/profile" ) ;
53- await expect ( page ) . toHaveURL ( / \/ l o g i n (?: \? | $ ) / ) ;
55+ await expect ( page ) . toHaveURL ( loginUrl ) ;
5456}
5557
5658async function gotoLogin ( page : Page ) : Promise < void > {
57- const loginUrl = / \/ l o g i n (?: \? | $ ) / ;
5859 if ( loginUrl . test ( page . url ( ) ) ) {
5960 return ;
6061 }
@@ -142,10 +143,28 @@ async function skipPasskeyUpsellIfVisible(page: Page): Promise<void> {
142143}
143144
144145async function expectSignedIn ( page : Page ) : Promise < void > {
145- await page . waitForURL ( "**/profile" , { timeout : 30_000 } ) ;
146+ if ( expectsProtectedRouteRedirect ) {
147+ await expect ( page ) . toHaveURL ( profileUrl , { timeout : 30_000 } ) ;
148+ } else {
149+ await expect ( signedInLocator ( page ) . first ( ) ) . toBeVisible ( { timeout : 30_000 } ) ;
150+ if ( ! profileUrl . test ( page . url ( ) ) ) {
151+ await gotoProfile ( page ) ;
152+ }
153+ }
146154 await expect ( signedInLocator ( page ) . first ( ) ) . toBeVisible ( { timeout : 30_000 } ) ;
147155}
148156
157+ async function gotoProfile ( page : Page ) : Promise < void > {
158+ await page . goto ( "/profile" ) . catch ( async ( error : unknown ) => {
159+ if ( ! isInterruptedByProfileNavigation ( error ) && ! profileUrl . test ( page . url ( ) ) ) {
160+ throw error ;
161+ }
162+ if ( ! profileUrl . test ( page . url ( ) ) ) {
163+ await page . waitForURL ( profileUrl , { timeout : 5000 } ) ;
164+ }
165+ } ) ;
166+ }
167+
149168async function expectSessionCookie ( page : Page ) : Promise < void > {
150169 await expect
151170 . poll (
@@ -187,8 +206,8 @@ async function logout(page: Page): Promise<void> {
187206 await expect ( logout . first ( ) ) . toBeVisible ( { timeout : 5000 } ) ;
188207 await logout . first ( ) . click ( ) ;
189208 const loggedOutUrl = expectsProtectedRouteRedirect
190- ? / \/ l o g i n (?: \? | $ ) /
191- : / \/ (?: l o g i n ) ? (?: \? | $ ) / ;
209+ ? loginUrl
210+ : / \/ (?: l o g i n ) ? (?: [ / ? # ] | $ ) / ;
192211 await expect ( page ) . toHaveURL ( loggedOutUrl ) ;
193212 await expectSessionCleared ( page ) ;
194213}
@@ -296,8 +315,22 @@ function actionLocator(page: Page, actionName: string) {
296315function isInterruptedByLoginNavigation ( error : unknown ) : boolean {
297316 return (
298317 error instanceof Error &&
299- error . message . includes ( 'interrupted by another navigation to "' ) &&
300- error . message . includes ( "/login" )
318+ isExpectedNavigationRace ( error . message , "/login" )
319+ ) ;
320+ }
321+
322+ function isInterruptedByProfileNavigation ( error : unknown ) : boolean {
323+ return (
324+ error instanceof Error &&
325+ isExpectedNavigationRace ( error . message , "/profile" )
326+ ) ;
327+ }
328+
329+ function isExpectedNavigationRace ( message : string , path : string ) : boolean {
330+ return (
331+ ( message . includes ( 'interrupted by another navigation to "' ) ||
332+ message . includes ( "net::ERR_ABORTED at " ) ) &&
333+ message . includes ( path )
301334 ) ;
302335}
303336
0 commit comments