import { describe, expect, it, vi, beforeEach } from "vitest"; import { screen, waitFor } from "@testing-library/react"; import { renderWithProviders } from "@/test/utils"; import userEvent from "@testing-library/user-event"; const listProviders = vi.fn(); const createProvider = vi.fn(); const deleteProvider = vi.fn(); const applyProvider = vi.fn(); const restore = vi.fn(); const getStatus = vi.fn(); const getSettings = vi.fn(); const listLogs = vi.fn(); const listBackups = vi.fn(); const updateProvider = vi.fn(); const updateSettings = vi.fn(); vi.mock("@/lib/api", () => ({ api: { listProviders: () => listProviders(), createProvider: (input: unknown) => createProvider(input), updateProvider: (id: string, input: unknown) => updateProvider(id, input), deleteProvider: (id: string) => deleteProvider(id), applyProvider: (id: string) => applyProvider(id), restore: () => restore(), getStatus: () => getStatus(), getSettings: () => getSettings(), updateSettings: (patch: unknown) => updateSettings(patch), listLogs: () => listLogs(), listBackups: () => listBackups(), }, })); import Providers from "./Providers"; const provider = { id: "p_1", name: "DeepSeek", preset: "deepseek", base_url: "https://api.deepseek.com/v1", api_key: "sk-x", models: { default: "deepseek-chat", sonnet: "deepseek-chat", haiku: "deepseek-chat", opus: "deepseek-chat" }, enabled_for_claude: false, created_at: "2026-10-18T00:00:00Z", }; function renderPage() { return renderWithProviders(); } beforeEach(() => { vi.clearAllMocks(); listProviders.mockResolvedValue({ items: [provider] }); createProvider.mockResolvedValue({ ...provider, id: "p_2" }); deleteProvider.mockResolvedValue({ deleted: "p_1" }); applyProvider.mockResolvedValue({ provider, env: { ANTHROPIC_BASE_URL: "http://127.0.0.1:1234" } }); }); describe("Providers page", () => { it("renders the provider list", async () => { renderPage(); expect(await screen.findByText("DeepSeek")).toBeInTheDocument(); expect(screen.getByText("https://api.deepseek.com/v1")).toBeInTheDocument(); }); it("validates the create form before submitting", async () => { const user = userEvent.setup(); renderPage(); await user.click(await screen.findByRole("button", { name: /新增供应商|Add provider/ })); await user.click(screen.getByRole("button", { name: /保存|Save/ })); expect(await screen.findByText(/请填写名称|Name is required/)).toBeInTheDocument(); expect(await screen.findByText(/请填写 http|http\(s\) base URL is required/)).toBeInTheDocument(); expect(createProvider).not.toHaveBeenCalled(); }); it("creates a provider with the preset defaults", async () => { const user = userEvent.setup(); renderPage(); await user.click(await screen.findByRole("button", { name: /新增供应商|Add provider/ })); await user.type(screen.getByLabelText(/名称|Name/), "Kimi"); await user.type(screen.getByLabelText(/Base URL/), "https://api.moonshot.cn/v1"); await user.type(screen.getByLabelText(/API Key/), "sk-kimi"); await user.click(screen.getByRole("button", { name: /保存|Save/ })); await waitFor(() => expect(createProvider).toHaveBeenCalledTimes(1)); const input = createProvider.mock.calls[0][0]; expect(input).toMatchObject({ name: "Kimi", base_url: "https://api.moonshot.cn/v1", api_key: "sk-kimi", }); }); it("activates a provider and shows the applied env", async () => { const user = userEvent.setup(); renderPage(); await user.click(await screen.findByRole("button", { name: /激活并写入|Activate & apply/ })); await waitFor(() => expect(applyProvider).toHaveBeenCalledWith("p_1")); expect(await screen.findByText(/ANTHROPIC_BASE_URL/)).toBeInTheDocument(); }); });