// @vitest-environment jsdom import { useState } from "react"; import { createRoot, type Root } from "react-dom/client"; import { flushSync } from "react-dom"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { Agent, Environment, UserSecretDefinition } from "@paperclipai/shared"; import { getEnvironmentCapabilities } from "@paperclipai/shared"; import { TooltipProvider } from "@/components/ui/tooltip"; import { ToastProvider } from "../context/ToastContext"; import { AgentConfigForm, AdapterLoginPanel, type AdapterLoginDescriptor } from "./AgentConfigForm"; import { defaultCreateValues } from "./agent-config-defaults"; import { buildNewAgentHirePayload } from "../lib/new-agent-hire-payload"; import { ApiError } from "../api/client"; const mockAgentsApi = vi.hoisted(() => ({ adapterModels: vi.fn(), detectModel: vi.fn(), list: vi.fn(), testEnvironment: vi.fn(), startAdapterAuthLogin: vi.fn(), getAdapterAuthLoginStatus: vi.fn(), cancelAdapterAuthLogin: vi.fn(), startClaudeSetupTokenLogin: vi.fn(), getClaudeSetupTokenLoginStatus: vi.fn(), getClaudeSetupTokenLoginPrompt: vi.fn(), submitClaudeSetupTokenBrowserCode: vi.fn(), completeClaudeSetupTokenLogin: vi.fn(), cancelClaudeSetupTokenLogin: vi.fn(), getClaudeOAuthTokenStatus: vi.fn(), })); const mockClipboard = vi.hoisted(() => ({ copyTextToClipboard: vi.fn(), })); const mockEnvironmentsApi = vi.hoisted(() => ({ list: vi.fn(), capabilities: vi.fn(), })); const mockInstanceSettingsApi = vi.hoisted(() => ({ get: vi.fn(), getExperimental: vi.fn(), getGeneral: vi.fn(), })); const mockSecretsApi = vi.hoisted(() => ({ list: vi.fn(), listProposals: vi.fn(), listUserSecretDefinitions: vi.fn(async () => [] as unknown[]), })); vi.mock("../api/agents", () => ({ agentsApi: mockAgentsApi, })); vi.mock("../api/environments", () => ({ environmentsApi: mockEnvironmentsApi, })); vi.mock("../api/instanceSettings", () => ({ instanceSettingsApi: mockInstanceSettingsApi, })); vi.mock("../api/secrets", () => ({ secretsApi: mockSecretsApi, })); vi.mock("../lib/clipboard", () => ({ copyTextToClipboard: mockClipboard.copyTextToClipboard, })); vi.mock("../context/CompanyContext", () => ({ useCompany: () => ({ companies: [{ id: "company-1", name: "Paperclip" }], selectedCompanyId: "company-1", selectedCompany: { id: "company-1", name: "Paperclip" }, selectionSource: "bootstrap", loading: false, error: null, setSelectedCompanyId: vi.fn(), reloadCompanies: vi.fn(), createCompany: vi.fn(), }), })); vi.mock("../adapters", () => ({ getUIAdapter: (type: string) => ({ type, label: type === "hermes_gateway" ? "Hermes Gateway" : "Codex", // The stand-in also records the two gates the form resolves for every // adapter, so a test can assert the plumbing without rendering a real // adapter's fields. ConfigFields: ({ adapterType, hideInstructionsFile, managedSandboxOnly }: { adapterType: string; hideInstructionsFile?: boolean; managedSandboxOnly?: boolean; }) => adapterType === "hermes_gateway" ?