import { test, expect } from "@playwright/test"; import { resetData, writeSettings } from "./helpers"; // The editor shell is branded by the global operational `adminTitle` (it manages // all sites, so it isn't tied to any one site's branding). test.beforeEach(async () => { await resetData("empty"); }); test("renders adminTitle in document title and sidebar", async ({ page }) => { await writeSettings({ adminTitle: "Cypress HQ", maxTranscriptPageBytes: 8388608, sleepBetweenDownloadsSeconds: 0, }); await page.goto("/"); await expect(page).toHaveTitle(/Cypress HQ/); await expect( page.locator("aside").getByRole("link", { name: "Cypress HQ" }), ).toBeVisible(); }); test("reflects sidebar header after saving via the settings form", async ({ page, }) => { await page.goto("/settings"); await page.getByLabel(/admin title/i).fill("Saved Admin"); await page.getByRole("button", { name: /save settings/i }).click(); await expect( page.getByRole("status").filter({ hasText: "Saved" }), ).toBeVisible(); await page.goto("/"); await expect( page.locator("aside").getByRole("link", { name: "Saved Admin" }), ).toBeVisible(); }); test("the sidebar carries the parent mark beside adminTitle, and the favicon is the mark", async ({ page, request, }) => { await writeSettings({ adminTitle: "Cypress HQ", maxTranscriptPageBytes: 8388608, sleepBetweenDownloadsSeconds: 0, }); await page.goto("/"); const aside = page.locator("aside"); // Decorative, and NOT inside the title link: its name stays adminTitle. const mark = aside.locator("svg[data-brand-mark]"); await expect(mark).toHaveCount(1); await expect(mark).toHaveAttribute("aria-hidden", "true"); await expect(mark).toBeVisible(); await expect( aside.getByRole("link", { name: "Cypress HQ", exact: true }), ).toBeVisible(); // app/icon.svg (Next's file convention) is linked from . const href = await page .locator('head link[rel="icon"][type="image/svg+xml"]') .getAttribute("href"); expect(href).toMatch(/^\/icon\.svg/); const svg = await (await request.get(href as string)).text(); expect(svg).toContain('fill="#151b20"'); expect(svg).toContain('fill="#e7edf1"'); }); // The ring on dark (release 10, slice MR): on the dark base the sidebar mark's // slate tile gets a 1px ring outside it in the slate's dim (#586977), a // box-shadow following the ground's corner; on light, none. test("on dark the sidebar mark's tile has a 1px ring in its dim; on light none", async ({ page, }) => { await page.goto("/"); const mark = page.locator("aside svg[data-brand-mark]"); const read = () => mark.evaluate((svg) => { const cs = getComputedStyle(svg); const layers = cs.boxShadow === "none" ? [] : cs.boxShadow.split(/,(?![^(]*\))/); return { dark: document.documentElement.classList.contains("dark"), ring: layers.map((l) => l.trim()).filter((l) => !l.startsWith("rgba(0, 0, 0, 0)")), radius: cs.borderTopLeftRadius, }; }); for (const base of ["dark", "light"] as const) { await page.evaluate((b) => localStorage.setItem("ytdlp-tb:base", b), base); await page.reload(); await expect .poll(read, { message: base }) .toEqual({ dark: base === "dark", ring: base === "dark" ? ["rgb(88, 105, 119) 0px 0px 0px 1px"] : [], radius: "21.875%", }); } });