188 lines
13 KiB
TypeScript
188 lines
13 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
||
import { login } from "./hub.ts";
|
||
|
||
test("фильтр → карточка окном → заметка сохраняется и переживает перезагрузку", async ({ page }) => {
|
||
await login(page, "/app/issues");
|
||
await page.getByLabel("Исполнитель").selectOption("Петров Пётр Петрович");
|
||
await expect(page).toHaveURL(/assignee=/);
|
||
await page.getByRole("link", { name: "AURORA-9002", exact: true }).click();
|
||
const d = page.getByRole("dialog");
|
||
await expect(d.getByRole("heading", { name: "API свода" })).toBeVisible();
|
||
await d.getByRole("button", { name: "Править" }).click();
|
||
await d.getByLabel("Осталось").fill("e2e: дописать тесты");
|
||
await d.getByRole("button", { name: "Сохранить" }).click();
|
||
await expect(d.getByText("e2e: дописать тесты")).toBeVisible();
|
||
await page.reload();
|
||
await expect(page.getByRole("dialog").getByText("e2e: дописать тесты")).toBeVisible();
|
||
await page.keyboard.press("Escape");
|
||
await expect(page.getByRole("dialog")).toHaveCount(0);
|
||
await expect(page).toHaveURL(/\/app\/issues\?project=AWPCA&assignee=/);
|
||
await expect(page.getByLabel("Исполнитель")).toHaveValue("Петров Пётр Петрович");
|
||
});
|
||
|
||
test("окно поверх списка: прокрутка списка на месте при открытии и после закрытия", async ({ page }) => {
|
||
await page.setViewportSize({ width: 1280, height: 320 });
|
||
await login(page, "/app/issues");
|
||
await expect(page.locator("table.grid tbody tr")).toHaveCount(9); // AURORA-9006 «Готово» скрыта
|
||
const y = await page.evaluate(() => { window.scrollTo(0, document.documentElement.scrollHeight); return window.scrollY; });
|
||
expect(y).toBeGreaterThan(50);
|
||
await page.locator("table.grid tbody tr").last().getByRole("link").click();
|
||
await expect(page.getByRole("dialog")).toBeVisible();
|
||
expect(await page.evaluate(() => window.scrollY)).toBe(y);
|
||
await page.keyboard.press("Escape");
|
||
await expect(page.getByRole("dialog")).toHaveCount(0);
|
||
expect(await page.evaluate(() => window.scrollY)).toBe(y);
|
||
});
|
||
|
||
test("переход по связи и «назад»; ✕ и щелчок по фону; после закрытия «назад» не открывает карточку", async ({ page }) => {
|
||
await login(page); // доска
|
||
await page.getByRole("link", { name: "Задачи", exact: true }).click();
|
||
await page.getByRole("link", { name: "AURORA-9001", exact: true }).click();
|
||
const d = page.getByRole("dialog");
|
||
await d.locator(".links-sec").getByRole("link", { name: "AURORA-9002", exact: true }).click();
|
||
await expect(page).toHaveURL(/\/app\/issues\/AURORA-9002$/);
|
||
await expect(d.getByRole("heading", { name: "API свода" })).toBeVisible();
|
||
await page.goBack();
|
||
await expect(d.getByRole("heading", { name: "Схема свода" })).toBeVisible();
|
||
await d.locator(".links-sec").getByRole("link", { name: "AURORA-9002", exact: true }).click();
|
||
await d.getByRole("button", { name: "Закрыть" }).click();
|
||
await expect(page).toHaveURL(/\/app\/issues\?project=AWPCA$/);
|
||
await expect(page.getByRole("dialog")).toHaveCount(0);
|
||
await page.getByRole("link", { name: "AURORA-9003", exact: true }).click();
|
||
await expect(page.getByRole("dialog")).toBeVisible();
|
||
await page.mouse.click(5, 300); // фон слева от окна
|
||
await expect(page.getByRole("dialog")).toHaveCount(0);
|
||
await page.goBack();
|
||
await expect(page).toHaveURL(/\/app\/board\?project=AWPCA$/);
|
||
await expect(page.getByRole("dialog")).toHaveCount(0);
|
||
});
|
||
|
||
test("прямой адрес и перезагрузка: окно поверх списка, ✕ ведёт в список", async ({ page }) => {
|
||
await login(page, "/app/issues/AURORA-9001");
|
||
const d = page.getByRole("dialog");
|
||
await expect(d.getByRole("heading", { name: "Схема свода" })).toBeVisible();
|
||
await expect(page.getByTestId("page-issues")).toBeAttached();
|
||
await page.reload();
|
||
await expect(page.getByRole("dialog").getByRole("heading", { name: "Схема свода" })).toBeVisible();
|
||
await page.getByRole("dialog").getByRole("button", { name: "Закрыть" }).click();
|
||
await expect(page).toHaveURL(/\/app\/issues\?project=AWPCA$/);
|
||
await expect(page.getByRole("dialog")).toHaveCount(0);
|
||
});
|
||
|
||
test("карточка: описание свёрнуто, комментарии новые сверху и скрываются с запоминанием, команды свёрнуты", async ({ page }) => {
|
||
await login(page, "/app/issues/AURORA-9001");
|
||
const d = page.getByRole("dialog");
|
||
await expect(d.getByRole("heading", { name: "Комментарии (3)" })).toBeVisible();
|
||
await expect(d.getByTestId("comments").getByRole("listitem").first()).toContainText("[мост] служебный комментарий");
|
||
await expect(d.getByRole("button", { name: "развернуть" })).toBeVisible();
|
||
await expect(d.locator("div.description")).toHaveClass(/clamped/); // свёрнуто по высоте (текст в DOM остаётся)
|
||
const hClamped = (await d.locator("div.description").boundingBox())!.height;
|
||
expect(await d.locator("div.description").evaluate((e) => e.scrollHeight > e.clientHeight)).toBe(true);
|
||
await d.getByRole("button", { name: "развернуть" }).click();
|
||
await expect(d.locator("div.description")).not.toHaveClass(/clamped/);
|
||
expect((await d.locator("div.description").boundingBox())!.height).toBeGreaterThan(hClamped);
|
||
await expect(d.getByText("Конец описания.")).toBeVisible();
|
||
await expect(d.getByRole("cell", { name: "ensure_fields" })).toBeHidden();
|
||
await d.getByText("Команды моста (2)").click();
|
||
await expect(d.getByRole("cell", { name: "ensure_fields" })).toBeVisible();
|
||
await d.getByRole("button", { name: "Скрыть" }).click();
|
||
await expect(d.getByText("Первый комментарий e2e")).toHaveCount(0);
|
||
await page.reload();
|
||
await expect(page.getByRole("dialog").getByRole("button", { name: "Показать" })).toBeVisible();
|
||
await expect(page.getByRole("dialog").getByText("Первый комментарий e2e")).toHaveCount(0);
|
||
});
|
||
|
||
test("разметка Jira: описание и комментарии отрендерены, «исходник» у каждого блока, ключ задачи — ссылка", async ({ page }) => {
|
||
await login(page, "/app/issues/AURORA-9001");
|
||
const d = page.getByRole("dialog");
|
||
const desc = d.locator("section", { has: page.getByRole("heading", { name: "Описание" }) });
|
||
await expect(desc.getByRole("heading", { level: 3, name: "Контекст" })).toBeVisible();
|
||
await expect(desc.getByRole("listitem").first()).toHaveText("Таблицы.");
|
||
await expect(desc.getByText("КФО", { exact: true })).toHaveJSProperty("tagName", "STRONG");
|
||
await expect(desc).not.toContainText("h3.");
|
||
await desc.getByRole("button", { name: "исходник" }).click();
|
||
await expect(desc.locator("pre.description")).toContainText("h3. Контекст");
|
||
await expect(desc.locator("pre.description")).toContainText("# Таблицы.");
|
||
await desc.getByRole("button", { name: "текст" }).click();
|
||
await expect(desc.getByRole("heading", { level: 3, name: "Контекст" })).toBeVisible();
|
||
|
||
const items = d.getByTestId("comments").getByRole("listitem");
|
||
const first = items.filter({ hasText: "Первый комментарий e2e" });
|
||
await expect(first.getByText("Первый комментарий e2e")).toHaveJSProperty("tagName", "STRONG");
|
||
await first.getByRole("button", { name: "исходник" }).click();
|
||
await expect(first.locator("pre.body")).toContainText("*Первый комментарий e2e*");
|
||
await expect(d.locator("pre.body")).toHaveCount(1);
|
||
|
||
await items.filter({ hasText: "Схему согласовали" }).getByRole("link", { name: "AURORA-9002" }).click();
|
||
await expect(d.getByRole("heading", { name: "API свода" })).toBeVisible();
|
||
await page.goBack();
|
||
await expect(d.getByRole("heading", { name: "Схема свода" })).toBeVisible();
|
||
await expect(d.locator("pre.body, pre.description")).toHaveCount(0); // после перехода всё снова отрендерено
|
||
});
|
||
|
||
test("C-1: повторное открытие из кэша — длинное описание свёрнуто с кнопкой «развернуть»", async ({ page }) => {
|
||
await login(page, "/app/issues");
|
||
await page.getByRole("link", { name: "AURORA-9001", exact: true }).click();
|
||
const d = page.getByRole("dialog");
|
||
await expect(d.getByRole("button", { name: "развернуть" })).toBeVisible();
|
||
await page.keyboard.press("Escape");
|
||
await expect(page.getByRole("dialog")).toHaveCount(0);
|
||
await page.getByRole("link", { name: "AURORA-9001", exact: true }).click();
|
||
await expect(d.getByRole("button", { name: "развернуть" })).toBeVisible();
|
||
});
|
||
|
||
test("I-1: телефон 375 px — таблица описания прокручивается внутри, заголовки таблицы без чужого стиля", async ({ page }) => {
|
||
await page.setViewportSize({ width: 375, height: 800 });
|
||
await login(page, "/app/issues/AURORA-9001");
|
||
const d = page.getByRole("dialog");
|
||
await d.getByRole("button", { name: "развернуть" }).click();
|
||
const th = d.getByRole("columnheader", { name: "Поле", exact: true });
|
||
await expect(th).toBeAttached();
|
||
expect(await d.evaluate((el) => el.scrollWidth <= el.clientWidth + 1)).toBe(true);
|
||
expect(await th.evaluate((el) => getComputedStyle(el).textTransform)).toBe("none");
|
||
expect(await d.getByRole("cell", { name: "data_type" }).evaluate((el) => el.scrollWidth <= el.clientWidth + 1)).toBe(true); // слово не рвётся (M-3)
|
||
});
|
||
|
||
test("несохранённая заметка: Esc спрашивает, «Остаться» оставляет окно, «Уйти» закрывает", async ({ page }) => {
|
||
await login(page, "/app/issues");
|
||
await page.getByRole("link", { name: "AURORA-9003", exact: true }).click();
|
||
const d = page.getByRole("dialog");
|
||
await d.getByRole("button", { name: "Править" }).click();
|
||
await d.getByLabel("Сделано").fill("черновик");
|
||
await page.keyboard.press("Escape");
|
||
await expect(d.getByText("Есть несохранённые правки заметки. Уйти без сохранения?")).toBeVisible();
|
||
await d.getByRole("button", { name: "Остаться" }).click();
|
||
await expect(d.getByLabel("Сделано")).toHaveValue("черновик");
|
||
await page.keyboard.press("Escape");
|
||
await d.getByRole("button", { name: "Уйти" }).click();
|
||
await expect(page.getByRole("dialog")).toHaveCount(0);
|
||
await expect(page).toHaveURL(/\/app\/issues\?project=AWPCA$/);
|
||
});
|
||
|
||
test("узкий экран: окно на всю ширину, заметки выше связей, без горизонтальной прокрутки", async ({ page }) => {
|
||
await page.setViewportSize({ width: 600, height: 800 });
|
||
await login(page, "/app/issues/AURORA-9001");
|
||
const d = page.getByRole("dialog");
|
||
await expect(d.getByRole("heading", { name: "Схема свода" })).toBeVisible();
|
||
expect((await d.boundingBox())!.width).toBeGreaterThan(590);
|
||
const notesY = (await d.getByRole("heading", { name: "Служебные заметки" }).boundingBox())!.y;
|
||
const linksY = (await d.getByRole("heading", { name: "Связи", exact: true }).boundingBox())!.y;
|
||
expect(notesY).toBeLessThan(linksY);
|
||
expect(await d.evaluate((el) => el.scrollWidth <= el.clientWidth + 1)).toBe(true);
|
||
await d.getByRole("button", { name: "развернуть" }).click(); // широкая таблица описания прокручивается внутри
|
||
await expect(d.getByRole("columnheader", { name: "Источник" })).toBeAttached();
|
||
expect(await d.evaluate((el) => el.scrollWidth <= el.clientWidth + 1)).toBe(true);
|
||
});
|
||
|
||
test("закрытые скрыты по умолчанию, снятый флажок показывает их", async ({ page }) => {
|
||
await login(page, "/app/issues");
|
||
await expect(page.locator("table.grid tbody tr")).toHaveCount(9);
|
||
await expect(page.getByRole("link", { name: "AURORA-9006", exact: true })).toHaveCount(0);
|
||
const hide = page.getByRole("checkbox", { name: "скрыть закрытые" });
|
||
await hide.click(); // не uncheck(): адрес меняется навигацией, флажок следует за ним не сразу
|
||
await expect(page).toHaveURL(/closed=1/);
|
||
await expect(hide).not.toBeChecked();
|
||
await expect(page.getByRole("link", { name: "AURORA-9006", exact: true })).toBeVisible();
|
||
await expect(page.locator("table.grid tbody tr")).toHaveCount(10);
|
||
});
|