import { render, screen, waitFor } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import type { AgentConfigInfo, AgentInfo } from "../api/agents"; import { agentsApi } from "../api/agents"; vi.mock("../api/agents", () => { const agentsApi = { listAgents: vi.fn(), getAgentConfig: vi.fn(), startAgent: vi.fn(), stopAgent: vi.fn(), reloadConfig: vi.fn(), }; return { agentsApi, subscribeAgentStream: vi.fn(() => () => {}) }; }); // Dynamic import so the mock is in place before the module loads const { AgentPanel } = await import("./AgentPanel"); const mockedAgents = { listAgents: vi.mocked(agentsApi.listAgents), getAgentConfig: vi.mocked(agentsApi.getAgentConfig), startAgent: vi.mocked(agentsApi.startAgent), }; const ROSTER: AgentConfigInfo[] = [ { name: "coder-1", role: "Full-stack engineer", model: "sonnet", allowed_tools: null, max_turns: 50, max_budget_usd: 5.0, }, ]; describe("AgentPanel diff command", () => { beforeAll(() => { Element.prototype.scrollIntoView = vi.fn(); }); beforeEach(() => { mockedAgents.getAgentConfig.mockResolvedValue(ROSTER); mockedAgents.listAgents.mockResolvedValue([]); }); it("shows diff command when an agent has a worktree path", async () => { const agentList: AgentInfo[] = [ { story_id: "33_diff_commands", agent_name: "coder-1", status: "running", session_id: null, worktree_path: "/tmp/project-story-33", base_branch: "master", }, ]; mockedAgents.listAgents.mockResolvedValue(agentList); render( , ); // Expand the agent detail by clicking the expand button const expandButton = await screen.findByText("▶"); await userEvent.click(expandButton); // The diff command should be rendered expect( await screen.findByText( 'cd "/tmp/project-story-33" && git difftool master...HEAD', ), ).toBeInTheDocument(); // A copy button should exist expect(screen.getByText("Copy")).toBeInTheDocument(); }); it("copies diff command to clipboard on click", async () => { const writeText = vi.fn().mockResolvedValue(undefined); Object.assign(navigator, { clipboard: { writeText }, }); const agentList: AgentInfo[] = [ { story_id: "33_diff_commands", agent_name: "coder-1", status: "completed", session_id: null, worktree_path: "/home/user/my-project-story-33", base_branch: "main", }, ]; mockedAgents.listAgents.mockResolvedValue(agentList); render( , ); const expandButton = await screen.findByText("▶"); await userEvent.click(expandButton); const copyButton = await screen.findByText("Copy"); await userEvent.click(copyButton); await waitFor(() => { expect(writeText).toHaveBeenCalledWith( 'cd "/home/user/my-project-story-33" && git difftool main...HEAD', ); }); expect(await screen.findByText("Copied")).toBeInTheDocument(); }); it("uses base_branch from the server in the diff command", async () => { const agentList: AgentInfo[] = [ { story_id: "33_diff_commands", agent_name: "coder-1", status: "running", session_id: null, worktree_path: "/tmp/wt", base_branch: "develop", }, ]; mockedAgents.listAgents.mockResolvedValue(agentList); render( , ); const expandButton = await screen.findByText("▶"); await userEvent.click(expandButton); expect( await screen.findByText('cd "/tmp/wt" && git difftool develop...HEAD'), ).toBeInTheDocument(); }); it("defaults to master when base_branch is null", async () => { const agentList: AgentInfo[] = [ { story_id: "33_diff_commands", agent_name: "coder-1", status: "running", session_id: null, worktree_path: "/tmp/wt", base_branch: null, }, ]; mockedAgents.listAgents.mockResolvedValue(agentList); render( , ); const expandButton = await screen.findByText("▶"); await userEvent.click(expandButton); expect( await screen.findByText('cd "/tmp/wt" && git difftool master...HEAD'), ).toBeInTheDocument(); }); });