/** * @vitest-environment jsdom */ import React from "react"; import { act } from "react"; import { createRoot, type Root } from "react-dom/client"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import type { ComposerAttachment } from "@/attachments/types"; import type { MessagePayload } from "@/components/message-input"; import { useCreateFlowStore } from "@/stores/create-flow-store"; import { useWorkspaceDraftSubmissionStore } from "@/stores/workspace-draft-submission-store"; import type { StreamItem } from "@/types/stream"; import { WorkspaceDraftAgentTab } from "./workspace-draft-agent-tab"; const { createAgentMock, getCheckoutStatusMock, onRuntimeEventMock, latestComposerText, latestComposerDisabled, latestStreamText, onCreatedMock, } = vi.hoisted(() => ({ createAgentMock: vi.fn(), getCheckoutStatusMock: vi.fn(), onRuntimeEventMock: vi.fn(() => () => {}), latestComposerText: { current: null as string | null }, latestComposerDisabled: { current: null as boolean | null }, latestStreamText: { current: null as string | null }, onCreatedMock: vi.fn(), })); vi.mock("react-native-unistyles", () => ({ StyleSheet: { create: (factory: unknown) => typeof factory === "function" ? factory({ colors: { surface0: "#000", surface2: "#222", destructive: "#f00", }, spacing: { 2: 8, 3: 12, 4: 16, 6: 24 }, borderRadius: { md: 6 }, fontSize: { sm: 13 }, }) : factory, }, useUnistyles: () => ({ rt: { breakpoint: "lg" } }), })); vi.mock("react-native-safe-area-context", () => ({ useSafeAreaInsets: () => ({ top: 0, right: 0, bottom: 0, left: 0 }), })); vi.mock("@/constants/platform", () => ({ isWeb: true, isNative: false, })); vi.mock("@/runtime/host-runtime", () => ({ useHostRuntimeClient: () => ({ createAgent: createAgentMock, getCheckoutStatus: getCheckoutStatusMock, on: onRuntimeEventMock, }), useHostRuntimeIsConnected: () => true, })); vi.mock("@/stores/session-store-hooks", () => ({ useWorkspaceExecutionAuthority: () => ({ ok: true, authority: { workspaceId: "workspace-1", workspaceDirectory: "/repo/.paseo/worktrees/workspace-1", }, }), })); vi.mock("@/hooks/use-agent-input-draft", () => ({ useAgentInputDraft: () => { const [text, setText] = React.useState("please review this change"); const [attachments, setAttachments] = React.useState([]); return { text, setText, attachments, setAttachments, cwd: "/repo/.paseo/worktrees/workspace-1", clear: () => { setText(""); setAttachments([]); }, isHydrated: true, composerState: { providerDefinitions: [{ id: "codex", label: "Codex" }], selectedProvider: "codex", selectedMode: "", modeOptions: [], selectedModel: "gpt-5.4", availableModels: [{ id: "gpt-5.4", label: "GPT-5.4" }], allProviderModels: {}, isAllModelsLoading: false, isModelLoading: false, effectiveModelId: "gpt-5.4", effectiveThinkingOptionId: "", featureValues: undefined, statusControls: { providerDefinitions: [{ id: "codex", label: "Codex" }], selectedProvider: "codex", modeOptions: [], selectedMode: "", models: [{ id: "gpt-5.4", label: "GPT-5.4" }], selectedModel: "gpt-5.4", thinkingOptions: [], selectedThinkingOptionId: "", isModelLoading: false, allProviderModels: {}, isAllModelsLoading: false, features: [], }, commandDraftConfig: undefined, persistFormPreferences: vi.fn(), }, }; }, })); vi.mock("@/utils/encode-images", () => ({ encodeImages: vi.fn(async () => []), })); vi.mock("@/components/composer-attachments", () => ({ splitComposerAttachmentsForSubmit: (attachments: ComposerAttachment[]) => ({ images: [], attachments, }), })); vi.mock("@/attachments/composer-workspace-attachments", () => ({ composerWorkspaceAttachment: { userAttachmentsOnly: (attachments: ComposerAttachment[]) => attachments.filter( (attachment): attachment is Exclude => attachment.kind !== "review", ), }, })); vi.mock("@/components/composer", () => ({ Composer: ({ value, isSubmitLoading, }: { onSubmitMessage: (payload: MessagePayload) => Promise; value: string; isSubmitLoading?: boolean; }) => { latestComposerText.current = value; latestComposerDisabled.current = isSubmitLoading ?? false; return (