/** * @vitest-environment jsdom */ import { act, renderHook } from "@testing-library/react"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { useCreateFlowStore } from "@/stores/create-flow-store"; import type { UserMessageImageAttachment } from "@/types/stream"; import type { AgentAttachment } from "@getpaseo/protocol/messages"; import { useDraftAgentCreateFlow, type DraftCreateAttempt } from "./create-flow"; describe("useDraftAgentCreateFlow", () => { beforeEach(() => { useCreateFlowStore.setState({ pendingByDraftId: {} }); }); it("renders a prepared new-workspace create attempt as optimistic chat before continuing it", async () => { const image: UserMessageImageAttachment = { id: "image-1", mimeType: "image/png", storageType: "web-indexeddb", storageKey: "image-key", createdAt: 123, }; const attachment = { type: "review", cwd: "/repo", summary: "Review", } as unknown as AgentAttachment; const attempt: DraftCreateAttempt = { clientMessageId: "msg-prepared", text: "build this", timestamp: new Date("2026-05-25T00:00:00.000Z"), images: [image], attachments: [attachment], }; const createRequest = vi.fn( async (ctx: { attempt: DraftCreateAttempt; text: string; images?: UserMessageImageAttachment[]; attachments?: AgentAttachment[]; cwd: string; }) => ({ agentId: "agent-1", result: { id: "agent-1", ctx }, }), ); const onCreateSuccess = vi.fn(); const { result } = renderHook(() => useDraftAgentCreateFlow({ draftId: "draft-1", getPendingServerId: () => "server-1", initialAttempt: attempt, buildDraftAgent: (currentAttempt) => ({ currentAttempt }), createRequest, onCreateSuccess, }), ); expect(result.current.isSubmitting).toBe(true); expect(result.current.draftAgent).toEqual({ currentAttempt: attempt }); expect(result.current.optimisticStreamItems).toEqual([ { kind: "user_message", id: "msg-prepared", text: "build this", timestamp: attempt.timestamp, optimistic: true, images: [image], attachments: [attachment], }, ]); expect(createRequest).not.toHaveBeenCalled(); await act(async () => { await result.current.continueCreateFromAttempt({ attempt, cwd: "/repo" }); }); expect(createRequest).toHaveBeenCalledTimes(1); expect(createRequest).toHaveBeenCalledWith({ attempt, text: "build this", images: [image], attachments: [attachment], cwd: "/repo", }); expect(onCreateSuccess).toHaveBeenCalledTimes(1); }); it("allows retrying an empty prompt when the draft still has context attachments", async () => { const attachment = { kind: "chat_history", id: "chat-history-1", attachment: { type: "text", mimeType: "text/plain", contextKind: "chat_history", title: "Chat history", text: "Previous conversation", }, source: { serverId: "server-1", agentId: "agent-source", }, } as const; const createRequest = vi.fn(async () => ({ agentId: "agent-1", result: { id: "agent-1" }, })); const onCreateSuccess = vi.fn(); const validateBeforeSubmit = vi.fn(() => null); const { result } = renderHook(() => useDraftAgentCreateFlow({ draftId: "draft-1", getPendingServerId: () => "server-1", buildDraftAgent: (currentAttempt) => ({ currentAttempt }), createRequest, onCreateSuccess, validateBeforeSubmit, }), ); await act(async () => { await result.current.handleCreateFromInput({ text: " ", attachments: [attachment], cwd: "/repo", }); }); expect(validateBeforeSubmit).toHaveBeenCalledWith({ text: "", attachments: [attachment], cwd: "/repo", }); expect(createRequest).toHaveBeenCalledWith({ attempt: expect.objectContaining({ text: "", attachments: [attachment.attachment], }), text: "", attachments: [attachment.attachment], cwd: "/repo", }); expect(onCreateSuccess).toHaveBeenCalledTimes(1); }); });