import { expect, test } from "@playwright/test"; import { CW } from "../src/modules/jira/board/constants.ts"; import { agentServeRefresh, jiraEvent, login } from "./hub.ts"; test.beforeEach(async ({ page }) => { await login(page); }); test("перетаскивание за рамку двигает карточку и переживает перезагрузку", async ({ page }) => { const card = page.locator('.board .card[data-key="AURORA-9001"]'); const before = await card.boundingBox(); const grip = card.locator(".grip.t"); const g = (await grip.boundingBox())!; await page.mouse.move(g.x + g.width / 2, g.y + g.height / 2); await page.mouse.down(); await page.mouse.move(g.x + g.width / 2 + 160, g.y + g.height / 2 + 40, { steps: 8 }); await page.mouse.up(); const after = (await card.boundingBox())!; expect(Math.round(after.x - before!.x)).toBeGreaterThan(100); await page.reload(); const reloaded = (await page.locator('.board .card[data-key="AURORA-9001"]').boundingBox())!; expect(Math.abs(reloaded.x - after.x)).toBeLessThan(2); expect(Math.abs(reloaded.y - after.y)).toBeLessThan(2); }); test("растяжка за уголок и возврат размера двойным щелчком", async ({ page }) => { const card = page.locator('.board .card[data-key="AURORA-9002"]'); const rsz = (await card.locator(".rsz").boundingBox())!; const w0 = (await card.boundingBox())!.width; await page.mouse.move(rsz.x + 2, rsz.y + 2); await page.mouse.down(); await page.mouse.move(rsz.x + 82, rsz.y + 42, { steps: 6 }); await page.mouse.up(); await expect.poll(async () => (await card.boundingBox())!.width).toBeGreaterThan(w0 + 60); await card.locator(".rsz").dblclick(); await expect.poll(async () => Math.round((await card.boundingBox())!.width)).toBe(CW); }); test("«по датам» — колонки дат, подписи и стрелки", async ({ page }) => { await page.getByRole("button", { name: "По датам" }).click(); await expect(page.locator(".dcol").first()).toBeVisible(); await expect(page.locator(".dates-track .dlabel").first()).toBeVisible(); await expect(page.locator("svg.edges path")).not.toHaveCount(0); }); test("«Обновить из Jira» с учебным агентом доходит до конца", async ({ page }) => { // на странице две кнопки: значок в панели («— все проекты») и кнопка в шапке доски const btn = page.getByTestId("page-board").getByRole("button", { name: "Обновить из Jira", exact: true }); await btn.click(); await expect(btn).toBeDisabled(); await expect(jiraEvent(page)).toContainText(/пакет #\d+/); await agentServeRefresh(); await expect(jiraEvent(page)).toContainText(/пакет #\d+ выполнен/, { timeout: 15_000 }); await expect(btn).toBeEnabled(); await expect(page.getByText(/^данные на .* · все проекты$/)).toBeVisible(); await expect(page.locator(".board .card[data-key]")).not.toHaveCount(0); }); test("ⓘ открывает карточку окном поверх доски", async ({ page }) => { await page.locator('.board .card[data-key="AURORA-9001"]').getByRole("link", { name: "Открыть карточку AURORA-9001" }).click(); await expect(page).toHaveURL(/\/app\/jira\/issues\/AURORA-9001$/); await expect(page.getByRole("dialog").getByRole("heading", { name: "Схема свода" })).toBeVisible(); await expect(page.getByTestId("page-board")).toBeAttached(); await expect(page.getByRole("link", { name: "Связи", exact: true })).toHaveAttribute("aria-current", "page"); }); test("M-3: прокрутка и данные доски после окна карточки и после другого раздела", async ({ page }) => { await page.setViewportSize({ width: 1600, height: 600 }); await expect(page.locator(".board .card[data-key]").first()).toBeVisible(); const y = await page.evaluate(() => { window.scrollTo(0, document.documentElement.scrollHeight); return window.scrollY; }); expect(y).toBeGreaterThan(100); // реальный щелчок по ⓘ карточки, видимой в окне после прокрутки (иначе Playwright сам сдвинет страницу) const key = await page.evaluate(() => { const vh = window.innerHeight; const a = [...document.querySelectorAll(".board .card[data-key] a.open-card")] .find((e) => { const r = e.getBoundingClientRect(); return r.top > 200 && r.bottom < vh - 20; }); return a?.closest(".card")?.dataset.key ?? null; }); expect(key).not.toBeNull(); let boardLoads = 0; page.on("request", (r) => { if (new URL(r.url()).pathname === "/board") boardLoads++; }); await page.locator(`.board .card[data-key="${key}"] a.open-card`).click(); await expect(page.getByRole("dialog")).toBeVisible(); await page.keyboard.press("Escape"); await expect(page).toHaveURL(/\/app\/jira\/links\?project=AWPCA$/); expect(await page.evaluate(() => window.scrollY)).toBeGreaterThan(y - 2); expect(boardLoads).toBe(0); // доска не перезагружалась // боковая панель закреплена (#69): ссылки разделов видны и после прокрутки, щелчок не двигает доску await page.getByRole("link", { name: "Задачи", exact: true }).click(); await expect(page).toHaveURL(/\/app\/jira\/issues\?project=AWPCA$/); await page.getByRole("link", { name: "Связи", exact: true }).click(); await expect.poll(() => page.evaluate(() => window.scrollY)).toBeGreaterThan(y - 2); }); test("заметка из окна уходит в хаб, карточка на доске остаётся на месте, прокрутка сохраняется", async ({ page }) => { // доска показывает вид работы по меткам Jira (fromHub), заметка work_kind в карточку доски не попадает: проверяем снимок /board await page.locator('.board .card[data-key="AURORA-9002"]').evaluate((e) => { (e as HTMLElement).dataset.marker = "keep"; }); await page.locator('.board .card[data-key="AURORA-9002"] a.open-card').click(); const d = page.getByRole("dialog"); const y = await page.evaluate(() => window.scrollY); await d.getByRole("button", { name: "Править" }).click(); await d.getByLabel("Вид работы").selectOption("тестирование"); const snap = page.waitForResponse((r) => new URL(r.url()).pathname === "/board" && r.request().method() === "GET"); await d.getByRole("button", { name: "Сохранить" }).click(); const body = await (await snap).json(); expect(body.issues.find((i: { key: string }) => i.key === "AURORA-9002").work_kind).toBe("тестирование"); await expect(d.getByRole("button", { name: "Править" })).toBeVisible(); await page.keyboard.press("Escape"); await expect(page.getByTestId("page-board")).toBeAttached(); await expect(page.locator('.board .card[data-key="AURORA-9002"]')).toBeVisible(); await expect(page.locator('.board .card[data-key="AURORA-9002"]')).toHaveAttribute("data-marker", "keep"); // узел не пересоздан expect(await page.evaluate(() => window.scrollY)).toBe(y); });