/** * @file Tests for CloneSourcesForm: every URL in the box is cloned in turn as * an extra folder, a host that wants a login opens the login row, and Retry * re-runs only the failed URLs with that login. An SSH link while the * account has no key is never sent — the user is pointed at Settings → Git — * and an HTTPS host with no saved login is flagged before Clone. The * partial-clone box adds `partial: true` to every clone. * @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 "../../../i18n"; vi.mock("../../../lib/api", () => ({ api: { lanes: { cloneFolder: vi.fn() }, gitIdentity: { get: vi.fn() } }, })); import { api, type GitIdentity, type LaneSourcesView } from "../../../lib/api"; import { CloneSourcesForm, cloneTarget } from "../CloneSourcesForm"; const view = { sources: [] } as unknown as LaneSourcesView & { path: string }; describe("CloneSourcesForm", () => { beforeEach(() => { vi.mocked(api.lanes.cloneFolder).mockReset(); // Unknown identity: nothing is checked up front. vi.mocked(api.gitIdentity.get).mockReset().mockRejectedValue(new Error("old server")); }); it("clones each URL, asks for a login where needed, and retries only that one", async () => { const user = userEvent.setup(); const onAdded = vi.fn(); vi.mocked(api.lanes.cloneFolder).mockImplementation(async (_id, body) => { if (body?.url.includes("private") && !body.credentials) throw Object.assign(new Error("login"), { code: "ECREDENTIALS", auth: { protocol: "https", host: "private.test" }, }); return view; }); render(); await user.type( screen.getByTestId("workspace-clone-input"), "https://h/a.git\nhttps://private.test/b.git\nhttps://h/a.git" ); await user.click(screen.getByTestId("workspace-clone-run")); await waitFor(() => expect(api.lanes.cloneFolder).toHaveBeenCalledTimes(2)); expect(onAdded).toHaveBeenCalledTimes(1); expect(await screen.findByText(/private\.test needs a login/)).toBeInTheDocument(); // Only what is left stays in the box. expect(screen.getByTestId("workspace-clone-input")).toHaveValue("https://private.test/b.git"); await user.type(screen.getByLabelText("Username"), "dev"); await user.type(screen.getByLabelText("Password or access token"), "tok"); await user.click(screen.getByRole("button", { name: "Retry the failed ones" })); await waitFor(() => expect(onAdded).toHaveBeenCalledTimes(2)); expect(api.lanes.cloneFolder).toHaveBeenLastCalledWith(3, { progressToken: expect.any(String), url: "https://private.test/b.git", credentials: { username: "dev", password: "tok", remember: true }, }); expect(screen.getByTestId("workspace-clone-input")).toHaveValue(""); }); it("asks for partial clones when the box is ticked", async () => { const user = userEvent.setup(); vi.mocked(api.lanes.cloneFolder).mockResolvedValue(view); render(); await user.type(screen.getByTestId("workspace-clone-input"), "https://h/big.git"); await user.click(screen.getByTestId("workspace-clone-partial")); await user.click(screen.getByTestId("workspace-clone-run")); await waitFor(() => expect(api.lanes.cloneFolder).toHaveBeenCalledWith(3, { progressToken: expect.any(String), url: "https://h/big.git", partial: true, }) ); }); it("tells an SSH link from an HTTPS one", () => { expect(cloneTarget("git@github.com:o/r.git")).toEqual({ kind: "ssh", host: "github.com" }); expect(cloneTarget("ssh://git@h.test:2222/o/r")).toEqual({ kind: "ssh", host: "h.test" }); expect(cloneTarget("https://h.test/o/r.git")).toEqual({ kind: "https", host: "h.test" }); expect(cloneTarget("not a url")).toBeNull(); }); it("does not clone an SSH link before the account has a key, and flags an HTTPS host with no login", async () => { const user = userEvent.setup(); vi.mocked(api.gitIdentity.get).mockResolvedValue({ ssh: null, sshKeys: [], https: [], } as unknown as GitIdentity); vi.mocked(api.lanes.cloneFolder).mockResolvedValue(view); render(); await waitFor(() => expect(api.gitIdentity.get).toHaveBeenCalled()); await user.type( screen.getByTestId("workspace-clone-input"), "git@github.com:o/r.git\nhttps://h.test/a.git" ); expect(screen.getByTestId("workspace-clone-need-ssh")).toHaveTextContent("github.com"); expect(screen.getByTestId("workspace-clone-need-login")).toHaveTextContent("h.test"); await user.click(screen.getByTestId("workspace-clone-run")); await waitFor(() => expect(api.lanes.cloneFolder).toHaveBeenCalledTimes(1)); expect(api.lanes.cloneFolder).toHaveBeenCalledWith(3, { url: "https://h.test/a.git", progressToken: expect.any(String), }); expect(await screen.findByText(/has no SSH key yet/)).toBeInTheDocument(); expect(screen.getByTestId("workspace-clone-input")).toHaveValue("git@github.com:o/r.git"); }); });