sdlc-hub/web/src/modules/jira/agile/AgileGate.test.tsx
Andrey Epifancev f21dea39b6 test(web): e2e широкой доски и фильтров, сид WIDE_E2E, тесты AgileGate (#112, T9.4, T12.2–T12.4)
Также: шеврон свёртки секции «Бэклог» — свёрнуто вниз, развёрнуто вверх (T4.5).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 21:04:57 +04:00

69 lines
3.7 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 { render, screen, waitFor, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { createMemoryRouter } from "react-router";
import { beforeEach, describe, expect, it } from "vitest";
import { App } from "../../../App.tsx";
import { setToken } from "../../../auth/token.ts";
import settings from "../board/__fixtures__/settings.json";
import { routes } from "../../../routes.tsx";
import { json, mockFetch } from "../../../test/fetchMock.ts";
import type { AgileResponse } from "../api/types.ts";
const S = { label: "AWPCA", name: "АРМ КА", board_id: 4216, board_type: "scrum", created_at: "", issues_count: 9, jira_synced_at: null };
const K = { label: "KAN", name: "Канбан", board_id: 5120, board_type: "kanban", created_at: "", issues_count: 4, jira_synced_at: null };
const data: AgileResponse = {
board: { id: 4216, type: "scrum", columns: [{ name: "Новая", statuses: ["Новая"] }], kanban_backlog: null, fetched_at: "2026-10-24T10:00:00+00:00" },
sprints: [], backlog: [], board_issues: [],
};
const open = (path: string) => {
const router = createMemoryRouter(routes, { initialEntries: [path], basename: "/app" });
render(<App router={router} />);
return router;
};
const base = (method: string, pathname: string, projects: unknown[]) => {
const k = `${method} ${pathname}`;
if (k === "GET /projects") return json(200, { projects });
if (k === "GET /settings") return json(200, settings);
if (k === "GET /issues") return json(200, { issues: [] });
if (k === "GET /batches") return json(200, { batches: [] });
if (k === "GET /agents") return json(200, { agents: [] });
return null;
};
describe("AgileGate (T9.4)", () => {
beforeEach(() => { setToken("tok"); localStorage.clear(); });
it("пока /agile не ответил — «Загрузка…»", async () => {
mockFetch((method, url) => {
if (`${method} ${url.pathname}` === "GET /agile") return new Promise<Response>(() => {});
return base(method, url.pathname, [S]) ?? json(404, { error: "not_found" });
});
open("/app/jira/sprint?project=AWPCA");
expect(await screen.findByText("Загрузка…")).toBeInTheDocument();
});
it("ошибка /agile — текст ошибки и «Повторить», щелчок повторяет запрос", async () => {
let calls = 0;
mockFetch((method, url) => {
if (`${method} ${url.pathname}` === "GET /agile") { calls += 1; return calls === 1 ? json(500, { error: "hub_down" }) : json(200, data); }
return base(method, url.pathname, [S]) ?? json(404, { error: "not_found" });
});
open("/app/jira/sprint?project=AWPCA");
const retry = await screen.findByRole("button", { name: "Повторить" });
expect(screen.queryByText("Загрузка…")).not.toBeInTheDocument();
await userEvent.click(retry);
await waitFor(() => expect(calls).toBe(2));
await waitFor(() => expect(screen.queryByRole("button", { name: "Повторить" })).not.toBeInTheDocument());
});
it("меню kanban-проекта: «Kanban» есть, «Бэклог» и «Спринт» нет", async () => {
mockFetch((method, url) => base(method, url.pathname, [K]) ?? json(200, { ...data, board: { ...data.board, type: "kanban" }, sprints: [], backlog: null }));
open("/app/jira/kanban?project=KAN");
const menu = await screen.findByRole("group", { name: "Jira" });
expect(await within(menu).findByRole("link", { name: "Kanban" })).toBeInTheDocument();
expect(within(menu).queryByRole("link", { name: "Бэклог" })).not.toBeInTheDocument();
expect(within(menu).queryByRole("link", { name: "Спринт" })).not.toBeInTheDocument();
});
});