fix onboarding login glitch (#1118)
This commit is contained in:
		
							parent
							
								
									9befd4abb9
								
							
						
					
					
						commit
						df687009bd
					
				
					 4 changed files with 59 additions and 20 deletions
				
			
		
							
								
								
									
										1
									
								
								.github/workflows/e2e.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/e2e.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -9,6 +9,7 @@ jobs: | |||
|       DATABASE_URL: postgresql://postgres:@localhost:5432/calendso | ||||
|       BASE_URL: http://localhost:3000 | ||||
|       JWT_SECRET: secret | ||||
|       GOOGLE_API_CREDENTIALS: "{}" | ||||
|       # GOOGLE_API_CREDENTIALS: ${{ secrets.CI_GOOGLE_API_CREDENTIALS }} | ||||
|       # CRON_API_KEY: xxx | ||||
|       # CALENDSO_ENCRYPTION_KEY: xxx | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ import { | |||
| import { signOut, useSession } from "next-auth/client"; | ||||
| import Link from "next/link"; | ||||
| import { useRouter } from "next/router"; | ||||
| import React, { ReactNode, useEffect } from "react"; | ||||
| import React, { ReactNode, useEffect, useState } from "react"; | ||||
| import { Toaster } from "react-hot-toast"; | ||||
| 
 | ||||
| import LicenseBanner from "@ee/components/LicenseBanner"; | ||||
|  | @ -37,7 +37,11 @@ import { useViewerI18n } from "./I18nLanguageHandler"; | |||
| import Logo from "./Logo"; | ||||
| 
 | ||||
| function useMeQuery() { | ||||
|   const meQuery = trpc.useQuery(["viewer.me"]); | ||||
|   const meQuery = trpc.useQuery(["viewer.me"], { | ||||
|     retry(failureCount) { | ||||
|       return failureCount > 3; | ||||
|     }, | ||||
|   }); | ||||
| 
 | ||||
|   return meQuery; | ||||
| } | ||||
|  | @ -45,7 +49,6 @@ function useMeQuery() { | |||
| function useRedirectToLoginIfUnauthenticated() { | ||||
|   const [session, loading] = useSession(); | ||||
|   const router = useRouter(); | ||||
|   const query = useMeQuery(); | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     if (!loading && !session) { | ||||
|  | @ -56,28 +59,36 @@ function useRedirectToLoginIfUnauthenticated() { | |||
|         }, | ||||
|       }); | ||||
|     } | ||||
|   }, [loading, session, router]); | ||||
|     // eslint-disable-next-line react-hooks/exhaustive-deps
 | ||||
|   }, [loading, session]); | ||||
| 
 | ||||
|   if (query.status !== "loading" && !query.data) { | ||||
|     router.replace("/auth/login"); | ||||
|   } | ||||
|   return { | ||||
|     loading: loading && !session, | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| function useRedirectToOnboardingIfNeeded() { | ||||
|   const [session, loading] = useSession(); | ||||
|   const router = useRouter(); | ||||
|   const query = useMeQuery(); | ||||
|   const user = query.data; | ||||
| 
 | ||||
|   const [isRedirectingToOnboarding, setRedirecting] = useState(false); | ||||
|   useEffect(() => { | ||||
|     if (!loading && user) { | ||||
|       if (shouldShowOnboarding(user)) { | ||||
|     if (user && shouldShowOnboarding(user)) { | ||||
|       setRedirecting(true); | ||||
|     } | ||||
|   }, [router, user]); | ||||
|   useEffect(() => { | ||||
|     if (isRedirectingToOnboarding) { | ||||
|       router.replace({ | ||||
|         pathname: "/getting-started", | ||||
|       }); | ||||
|     } | ||||
|     } | ||||
|   }, [loading, session, router, user]); | ||||
|     // eslint-disable-next-line react-hooks/exhaustive-deps
 | ||||
|   }, [isRedirectingToOnboarding]); | ||||
|   return { | ||||
|     isRedirectingToOnboarding, | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| export function ShellSubHeading(props: { | ||||
|  | @ -109,8 +120,8 @@ export default function Shell(props: { | |||
| }) { | ||||
|   const { t } = useLocale(); | ||||
|   const router = useRouter(); | ||||
|   useRedirectToLoginIfUnauthenticated(); | ||||
|   useRedirectToOnboardingIfNeeded(); | ||||
|   const { loading } = useRedirectToLoginIfUnauthenticated(); | ||||
|   const { isRedirectingToOnboarding } = useRedirectToOnboardingIfNeeded(); | ||||
| 
 | ||||
|   const telemetry = useTelemetry(); | ||||
| 
 | ||||
|  | @ -157,7 +168,7 @@ export default function Shell(props: { | |||
| 
 | ||||
|   const i18n = useViewerI18n(); | ||||
| 
 | ||||
|   if (i18n.status === "loading") { | ||||
|   if (i18n.status === "loading" || isRedirectingToOnboarding || loading) { | ||||
|     // show spinner whilst i18n is loading to avoid language flicker
 | ||||
|     return ( | ||||
|       <div className="z-50 absolute w-full h-screen bg-gray-50 flex items-center"> | ||||
|  |  | |||
|  | @ -45,7 +45,7 @@ export function loginProvider(opts: { | |||
|       if (cachedCookies) { | ||||
|         await context.addCookies(cachedCookies); | ||||
|       } else { | ||||
|         await page.goto("http://localhost:3000/event-types"); | ||||
|         await page.goto("http://localhost:3000/auth/login"); | ||||
|         // Click input[name="email"]
 | ||||
|         await page.click('input[name="email"]'); | ||||
|         // Fill input[name="email"]
 | ||||
|  | @ -57,7 +57,12 @@ export function loginProvider(opts: { | |||
|         // Press Enter
 | ||||
|         await page.press('input[name="password"]', "Enter"); | ||||
| 
 | ||||
|         await page.waitForSelector("[data-testid=event-types]"); | ||||
|         await page.waitForNavigation({ | ||||
|           url(url) { | ||||
|             return !url.pathname.startsWith("/auth"); | ||||
|           }, | ||||
|         }); | ||||
| 
 | ||||
|         const cookies = await context.cookies(); | ||||
|         cookieCache.set(opts.user, cookies); | ||||
|       } | ||||
|  |  | |||
							
								
								
									
										22
									
								
								playwright/onboarding.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								playwright/onboarding.test.ts
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| import { kont } from "kont"; | ||||
| 
 | ||||
| import { loginProvider } from "./lib/loginProvider"; | ||||
| 
 | ||||
| jest.setTimeout(60e3); | ||||
| jest.retryTimes(2); | ||||
| 
 | ||||
| const ctx = kont() | ||||
|   .useBeforeEach( | ||||
|     loginProvider({ | ||||
|       user: "onboarding", | ||||
|     }) | ||||
|   ) | ||||
|   .done(); | ||||
| 
 | ||||
| test("redirects to /getting-started after login", async () => { | ||||
|   await ctx.page.waitForNavigation({ | ||||
|     url(url) { | ||||
|       return url.pathname === "/getting-started"; | ||||
|     }, | ||||
|   }); | ||||
| }); | ||||
		Loading…
	
		Reference in a new issue
	
	 Alex Johansson
						Alex Johansson