diff --git a/desktop/playwright.config.ts b/desktop/playwright.config.ts index 446f3ecd4..7c73d54b8 100644 --- a/desktop/playwright.config.ts +++ b/desktop/playwright.config.ts @@ -79,6 +79,7 @@ export default defineConfig({ "**/project-commit-detail.spec.ts", "**/persona-model-combobox-screenshots.spec.ts", "**/drafts-screenshots.spec.ts", + "**/buzz-theme-screenshots.spec.ts", "**/channel-sort.spec.ts", ], use: { diff --git a/desktop/tests/e2e/buzz-theme-screenshots.spec.ts b/desktop/tests/e2e/buzz-theme-screenshots.spec.ts new file mode 100644 index 000000000..60856cddc --- /dev/null +++ b/desktop/tests/e2e/buzz-theme-screenshots.spec.ts @@ -0,0 +1,83 @@ +import { expect, test, type Page } from "@playwright/test"; + +import { waitForAnimations } from "../helpers/animations"; +import { installMockBridge } from "../helpers/bridge"; + +const SHOTS = "test-results/buzz-theme"; +const THEME_STORAGE_KEY = "buzz-theme"; + +/** + * Seed the active theme into localStorage BEFORE the mock bridge installs so + * ThemeProvider reads it on first mount (init scripts run in registration + * order; React reads state on mount, which the bridge triggers). + */ +async function seedTheme(page: Page, theme: string) { + await page.addInitScript( + ({ key, value }) => { + window.localStorage.setItem(key, value); + }, + { key: THEME_STORAGE_KEY, value: theme }, + ); +} + +async function openChannel(page: Page) { + await page.goto("/", { waitUntil: "domcontentloaded" }); + await page.getByTestId("channel-general").click(); + await expect(page.getByTestId("chat-title")).toHaveText("general"); + await expect(page.getByTestId("app-sidebar")).toBeVisible(); +} + +test("buzz light sidebar gradient", async ({ page }) => { + await seedTheme(page, "buzz"); + await installMockBridge(page); + await openChannel(page); + await waitForAnimations(page); + await page + .getByTestId("app-sidebar") + .screenshot({ path: `${SHOTS}/01-buzz-light-sidebar.png` }); +}); + +test("buzz dark sidebar gradient", async ({ page }) => { + await seedTheme(page, "buzz-dark"); + await installMockBridge(page); + await openChannel(page); + await waitForAnimations(page); + await page + .getByTestId("app-sidebar") + .screenshot({ path: `${SHOTS}/02-buzz-dark-sidebar.png` }); +}); + +async function openAppearance(page: Page, mode: "system" | "light" | "dark") { + // Settings renders at the AppShell level; open it via the profile card + // button, then select the Appearance section. + await page.goto("/", { waitUntil: "domcontentloaded" }); + await page.getByTestId("open-settings").click(); + await page.getByTestId("profile-popover-settings").click(); + await page.getByTestId("settings-nav-appearance").click(); + const panel = page.getByTestId("settings-theme"); + await expect(panel).toBeVisible({ timeout: 10_000 }); + await page.getByTestId(`appearance-mode-${mode}`).click(); + await waitForAnimations(page); + return panel; +} + +test("appearance picker — system tab (Buzz follows OS)", async ({ page }) => { + await seedTheme(page, "buzz"); + await installMockBridge(page); + const panel = await openAppearance(page, "system"); + await panel.screenshot({ path: `${SHOTS}/03-picker-system.png` }); +}); + +test("appearance picker — light tab (Buzz)", async ({ page }) => { + await seedTheme(page, "buzz"); + await installMockBridge(page); + const panel = await openAppearance(page, "light"); + await panel.screenshot({ path: `${SHOTS}/04-picker-light.png` }); +}); + +test("appearance picker — dark tab (Buzz Dark)", async ({ page }) => { + await seedTheme(page, "buzz-dark"); + await installMockBridge(page); + const panel = await openAppearance(page, "dark"); + await panel.screenshot({ path: `${SHOTS}/05-picker-dark.png` }); +});