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)) {
 | 
			
		||||
        router.replace({
 | 
			
		||||
          pathname: "/getting-started",
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    if (user && shouldShowOnboarding(user)) {
 | 
			
		||||
      setRedirecting(true);
 | 
			
		||||
    }
 | 
			
		||||
  }, [loading, session, router, user]);
 | 
			
		||||
  }, [router, user]);
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (isRedirectingToOnboarding) {
 | 
			
		||||
      router.replace({
 | 
			
		||||
        pathname: "/getting-started",
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    // 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