Files
rf4-spotter/apps/web/tests/theme-acceptance.spec.ts
T
ik 2729e7a035
CI / backend-and-migrations (push) Waiting to run
CI / astro-build (push) Waiting to run
CI / dependency-audit (push) Waiting to run
CI / compose-e2e (push) Waiting to run
test: cover theme persistence and reduced motion
2026-09-21 17:48:17 +07:00

40 lines
2.0 KiB
TypeScript

import { expect, test } from "@playwright/test";
test("theme switcher persists the explicit choice and keeps browser metadata in sync", async ({ page, context }) => {
await context.clearCookies();
await page.goto("/");
await expect(page.locator("html")).not.toHaveAttribute("data-theme");
await expect(page.locator('[data-theme-option="system"]')).toHaveAttribute("aria-pressed", "true");
await page.locator('[data-theme-option="dark"]').click();
await expect(page.locator("html")).toHaveAttribute("data-theme", "dark");
await expect(page.locator('[data-theme-option="dark"]')).toHaveAttribute("aria-pressed", "true");
await expect(page.locator('meta[data-theme-color="dark"]')).toHaveAttribute("media", "all");
await expect(page.locator('meta[data-theme-color="light"]')).toHaveAttribute("media", "not all");
const cookies = await context.cookies();
expect(cookies.find(cookie => cookie.name === "rf4-theme")).toMatchObject({ value: "dark", sameSite: "Lax" });
await page.reload();
await expect(page.locator("html")).toHaveAttribute("data-theme", "dark");
await expect(page.locator('[data-theme-option="dark"]')).toHaveAttribute("aria-pressed", "true");
await page.locator('[data-theme-option="system"]').click();
await expect(page.locator("html")).not.toHaveAttribute("data-theme");
await expect(page.locator('[data-theme-option="system"]')).toHaveAttribute("aria-pressed", "true");
await expect(page.locator('meta[data-theme-color="dark"]')).toHaveAttribute("media", "(prefers-color-scheme: dark)");
});
test("reduced motion disables decorative animation loops", async ({ page }) => {
await page.emulateMedia({ reducedMotion: "reduce" });
await page.goto("/");
const motion = await page.locator(".pulse-orb span").evaluate(element => {
const style = getComputedStyle(element);
return { duration: style.animationDuration, iterations: style.animationIterationCount };
});
expect(motion.duration).toBe("0.01s");
expect(motion.iterations).toBe("1");
});