/** * @file Pins the paused cherry-pick/revert banner: it names the commit it * stopped at and the step ("2 of 3"), Continue waits for every conflict to be * resolved, Skip and Abort each need a second click and only then send * `confirm: true`, and it draws nothing when no pick is open. * @author Nguyễn Ngọc Trí Vĩ */ import { describe, it, expect, vi, beforeEach } from "vitest"; import { render, screen, waitFor } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { PickBanner } from "../PickBanner"; import { api } from "../../../../lib/api"; vi.mock("../../../../lib/api", () => ({ api: { lanes: { gitHistory: { sequence: vi.fn(), act: vi.fn() } } }, })); const paused = (conflicts: string[]) => ({ available: true as const, active: true as const, operation: "cherry-pick" as const, current: { sha: "b".repeat(40), short: "bbbbbbb", subject: "edit a" }, remaining: [{ sha: "c".repeat(40), short: "ccccccc", subject: "add c" }], done: 1, startedFrom: "a".repeat(40), conflicts, }); const props = () => ({ target: 7, conflicts: 1, reread: 0, busy: false, onBusy: vi.fn(), onDone: vi.fn(), }); beforeEach(() => { vi.mocked(api.lanes.gitHistory.act).mockReset().mockResolvedValue({ action: "pick-continue", ok: true, output: "", conflicts: [], paused: false, commits: [], }); }); describe("PickBanner", () => { it("names the stop and its step, and Continue waits for the conflicts", async () => { vi.mocked(api.lanes.gitHistory.sequence).mockResolvedValue(paused(["a.txt"])); render(); const banner = await screen.findByTestId("pick-banner"); expect(banner).toHaveTextContent('cherry-pick paused at bbbbbbb "edit a" (2 of 3)'); expect(banner).toHaveTextContent("Still to apply: ccccccc"); expect(screen.getByTestId("pick-continue")).toBeDisabled(); }); it("continues once resolved, and skips/aborts only on a second click", async () => { const user = userEvent.setup(); vi.mocked(api.lanes.gitHistory.sequence).mockResolvedValue(paused([])); const p = props(); render(); await user.click(await screen.findByTestId("pick-continue")); await waitFor(() => expect(api.lanes.gitHistory.act).toHaveBeenCalledWith(7, "pick-continue", {}) ); expect(p.onDone).toHaveBeenCalled(); await user.click(screen.getByTestId("pick-skip")); expect(api.lanes.gitHistory.act).toHaveBeenCalledTimes(1); await user.click(screen.getByTestId("pick-skip")); expect(api.lanes.gitHistory.act).toHaveBeenLastCalledWith(7, "pick-skip", { confirm: true }); await user.click(screen.getByTestId("pick-abort")); expect(api.lanes.gitHistory.act).toHaveBeenCalledTimes(2); await user.click(screen.getByTestId("pick-abort")); expect(api.lanes.gitHistory.act).toHaveBeenLastCalledWith(7, "pick-abort", { confirm: true }); }); it("draws nothing when no pick is open", async () => { vi.mocked(api.lanes.gitHistory.sequence).mockResolvedValue({ available: true, active: false }); const { container } = render(); await waitFor(() => expect(api.lanes.gitHistory.sequence).toHaveBeenCalled()); expect(container).toBeEmptyDOMElement(); }); });