import { render, screen, waitFor } from "@testing-library/react"; import { beforeAll, afterAll, beforeEach, describe, expect, it, vi } from "vitest"; import { PrCreateModal } from "../PrCreateModal"; import { loadAllAppCss } from "../../test/cssFixture"; const mocks = vi.hoisted(() => ({ generatePrMetadata: vi.fn(), fetchPrPreflight: vi.fn(), fetchPrOptions: vi.fn(), createPr: vi.fn(), })); vi.mock("../../api", () => ({ generatePrMetadata: mocks.generatePrMetadata, fetchPrPreflight: mocks.fetchPrPreflight, fetchPrOptions: mocks.fetchPrOptions, createPr: mocks.createPr, })); describe("PrCreateModal layout", () => { let styleEl: HTMLStyleElement; beforeAll(() => { styleEl = document.createElement("style"); styleEl.textContent = loadAllAppCss(); document.head.appendChild(styleEl); }); afterAll(() => { styleEl.remove(); }); beforeEach(() => { vi.clearAllMocks(); mocks.generatePrMetadata.mockResolvedValue({ title: "AI title", body: "AI body", templateUsed: false }); mocks.fetchPrPreflight.mockResolvedValue({ branchOnRemote: true, commitsPresent: true, conflictsWithBase: false, ghAuthOk: true, defaultBaseBranch: "main", head: "fusion/FN-5049", commits: [], changedFiles: [], }); mocks.fetchPrOptions.mockResolvedValue({ baseBranches: ["main"], reviewers: [], assignees: [], labels: [], }); }); it("renders a dedicated scroll body between modal header and actions", async () => { render(); await waitFor(() => expect(mocks.generatePrMetadata).toHaveBeenCalled()); const dialog = screen.getByRole("dialog"); const modal = dialog.classList.contains("modal") ? dialog : dialog.closest(".modal"); expect(modal).toBeTruthy(); const header = modal?.querySelector(":scope > .modal-header"); const body = modal?.querySelector(":scope > .pr-create-modal__body"); const actions = modal?.querySelector(":scope > .modal-actions"); expect(header).toBeTruthy(); expect(body).toBeTruthy(); expect(actions).toBeTruthy(); expect(actions?.parentElement).toBe(modal); const allAutoOverflow = Array.from(modal?.querySelectorAll("*") ?? []).filter( (element) => getComputedStyle(element).overflowY === "auto", ); expect(allAutoOverflow).toHaveLength(1); expect(allAutoOverflow[0]).toBe(body); }); });