This commit is contained in:
sean-brydon
2026-02-13 12:14:08 +00:00
committed by GitHub
parent 237d7e95c4
commit 227ed64b49
9 changed files with 88 additions and 61 deletions
@@ -151,7 +151,6 @@ export const OnboardingView = ({ userEmail }: OnboardingViewProps) => {
footer={
<div className="flex w-full justify-end gap-2">
<Button
data-testid="onboarding-continue-btn"
color="primary"
className="rounded-[10px]"
onClick={handleContinue}
@@ -117,7 +117,6 @@ export const PersonalCalendarView = ({ userEmail }: PersonalCalendarViewProps) =
{t("onboarding_skip_for_now")}
</Button>
<Button
data-testid="onboarding-continue-btn"
color="primary"
className="rounded-[10px]"
onClick={handleContinue}
+3 -2
View File
@@ -1,4 +1,5 @@
import { expect } from "@playwright/test";
import { test } from "./lib/fixtures";
test.describe.configure({ mode: "parallel" });
@@ -76,12 +77,12 @@ test.describe("apps/ A/B tests", () => {
await expect(locator).toBeDefined();
});
test("should render the /onboarding/personal/calendar", async ({ page, users }) => {
test("should render the /getting-started", async ({ page, users }) => {
const user = await users.create({ completedOnboarding: false, name: null });
await user.apiLogin();
await page.goto("/onboarding/personal/calendar");
await page.goto("/getting-started/connected-calendar");
const locator = page.getByText("Apple Calendar");
+3 -1
View File
@@ -1,4 +1,5 @@
import { expect } from "@playwright/test";
import { test } from "../lib/fixtures";
import { submitAndWaitForResponse } from "../lib/testUtils";
@@ -68,7 +69,8 @@ test.describe("Can signup from a team invite", async () => {
await newPage.fill('input[name="password"]', testUser.password);
await submitAndWaitForResponse(newPage, "/api/auth/signup", { expectedStatusCode: 201 });
// Since it's a new user, it should be redirected to the onboarding
await newPage.waitForURL(/\/(getting-started|onboarding\/(getting-started|personal\/settings))/);
await newPage.locator('text="Welcome to Cal.com!"').waitFor();
await expect(newPage.locator('text="Welcome to Cal.com!"')).toBeVisible();
// We don't need the new browser anymore
await newPage.close();
+62 -19
View File
@@ -1,5 +1,7 @@
import { IdentityProvider } from "@calcom/prisma/enums";
import { expect } from "@playwright/test";
import { IdentityProvider } from "@calcom/prisma/enums";
import { test } from "./lib/fixtures";
test.describe.configure({ mode: "parallel" });
@@ -8,39 +10,80 @@ test.afterEach(({ users }) => users.deleteAll());
test.describe("Onboarding", () => {
const testOnboarding = (identityProvider: IdentityProvider) => {
test(`Onboarding Flow (v3) - ${identityProvider} user`, async ({ page, users }) => {
test(`Onboarding Flow - ${identityProvider} user`, async ({ page, users }) => {
const user = await users.create({
completedOnboarding: false,
name: null,
identityProvider,
});
await user.apiLogin();
await page.goto("/onboarding/getting-started");
await page.waitForURL("/onboarding/getting-started");
await page.goto("/getting-started");
// tests whether the user makes it to /getting-started
// after login with completedOnboarding false
await page.waitForURL("/getting-started");
await expect(page.locator('text="Connect your calendar"').first()).toBeVisible(); // Fix race condition
await test.step("step 1 - Plan Selection", async () => {
await expect(page.getByTestId("onboarding-continue-btn")).toBeVisible();
await page.getByTestId("onboarding-continue-btn").click();
await page.waitForURL(/.*\/onboarding\/personal\/settings/);
});
await test.step("step 1 - User Settings", async () => {
const onboarding = page.getByTestId("onboarding");
const form = onboarding.locator("form").first();
const submitButton = form.getByTestId("connect-calendar-button");
await test.step("step 2 - Personal Settings", async () => {
const nameInput = page.locator('input[name="name"]');
await nameInput.fill("new user 2");
await page.locator('button[type="submit"]').click();
await page.waitForURL(/.*\/onboarding\/personal\/calendar/);
// Check required fields
await submitButton.click();
await expect(page.locator("data-testid=required")).toBeVisible();
// happy path
await form.locator("input[name=username]").fill("new user onboarding");
await form.getByLabel("Full name").fill("new user 2");
await form.locator("input[role=combobox]").click();
await page
.locator("*")
.filter({ hasText: /^Europe\/London/ })
.first()
.click();
await submitButton.click();
await expect(page).toHaveURL(/.*connected-calendar/);
const userComplete = await user.self();
expect(userComplete.name).toBe("new user 2");
});
await test.step("step 3 - Calendar Connection", async () => {
await expect(page.getByTestId("onboarding-continue-btn")).toBeVisible();
await page.getByTestId("onboarding-continue-btn").click();
await page.waitForURL("/event-types**");
await test.step("step 2 - Connected Calendar", async () => {
const isDisabled = await page.locator("button[data-testid=save-calendar-button]").isDisabled();
await expect(isDisabled).toBe(true);
// tests skip button, we don't want to test entire flow.
await page.locator("button[data-testid=skip-step]").click();
await expect(page).toHaveURL(/.*connected-video/);
});
await test.step("step 3 - Connected Video", async () => {
const isDisabled = await page.locator("button[data-testid=save-video-button]").isDisabled();
await expect(isDisabled).toBe(true);
// tests skip button, we don't want to test entire flow.
await page.locator("button[data-testid=skip-step]").click();
await expect(page).toHaveURL(/.*setup-availability/);
});
await test.step("step 4 - Setup Availability", async () => {
const isDisabled = await page.locator("button[data-testid=save-availability]").isDisabled();
await expect(isDisabled).toBe(false);
// same here, skip this step.
await page.locator("button[data-testid=save-availability]").click();
await expect(page).toHaveURL(/.*user-profile/);
});
await test.step("step 5- User Profile", async () => {
const onboarding = page.getByTestId("onboarding");
const form = onboarding.locator("form").first();
const submitButton = form.getByRole("button", { name: "Finish setup and get started" });
await submitButton.click();
// should redirect to /event-types after onboarding
await page.waitForURL("/event-types");
const userComplete = await user.self();
expect(userComplete.completedOnboarding).toBe(true);
expect(userComplete.bio?.replace("<p><br></p>", "").length).toBe(0);
});
});
};
@@ -1,7 +1,10 @@
import prisma from "@calcom/prisma";
import { MembershipRole, SchedulingType } from "@calcom/prisma/enums";
import type { Browser, Page } from "@playwright/test";
import { expect } from "@playwright/test";
import prisma from "@calcom/prisma";
import { MembershipRole } from "@calcom/prisma/enums";
import { SchedulingType } from "@calcom/prisma/enums";
import { test } from "../lib/fixtures";
import { moveUserToOrg } from "../lib/orgMigration";
import { bookTeamEvent, doOnOrgDomain, expectPageToBeNotFound, getInviteLink } from "../lib/testUtils";
@@ -502,10 +505,7 @@ async function signupFromInviteLink({
await inviteLinkPage.locator("input[name=email]").fill(email);
await inviteLinkPage.locator("input[name=password]").fill(`P4ssw0rd!`);
await inviteLinkPage.locator("button[type=submit]").click();
await inviteLinkPage.waitForURL((url) => {
const path = url.pathname;
return /\/(getting-started|onboarding\/(getting-started|personal\/settings))/.test(path);
});
await inviteLinkPage.waitForURL("/getting-started");
return { email };
}
@@ -540,10 +540,7 @@ export async function signupFromEmailInviteLink({
// Check required fields
await signupPage.locator("input[name=password]").fill(`P4ssw0rd!`);
await signupPage.locator("button[type=submit]").click();
await signupPage.waitForURL((url) => {
const path = url.pathname;
return /\/(getting-started|onboarding\/(getting-started|personal\/settings))/.test(path);
});
await signupPage.waitForURL("/getting-started?from=signup");
await context.close();
await signupPage.close();
}
+9 -19
View File
@@ -1,10 +1,11 @@
import { randomBytes } from "node:crypto";
import process from "node:process";
import { APP_NAME, IS_MAILHOG_ENABLED, IS_PREMIUM_USERNAME_ENABLED } from "@calcom/lib/constants";
import prisma from "@calcom/prisma";
import type { Browser, Page } from "@playwright/test";
import { expect } from "@playwright/test";
import { hashSync } from "bcryptjs";
import { randomBytes } from "node:crypto";
import { APP_NAME, IS_PREMIUM_USERNAME_ENABLED, IS_MAILHOG_ENABLED } from "@calcom/lib/constants";
import prisma from "@calcom/prisma";
import { test } from "./lib/fixtures";
import { localize } from "./lib/localize";
import { getEmailsReceivedByUser, getInviteLink } from "./lib/testUtils";
@@ -187,10 +188,7 @@ test.describe("Email Signup Flow Test", async () => {
await page.locator('button[type="submit"]').click();
// Should successfully login with original password
await expect(page).toHaveURL(
/\/(getting-started|onboarding\/getting-started|onboarding\/personal\/settings|event-types|teams)/,
{ timeout: 8000 }
);
await expect(page).toHaveURL(/\/(getting-started|event-types|teams)/, { timeout: 8000 });
// Cleanup
await prisma.verificationToken.deleteMany({ where: { token } });
@@ -395,10 +393,7 @@ test.describe("Email Signup Flow Test", async () => {
// Check required fields
await newPage.locator("input[name=password]").fill(`P4ssw0rd!`);
await newPage.locator("button[type=submit]").click();
await newPage.waitForURL((url) => {
const path = url.pathname;
return /\/(getting-started|onboarding\/(getting-started|personal\/settings))/.test(path);
});
await newPage.waitForURL("/getting-started?from=signup");
await newPage.close();
await context.close();
});
@@ -529,9 +524,7 @@ test.describe("Email Signup Flow Test", async () => {
await page.locator('input[name="password"]').fill("Password99!");
await page.getByTestId("signup-submit-button").click();
await expect(page).toHaveURL(
/\/(getting-started|onboarding\/(getting-started|personal\/settings))|\/auth\/verify-email/
);
await expect(page).toHaveURL(/\/getting-started|\/auth\/verify-email/);
const createdUser = await prisma.user.findUnique({
where: { email: userToCreate.email },
@@ -640,9 +633,6 @@ async function signupFromInviteLink({
await inviteLinkPage.locator("input[name=email]").fill(email);
await inviteLinkPage.locator("input[name=password]").fill(`P4ssw0rd!`);
await inviteLinkPage.locator("button[type=submit]").click();
await inviteLinkPage.waitForURL((url) => {
const path = url.pathname;
return /\/(getting-started|onboarding\/(getting-started|personal\/settings))/.test(path);
});
await inviteLinkPage.waitForURL("/getting-started");
await context.close();
}
@@ -1,7 +1,9 @@
import { expect } from "@playwright/test";
import { WEBAPP_URL } from "@calcom/lib/constants";
import { prisma } from "@calcom/prisma";
import { MembershipRole, SchedulingType } from "@calcom/prisma/enums";
import { expect } from "@playwright/test";
import { test } from "../lib/fixtures";
import { localize } from "../lib/localize";
import { getInviteLink } from "../lib/testUtils";
@@ -63,10 +65,7 @@ test.describe("Team", () => {
// Check required fields
await newPage.locator("input[name=password]").fill(`P4ssw0rd!`);
await newPage.locator("button[type=submit]").click();
await newPage.waitForURL((url) => {
const path = url.pathname;
return /\/(getting-started|onboarding\/(getting-started|personal\/settings))/.test(path);
});
await newPage.waitForURL("/getting-started?from=signup");
await newPage.close();
await context.close();
@@ -1,3 +0,0 @@
UPDATE "Feature"
SET "enabled" = true, "updatedAt" = CURRENT_TIMESTAMP
WHERE "slug" = 'onboarding-v3';