feat(profile)!: replace sidebar and add avatar navigation
Rename the global Sidebar route, UI, assets, analytics, and payment return context to Profile. Add accessible message-avatar navigation and preserve the source character across auth and logout flows. BREAKING CHANGE: /sidebar has been removed; use /profile instead.
This commit is contained in:
@@ -11,7 +11,7 @@ export const splashStartChatButtonName = "Start Chatting";
|
||||
export const defaultCharacterSlug = "elio";
|
||||
export const defaultCharacterSplashPath = `/characters/${defaultCharacterSlug}/splash`;
|
||||
export const defaultCharacterChatPath = `/characters/${defaultCharacterSlug}/chat`;
|
||||
export const defaultCharacterSidebarPath = `/sidebar?returnTo=%2Fcharacters%2F${defaultCharacterSlug}%2Fchat`;
|
||||
export const defaultCharacterProfilePath = `/profile?returnTo=%2Fcharacters%2F${defaultCharacterSlug}%2Fchat`;
|
||||
export const defaultCharacterChatUrl = new RegExp(
|
||||
`/characters/${defaultCharacterSlug}/chat(?:\\?.*)?$`,
|
||||
);
|
||||
|
||||
@@ -27,7 +27,7 @@ export async function enterChatFromSplash(page: Page, options: { expectedUrl?: R
|
||||
await expect(startChatButton).toBeVisible({ timeout });
|
||||
await expect(startChatButton).toBeEnabled();
|
||||
for (let attempt = 0; attempt < 3; attempt += 1) {
|
||||
await startChatButton.click();
|
||||
await startChatButton.click({ timeout: 3_000 }).catch(() => {});
|
||||
try { await expect(page).toHaveURL(expectedUrl, { timeout: 3_000 }); return; } catch { await page.waitForTimeout(500); }
|
||||
}
|
||||
await expect(page).toHaveURL(expectedUrl, { timeout });
|
||||
|
||||
@@ -31,5 +31,5 @@ test("user can email login from other sign-in options and return to chat", async
|
||||
expect(["desktop", "android"]).toContain(loginRequest?.postDataJSON().platform);
|
||||
|
||||
await expect(page.getByRole("textbox", { name: "Message" })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "Menu" })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "Profile" })).toBeVisible();
|
||||
});
|
||||
|
||||
+5
-5
@@ -3,7 +3,7 @@ import { expect, test } from "@playwright/test";
|
||||
import { mockCoreApis } from "@e2e/fixtures/api-mocks";
|
||||
import {
|
||||
clearBrowserState,
|
||||
defaultCharacterSidebarPath,
|
||||
defaultCharacterProfilePath,
|
||||
defaultCharacterSplashPath,
|
||||
defaultCharacterChatUrl,
|
||||
enterChatFromSplash,
|
||||
@@ -17,7 +17,7 @@ test.beforeEach(async ({ baseURL, context, page }) => {
|
||||
await mockCoreApis(page);
|
||||
});
|
||||
|
||||
test("user can log out from the sidebar after email login", async ({
|
||||
test("user can log out from the profile after email login", async ({
|
||||
page,
|
||||
}) => {
|
||||
await enterChatFromSplash(page);
|
||||
@@ -27,11 +27,11 @@ test("user can log out from the sidebar after email login", async ({
|
||||
await expect(page).toHaveURL(/\/auth(?:\?.*)?$/);
|
||||
await switchToEmailSignIn(page);
|
||||
await submitEmailLogin(page, { expectedUrl: defaultCharacterChatUrl });
|
||||
await expect(page.getByRole("button", { name: "Menu" })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "Profile" })).toBeVisible();
|
||||
|
||||
await page.getByRole("button", { name: "Menu" }).click();
|
||||
await page.getByRole("button", { name: "Profile" }).click();
|
||||
await expect(page).toHaveURL(
|
||||
new RegExp(defaultCharacterSidebarPath.replace("?", "\\?") + "$"),
|
||||
new RegExp(defaultCharacterProfilePath.replace("?", "\\?") + "$"),
|
||||
);
|
||||
|
||||
const logoutRequestPromise = page.waitForRequest("**/api/auth/logout");
|
||||
@@ -0,0 +1,86 @@
|
||||
import { expect, test, type Page } from "@playwright/test";
|
||||
|
||||
import { mockCoreApis } from "@e2e/fixtures/api-mocks";
|
||||
import {
|
||||
clearBrowserState,
|
||||
defaultCharacterProfilePath,
|
||||
dismissChatInterruptions,
|
||||
enterChatFromSplash,
|
||||
submitEmailLogin,
|
||||
switchToEmailSignIn,
|
||||
} from "@e2e/fixtures/test-helpers";
|
||||
|
||||
const characters = [
|
||||
{ slug: "elio", displayName: "Elio Silvestri" },
|
||||
{ slug: "maya", displayName: "Maya Tan" },
|
||||
{ slug: "nayeli", displayName: "Nayeli Cervantes" },
|
||||
] as const;
|
||||
|
||||
test.beforeEach(async ({ baseURL, context, page }) => {
|
||||
await clearBrowserState(context, page, baseURL);
|
||||
await mockCoreApis(page);
|
||||
});
|
||||
|
||||
test("guest user avatar returns to Profile after sign-in", async ({
|
||||
page,
|
||||
}) => {
|
||||
await enterChatFromSplash(page, { timeout: 30_000 });
|
||||
await sendMessage(page, "Open my profile");
|
||||
|
||||
await page.getByRole("button", { name: "Open profile" }).click();
|
||||
|
||||
await expect(page).toHaveURL(/\/auth\?redirect=/);
|
||||
expect(new URL(page.url()).searchParams.get("redirect")).toBe(
|
||||
defaultCharacterProfilePath,
|
||||
);
|
||||
await switchToEmailSignIn(page);
|
||||
await submitEmailLogin(page, {
|
||||
expectedUrl: new RegExp(
|
||||
`${defaultCharacterProfilePath.replace("?", "\\?")}$`,
|
||||
),
|
||||
});
|
||||
});
|
||||
|
||||
for (const character of characters) {
|
||||
test(`${character.displayName} avatar opens the matching Private Room`, async ({
|
||||
page,
|
||||
}) => {
|
||||
await enterCharacterChat(page, character.slug);
|
||||
await sendMessage(page, `Hello ${character.displayName}`);
|
||||
|
||||
await page
|
||||
.getByRole("button", {
|
||||
name: `Open ${character.displayName}'s private room`,
|
||||
})
|
||||
.last()
|
||||
.click();
|
||||
|
||||
await expect(page).toHaveURL(
|
||||
new RegExp(`/characters/${character.slug}/private-room(?:\\?.*)?$`),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async function enterCharacterChat(page: Page, characterSlug: string) {
|
||||
const chatPath = `/characters/${characterSlug}/chat`;
|
||||
|
||||
await page.goto(`/characters/${characterSlug}/splash`);
|
||||
await page.getByRole("button", { name: "Start Chatting" }).click();
|
||||
await expect(page).toHaveURL(new RegExp(`${chatPath}(?:\\?.*)?$`));
|
||||
await dismissChatInterruptions(page);
|
||||
await expect(page.getByRole("textbox", { name: "Message" })).toBeEnabled({
|
||||
timeout: 20_000,
|
||||
});
|
||||
}
|
||||
|
||||
async function sendMessage(page: Page, message: string) {
|
||||
await dismissChatInterruptions(page);
|
||||
const messageInput = page.getByRole("textbox", { name: "Message" });
|
||||
|
||||
await expect(messageInput).toBeEnabled({ timeout: 20_000 });
|
||||
await messageInput.fill(message);
|
||||
await messageInput.press("Enter");
|
||||
await expect(page.getByRole("button", { name: "Open profile" })).toBeVisible({
|
||||
timeout: 10_000,
|
||||
});
|
||||
}
|
||||
@@ -42,7 +42,7 @@ test.describe("pre-release email login smoke", () => {
|
||||
urlTimeout: 20_000,
|
||||
});
|
||||
|
||||
await expect(page.getByRole("button", { name: "Menu" })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "Profile" })).toBeVisible();
|
||||
await expect(page.getByRole("textbox", { name: "Message" })).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user