sdlc-hub/web/e2e/board.spec.ts

111 lines
7.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { expect, test } from "@playwright/test";
import { CW } from "../src/board/constants.ts";
import { agentServeRefresh, 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.getByRole("button", { name: "Обновить из Jira" });
await btn.click();
await expect(btn).toBeDisabled();
await expect(page.getByRole("status")).toContainText(/пакет #\d+/);
await agentServeRefresh();
await expect(page.getByRole("status")).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\/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 })).toHaveClass(/active/);
});
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<HTMLElement>(".board .card[data-key] a.open-card")]
.find((e) => { const r = e.getBoundingClientRect(); return r.top > 200 && r.bottom < vh - 20; });
return a?.closest<HTMLElement>(".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\/board\?project=AWPCA$/);
expect(await page.evaluate(() => window.scrollY)).toBeGreaterThan(y - 2);
expect(boardLoads).toBe(0); // доска не перезагружалась
// ссылки меню вверху страницы: обычный click прокрутил бы доску к ним до перехода и затёр запомненное, поэтому dispatchEvent
await page.getByRole("link", { name: "Задачи", exact: true }).dispatchEvent("click");
await expect(page).toHaveURL(/\/app\/issues\?project=AWPCA$/);
await page.getByRole("link", { name: "Доска", exact: true }).dispatchEvent("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);
});