diff --git a/e2e/fixtures/helpers/auth.ts b/e2e/fixtures/helpers/auth.ts index 07ac2ee3..b190b0e4 100644 --- a/e2e/fixtures/helpers/auth.ts +++ b/e2e/fixtures/helpers/auth.ts @@ -8,6 +8,13 @@ export const e2eEmailCredentials = { }; export const splashStartChatButtonName = "Start Chatting"; +export const defaultCharacterSlug = "elio"; +export const defaultCharacterSplashPath = `/characters/${defaultCharacterSlug}/splash`; +export const defaultCharacterChatPath = `/characters/${defaultCharacterSlug}/chat`; +export const defaultCharacterSidebarPath = `/characters/${defaultCharacterSlug}/sidebar`; +export const defaultCharacterChatUrl = new RegExp( + `/characters/${defaultCharacterSlug}/chat(?:\\?.*)?$`, +); export function getSplashStartChatButton(page: Page) { return page.getByRole("button", { name: splashStartChatButtonName }); @@ -24,8 +31,9 @@ export async function setEmailSessionStorage(page: Page) { } export async function seedEmailSession(page: Page) { - await page.goto("/splash"); + await page.goto(defaultCharacterSplashPath); await setEmailSessionStorage(page); + await page.reload(); } export async function switchToEmailSignIn(page: Page) { diff --git a/e2e/fixtures/helpers/chat.ts b/e2e/fixtures/helpers/chat.ts index a5b3988e..330cb827 100644 --- a/e2e/fixtures/helpers/chat.ts +++ b/e2e/fixtures/helpers/chat.ts @@ -1,6 +1,11 @@ import { expect, type BrowserContext, type Page } from "@playwright/test"; -import { seedEmailSession } from "./auth"; +import { + defaultCharacterChatPath, + defaultCharacterChatUrl, + defaultCharacterSplashPath, + seedEmailSession, +} from "./auth"; export async function clearBrowserState(context: BrowserContext, page: Page, baseURL?: string) { await context.clearCookies(); @@ -12,8 +17,12 @@ export async function clearBrowserState(context: BrowserContext, page: Page, bas } export async function enterChatFromSplash(page: Page, options: { expectedUrl?: RegExp; timeout?: number; waitUntil?: "commit" | "domcontentloaded" | "load" | "networkidle" } = {}) { - const { expectedUrl = /\/chat$/, timeout = 10_000, waitUntil } = options; - await page.goto("/splash", { waitUntil }); + const { + expectedUrl = defaultCharacterChatUrl, + timeout = 10_000, + waitUntil, + } = options; + await page.goto(defaultCharacterSplashPath, { waitUntil }); const startChatButton = page.getByRole("button", { name: "Start Chatting" }); await expect(startChatButton).toBeVisible({ timeout }); await expect(startChatButton).toBeEnabled(); @@ -34,7 +43,7 @@ export async function dismissChatInterruptions(page: Page) { export async function signInWithEmailAndOpenChat(page: Page) { await seedEmailSession(page); const historyResponsePromise = page.waitForResponse("**/api/chat/history**"); - await page.goto("/chat"); + await page.goto(defaultCharacterChatPath); await historyResponsePromise; await dismissChatInterruptions(page); await expect(page.getByRole("textbox", { name: "Message" })).toBeEnabled({ timeout: 20_000 }); diff --git a/e2e/specs/mock/auth/email-login-from-other-options.spec.ts b/e2e/specs/mock/auth/email-login-from-other-options.spec.ts index 504fd21a..99511ee6 100644 --- a/e2e/specs/mock/auth/email-login-from-other-options.spec.ts +++ b/e2e/specs/mock/auth/email-login-from-other-options.spec.ts @@ -3,6 +3,7 @@ import { expect, test } from "@playwright/test"; import { mockCoreApis } from "@e2e/fixtures/api-mocks"; import { clearBrowserState, + defaultCharacterChatUrl, enterChatFromSplash, submitEmailLogin, switchToEmailSignIn, @@ -24,7 +25,9 @@ test("user can email login from other sign-in options and return to chat", async await expect(page).toHaveURL(/\/auth(?:\?.*)?$/); await switchToEmailSignIn(page); - const loginRequest = await submitEmailLogin(page, { expectedUrl: /\/chat$/ }); + const loginRequest = await submitEmailLogin(page, { + expectedUrl: defaultCharacterChatUrl, + }); expect(["desktop", "android"]).toContain(loginRequest?.postDataJSON().platform); await expect(page.getByRole("textbox", { name: "Message" })).toBeVisible(); diff --git a/e2e/specs/mock/auth/logout-from-sidebar.spec.ts b/e2e/specs/mock/auth/logout-from-sidebar.spec.ts index e9dabf6c..56a79e9c 100644 --- a/e2e/specs/mock/auth/logout-from-sidebar.spec.ts +++ b/e2e/specs/mock/auth/logout-from-sidebar.spec.ts @@ -3,6 +3,8 @@ import { expect, test } from "@playwright/test"; import { mockCoreApis } from "@e2e/fixtures/api-mocks"; import { clearBrowserState, + defaultCharacterSidebarPath, + defaultCharacterSplashPath, getSplashStartChatButton, signInWithEmailAndOpenChat, } from "@e2e/fixtures/test-helpers"; @@ -19,7 +21,7 @@ test("user can log out from the sidebar after email login", async ({ await expect(page.getByRole("button", { name: "Menu" })).toBeVisible(); await page.getByRole("button", { name: "Menu" }).click(); - await expect(page).toHaveURL(/\/sidebar$/); + await expect(page).toHaveURL(new RegExp(`${defaultCharacterSidebarPath}$`)); const logoutRequestPromise = page.waitForRequest("**/api/auth/logout"); await page.getByRole("button", { name: /Log out/i }).click(); @@ -27,6 +29,6 @@ test("user can log out from the sidebar after email login", async ({ const logoutRequest = await logoutRequestPromise; expect(logoutRequest.method()).toBe("POST"); - await expect(page).toHaveURL(/\/splash$/); + await expect(page).toHaveURL(new RegExp(`${defaultCharacterSplashPath}$`)); await expect(getSplashStartChatButton(page)).toBeVisible(); }); diff --git a/e2e/specs/mock/auth/psid-login-from-external-entry.spec.ts b/e2e/specs/mock/auth/psid-login-from-external-entry.spec.ts index bd58194d..052fe9bb 100644 --- a/e2e/specs/mock/auth/psid-login-from-external-entry.spec.ts +++ b/e2e/specs/mock/auth/psid-login-from-external-entry.spec.ts @@ -1,7 +1,10 @@ import { expect, test } from "@playwright/test"; import { mockCoreApis } from "@e2e/fixtures/api-mocks"; -import { clearBrowserState } from "@e2e/fixtures/test-helpers"; +import { + clearBrowserState, + defaultCharacterChatUrl, +} from "@e2e/fixtures/test-helpers"; const psid = "e2e-facebook-psid"; @@ -27,7 +30,7 @@ test("user enters from an external PSID link and becomes a guest", async ({ }); expect(psidLoginRequest.postDataJSON().deviceId).toEqual(expect.any(String)); - await expect(page).toHaveURL(/\/chat$/); + await expect(page).toHaveURL(defaultCharacterChatUrl); await expect(page.getByRole("textbox", { name: "Message" })).toBeVisible(); await expect diff --git a/e2e/specs/mock/chat/chat-quantity-limit.spec.ts b/e2e/specs/mock/chat/chat-quantity-limit.spec.ts index bf236e44..95137288 100644 --- a/e2e/specs/mock/chat/chat-quantity-limit.spec.ts +++ b/e2e/specs/mock/chat/chat-quantity-limit.spec.ts @@ -4,6 +4,7 @@ import { mockCoreApis } from "@e2e/fixtures/api-mocks"; import { clearBrowserState, completeVipPayment, + defaultCharacterChatUrl, dismissChatInterruptions, enterChatFromSplash, expectAuthRedirectToVipChatSubscription, @@ -29,9 +30,9 @@ test("guest uses the shared chat limit top-up flow", async ({ page }) => { await dismissChatInterruptions(page); const messageInput = page.getByRole("textbox", { name: "Message" }); - const quantityLimitBanner = page - .getByRole("status") - .filter({ hasText: "Insufficient credits" }); + const quantityLimitBanner = page.getByTestId( + "chat-insufficient-credits-banner", + ); let limitTriggeredAt: number | null = null; let completedSendCount = 0; @@ -79,9 +80,7 @@ test("guest uses the shared chat limit top-up flow", async ({ page }) => { expect(limitTriggeredAt).toBe(mockedLimitTriggerAt); await expect(quantityLimitBanner).toBeVisible(); - await expect( - quantityLimitBanner.getByText("Free chats refresh every day."), - ).toBeVisible(); + await expect(quantityLimitBanner.getByText("Out of Daily Free Chats")).toBeVisible(); const topUpButton = quantityLimitBanner.getByRole("button", { name: "Top up credits to continue", }); @@ -97,7 +96,7 @@ test("guest uses the shared chat limit top-up flow", async ({ page }) => { await completeVipPayment(page); - await expect(page).toHaveURL(/\/chat$/); + await expect(page).toHaveURL(defaultCharacterChatUrl); await expect(page.getByRole("textbox", { name: "Message" })).toBeVisible(); }); diff --git a/e2e/specs/mock/chat/paid-image-promotion-topup.spec.ts b/e2e/specs/mock/chat/paid-image-promotion-topup.spec.ts index 5b773e19..9f3ff07b 100644 --- a/e2e/specs/mock/chat/paid-image-promotion-topup.spec.ts +++ b/e2e/specs/mock/chat/paid-image-promotion-topup.spec.ts @@ -4,6 +4,7 @@ import { mockCoreApis } from "@e2e/fixtures/api-mocks"; import { clearBrowserState, completeVipPayment, + defaultCharacterChatUrl, expectInsufficientCreditsDialog, expectVipChatSubscriptionUrl, setEmailSessionStorage, @@ -24,7 +25,7 @@ test("guest unlocks a promoted image through email login and top-up", async ({ await page.goto( "/external-entry?target=chat&mode=promotion&promotion_type=image", ); - await expect(page).toHaveURL(/\/chat$/); + await expect(page).toHaveURL(defaultCharacterChatUrl); const unlockButton = page.getByRole("button", { name: "Unlock private image", @@ -35,7 +36,7 @@ test("guest unlocks a promoted image through email login and top-up", async ({ await expect(page).toHaveURL(/\/auth\?redirect=/); await switchToEmailSignIn(page); - await submitEmailLogin(page, { expectedUrl: /\/chat$/ }); + await submitEmailLogin(page, { expectedUrl: defaultCharacterChatUrl }); await setEmailSessionStorage(page); const unlockRequestPromise = page.waitForRequest( @@ -57,6 +58,6 @@ test("guest unlocks a promoted image through email login and top-up", async ({ await expectVipChatSubscriptionUrl(page); await completeVipPayment(page); - await expect(page).toHaveURL(/\/chat$/); + await expect(page).toHaveURL(defaultCharacterChatUrl); await expect(page.getByRole("textbox", { name: "Message" })).toBeVisible(); }); diff --git a/e2e/specs/mock/paid-image.spec.ts b/e2e/specs/mock/paid-image.spec.ts index 5602450c..cd5dac9c 100644 --- a/e2e/specs/mock/paid-image.spec.ts +++ b/e2e/specs/mock/paid-image.spec.ts @@ -5,6 +5,7 @@ import { paidImageMessageId } from "@e2e/fixtures/test-data"; import { clearBrowserState, completeVipPayment, + defaultCharacterChatPath, dismissChatInterruptions, enterChatFromSplash, expectInsufficientCreditsDialog, @@ -15,7 +16,7 @@ import { } from "@e2e/fixtures/test-helpers"; const paidImageOverlayUrl = new RegExp( - `/chat\\?image=${paidImageMessageId}$`, + `${defaultCharacterChatPath}\\?image=${paidImageMessageId}$`, ); test.beforeEach(async ({ baseURL, context, page }) => { @@ -62,7 +63,7 @@ test("guest can unlock a paid image after email login and subscription payment", await expect(page).toHaveURL(/\/auth\?redirect=/); expect(new URL(page.url()).searchParams.get("redirect")).toBe( - `/chat?image=${paidImageMessageId}`, + `${defaultCharacterChatPath}?image=${paidImageMessageId}`, ); await switchToEmailSignIn(page); @@ -74,7 +75,7 @@ test("guest can unlock a paid image after email login and subscription payment", const unlockRequestPromise = page.waitForRequest( "**/api/chat/unlock-private", ); - await page.goto(`/chat?image=${paidImageMessageId}`); + await page.goto(`${defaultCharacterChatPath}?image=${paidImageMessageId}`); const unlockRequest = await unlockRequestPromise; expect(unlockRequest.postDataJSON()).toMatchObject({ @@ -89,7 +90,11 @@ test("guest can unlock a paid image after email login and subscription payment", await expectVipChatSubscriptionUrl(page); await completeVipPayment(page); - await expect(page).toHaveURL(/\/chat(?:\?image=msg_photo_paywall_001)?$/); - expect(new URL(page.url()).pathname).toBe("/chat"); + await expect(page).toHaveURL( + new RegExp( + `${defaultCharacterChatPath}(?:\\?image=msg_photo_paywall_001)?$`, + ), + ); + expect(new URL(page.url()).pathname).toBe(defaultCharacterChatPath); await expect(page.getByRole("textbox", { name: "Message" })).toBeVisible(); }); diff --git a/e2e/specs/mock/unlock-message/image-unlock-insufficient-credits.spec.ts b/e2e/specs/mock/unlock-message/image-unlock-insufficient-credits.spec.ts index 921906fb..769e40a8 100644 --- a/e2e/specs/mock/unlock-message/image-unlock-insufficient-credits.spec.ts +++ b/e2e/specs/mock/unlock-message/image-unlock-insufficient-credits.spec.ts @@ -4,6 +4,7 @@ import { mockCoreApis } from "@e2e/fixtures/api-mocks"; import { paidImageMessageId } from "@e2e/fixtures/test-data"; import { clearBrowserState, + defaultCharacterChatPath, dismissChatInterruptions, expectInsufficientCreditsDialog, expectVipChatSubscriptionUrl, @@ -11,7 +12,7 @@ import { } from "@e2e/fixtures/test-helpers"; const paidImageOverlayUrl = new RegExp( - `/chat\\?image=${paidImageMessageId}$`, + `${defaultCharacterChatPath}\\?image=${paidImageMessageId}$`, ); test.beforeEach(async ({ baseURL, context, page }) => { diff --git a/e2e/specs/real/email-login-from-other-options.spec.ts b/e2e/specs/real/email-login-from-other-options.spec.ts index 3e27fae5..101bf1c3 100644 --- a/e2e/specs/real/email-login-from-other-options.spec.ts +++ b/e2e/specs/real/email-login-from-other-options.spec.ts @@ -1,6 +1,7 @@ import { expect, test } from "@playwright/test"; import { + defaultCharacterChatUrl, enterChatFromSplash, submitEmailLogin, switchToEmailSignIn, @@ -19,7 +20,7 @@ test.describe("pre-release email login smoke", () => { page, }) => { await enterChatFromSplash(page, { - expectedUrl: /\/chat(?:\?.*)?$/, + expectedUrl: defaultCharacterChatUrl, timeout: 20_000, waitUntil: "domcontentloaded", }); @@ -36,7 +37,7 @@ test.describe("pre-release email login smoke", () => { await switchToEmailSignIn(page); await submitEmailLogin(page, { - expectedUrl: /\/chat(?:\?.*)?$/, + expectedUrl: defaultCharacterChatUrl, waitForRequest: false, urlTimeout: 20_000, });