diff --git a/apps/web/tests/authentication.spec.ts b/apps/web/tests/authentication.spec.ts index 8176af0c9..24cf11c40 100644 --- a/apps/web/tests/authentication.spec.ts +++ b/apps/web/tests/authentication.spec.ts @@ -3,21 +3,11 @@ import { prisma } from "@rallly/database"; import { load } from "cheerio"; import { captureEmailHTML } from "./mailpit/mailpit"; +import { RegisterPage } from "./register-page"; +import { getCode } from "./utils"; const testUserEmail = "test@example.com"; -/** - * Get the 6-digit code from the email - * @returns 6-digit code - */ -const getCode = async () => { - const html = await captureEmailHTML(testUserEmail); - - const $ = load(html); - - return $("#code").text().trim(); -}; - test.describe.serial(() => { test.afterAll(async () => { try { @@ -49,26 +39,11 @@ test.describe.serial(() => { }); test("user registration", async ({ page }) => { - await page.goto("/register"); - - await page.getByText("Create Your Account").waitFor(); - - await page.getByPlaceholder("Jessie Smith").fill("Test User"); - await page - .getByPlaceholder("jessie.smith@example.com") - .fill(testUserEmail); - - await page.getByRole("button", { name: "Continue", exact: true }).click(); - - const code = await getCode(); - - await page.getByText("Finish Registering").waitFor(); - - const codeInput = page.getByPlaceholder("Enter your 6-digit code"); - - await codeInput.fill(code); - - await expect(page.getByText("Test User")).toBeVisible(); + const registerPage = new RegisterPage(page); + await registerPage.register({ + name: "Test User", + email: testUserEmail, + }); }); }); @@ -141,7 +116,7 @@ test.describe.serial(() => { await page.getByRole("button", { name: "Continue with Email" }).click(); - const code = await getCode(); + const code = await getCode(testUserEmail); await page.getByPlaceholder("Enter your 6-digit code").fill(code); @@ -157,7 +132,7 @@ test.describe.serial(() => { await page.getByRole("button", { name: "Continue with Email" }).click(); - const code = await getCode(); + const code = await getCode(testUserEmail); await page.getByPlaceholder("Enter your 6-digit code").fill(code); diff --git a/apps/web/tests/create-delete-poll.spec.ts b/apps/web/tests/create-delete-poll.spec.ts index e3ed1b6e5..3c5fdfcc8 100644 --- a/apps/web/tests/create-delete-poll.spec.ts +++ b/apps/web/tests/create-delete-poll.spec.ts @@ -15,7 +15,6 @@ test.describe.serial(() => { test("create a new poll", async () => { const newPollPage = new NewPollPage(page); - await newPollPage.goto(); await newPollPage.createPollAndCloseDialog(); await expect(page.getByTestId("poll-title")).toHaveText("Monthly Meetup"); diff --git a/apps/web/tests/guest-to-user-migration.spec.ts b/apps/web/tests/guest-to-user-migration.spec.ts new file mode 100644 index 000000000..7178ed210 --- /dev/null +++ b/apps/web/tests/guest-to-user-migration.spec.ts @@ -0,0 +1,49 @@ +import { expect, test } from "@playwright/test"; +import { prisma } from "@rallly/database"; +import { NewPollPage } from "tests/new-poll-page"; + +import { deleteAllMessages } from "./mailpit/mailpit"; +import { RegisterPage } from "./register-page"; + +const TEST_USER_EMAIL = "testuser@example.com"; + +test.describe.serial(() => { + test.beforeAll(async () => { + await deleteAllMessages(); + }); + + test.afterAll(async () => { + // Clean up the test user + await prisma.user.delete({ + where: { + email: TEST_USER_EMAIL, + }, + }); + }); + + test("guest user can create a poll and convert to registered user", async ({ + page, + }) => { + // Step 1: Create a poll as guest + const newPollPage = new NewPollPage(page); + await newPollPage.createPollAndCloseDialog(); + await expect(page.getByTestId("poll-title")).toHaveText("Monthly Meetup"); + + // Step 2: Navigate to registration + await page.click("text=Create an account"); + await expect(page).toHaveURL(/register/); + + // Step 3: Complete registration + const registerPage = new RegisterPage(page); + await registerPage.register({ + name: "Test User", + email: TEST_USER_EMAIL, + }); + + // Step 4: Navigate back to the poll + await page.getByRole("link", { name: "Live" }).click(); + await expect(page).toHaveURL(/polls/); + await page.click("text=Monthly Meetup"); + await expect(page.getByTestId("poll-title")).toHaveText("Monthly Meetup"); + }); +}); diff --git a/apps/web/tests/new-poll-page.ts b/apps/web/tests/new-poll-page.ts index 9d1151d13..31b002964 100644 --- a/apps/web/tests/new-poll-page.ts +++ b/apps/web/tests/new-poll-page.ts @@ -9,6 +9,7 @@ export class NewPollPage { } async createPollAndCloseDialog() { + await this.goto(); const pollPage = await this.createPoll(); await pollPage.closeDialog(); return pollPage; diff --git a/apps/web/tests/register-page.ts b/apps/web/tests/register-page.ts new file mode 100644 index 000000000..19aa74bcb --- /dev/null +++ b/apps/web/tests/register-page.ts @@ -0,0 +1,32 @@ +import type { Page } from "@playwright/test"; +import { expect } from "@playwright/test"; + +import { getCode } from "./utils"; + +export class RegisterPage { + constructor(private readonly page: Page) {} + + async goto() { + await this.page.goto("/register"); + await this.page.getByText("Create Your Account").waitFor(); + } + + async register({ name, email }: { name: string; email: string }) { + await this.goto(); + // Fill in registration form + await this.page.getByPlaceholder("Jessie Smith").fill(name); + await this.page.getByPlaceholder("jessie.smith@example.com").fill(email); + + await this.page + .getByRole("button", { name: "Continue", exact: true }) + .click(); + + // Handle verification code + const code = await getCode(email); + await this.page.getByText("Finish Registering").waitFor(); + await this.page.getByPlaceholder("Enter your 6-digit code").fill(code); + + // Verify successful registration + await expect(this.page.getByText(name)).toBeVisible(); + } +} diff --git a/apps/web/tests/utils.ts b/apps/web/tests/utils.ts new file mode 100644 index 000000000..3a94ab8da --- /dev/null +++ b/apps/web/tests/utils.ts @@ -0,0 +1,16 @@ +import { load } from "cheerio"; + +import { captureEmailHTML } from "./mailpit/mailpit"; + +/** + * Get the 6-digit code from the email + * @param email The email address to get the code for + * @returns 6-digit code + */ +export const getCode = async (email: string) => { + const html = await captureEmailHTML(email); + + const $ = load(html); + + return $("#code").text().trim(); +};