import { expect, test, type Page } from "@playwright/test"; import { mkdirSync } from "node:fs"; import { resolve } from "node:path"; import { agentServeRefresh, jiraEvent, login } from "./hub.ts"; // Снимки экранов для проверки вида (запуск: SCREENS=1 npx playwright test e2e/screens.spec.ts). // Результат — web/e2e-screens/<тема>-<ширина>-<экран>.png, в git не попадает. test.skip(!process.env.SCREENS, "снимки только по SCREENS=1"); const OUT = resolve(import.meta.dirname, "../e2e-screens"); const SIZES = [{ w: 1920, h: 1080 }, { w: 390, h: 844 }]; for (const theme of ["light", "dark"] as const) { for (const { w, h } of SIZES) { test.describe(`${theme} ${w}`, () => { test.use({ viewport: { width: w, height: h }, colorScheme: theme }); test.beforeEach(async ({ page }) => { mkdirSync(OUT, { recursive: true }); await page.addInitScript((t) => { localStorage.setItem("graph-theme", t); }, theme); }); const shot = (page: Page, name: string) => page.screenshot({ path: `${OUT}/${theme}-${w}-${name}.png`, fullPage: true }); const settle = async (page: Page) => { await page.evaluate(() => document.fonts.ready.then(() => undefined)); await page.waitForTimeout(400); // раскладка доски и переходы успокаиваются до снимка }; test("login", async ({ page }) => { await page.goto("/app/jira/board"); await expect(page.getByLabel("Клиентский токен хаба")).toBeVisible(); await settle(page); await shot(page, "login"); }); test("overview", async ({ page }) => { await login(page, "/app/"); await expect(page.getByTestId("page-overview")).toBeVisible(); await expect(page.locator(".overview-card")).toHaveCount(2); await settle(page); await shot(page, "overview"); }); test("board", async ({ page }) => { await login(page); await expect(page.locator(".board .card[data-key]").first()).toBeVisible(); await settle(page); await shot(page, "board"); }); test("board-bydate", async ({ page }) => { await login(page); await page.getByRole("button", { name: "По датам" }).click(); await expect(page.locator(".dcol").first()).toBeVisible(); await settle(page); await shot(page, "board-bydate"); }); test("board-problems", async ({ page }) => { await login(page); await expect(page.locator(".board .card[data-key]").first()).toBeVisible(); await page.getByRole("button", { name: /Проблемы/ }).click(); await settle(page); await shot(page, "board-problems"); }); test("issues", async ({ page }) => { await login(page, "/app/jira/issues"); await expect(page.locator("table.issue-table tbody tr").first()).toBeVisible(); await settle(page); await shot(page, "issues"); }); test("issues-filters", async ({ page }) => { await login(page, "/app/jira/issues"); await page.getByRole("button", { name: /Фильтры/ }).click(); await page.getByRole("combobox", { name: "Исполнитель" }).selectOption("Петров Пётр Петрович"); await expect(page).toHaveURL(/assignee=/); await settle(page); await shot(page, "issues-filters"); }); test("card", async ({ page }) => { await login(page, "/app/jira/issues/AURORA-9001"); await expect(page.getByRole("dialog").getByRole("heading", { name: "Схема свода" })).toBeVisible(); await settle(page); await shot(page, "card"); }); test("new-project", async ({ page }) => { await login(page); if (w < 640) await page.getByRole("button", { name: "Меню" }).click(); // на узком экране проект — в выезжающей панели await page.getByLabel("Проект", { exact: true }).selectOption({ label: "+ Новый проект…" }); await expect(page.getByRole("dialog", { name: "Новый проект" })).toBeVisible(); await settle(page); await shot(page, "new-project"); }); test("board-collapsed", async ({ page }) => { test.skip(w < 640, "свёртка — только на широком экране"); await page.addInitScript(() => { localStorage.setItem("sdlc-hub-sidebar", "collapsed"); }); await login(page); await expect(page.locator(".board .card[data-key]").first()).toBeVisible(); await settle(page); await shot(page, "board-collapsed"); }); test("menu", async ({ page }) => { test.skip(w >= 640, "выезжающая панель — только на узком экране"); await login(page); await page.getByRole("button", { name: "Меню" }).click(); await expect(page.getByRole("complementary", { name: "Панель приложения" })).toBeVisible(); await settle(page); await page.screenshot({ path: `${OUT}/${theme}-${w}-menu.png` }); }); test("sidebar", async ({ page }) => { await login(page, "/app/"); if (w < 640) await page.getByRole("button", { name: "Меню" }).click(); const side = page.getByRole("complementary", { name: "Панель приложения" }); await expect(side).toBeVisible(); await settle(page); await side.screenshot({ path: `${OUT}/${theme}-${w}-sidebar.png` }); }); test("refresh", async ({ page }) => { await login(page); await page.getByTestId("page-board").getByRole("button", { name: "Обновить из Jira", exact: true }).click(); await expect(jiraEvent(page)).toContainText(/пакет #\d+/); await settle(page); await shot(page, "refresh"); await agentServeRefresh(); // не оставляем пакет в очереди тестового хаба await expect(jiraEvent(page)).toContainText(/выполнен/, { timeout: 15_000 }); }); }); } }