import { renderToStaticMarkup } from "react-dom/server"; import { describe, expect, it } from "vitest"; import { AiProvidersPage } from "./AiProvidersPage"; import aiProvidersPageSource from "./AiProvidersPage.tsx?raw"; import type { AiProviderResponse } from "../api/types"; const provider: AiProviderResponse = { id: "ai.openai", name: "OpenAI Relay", kind: "openai-compatible", baseUrlConfigured: true, apiKeyConfigured: true, models: ["gpt-4.1", "gpt-4.1-mini"], defaultModel: "gpt-4.1-mini", relayMode: "relay", timeoutMs: 30000, status: "active", redactionPolicy: "default" }; describe("AiProvidersPage", () => { it("renders the loading state before API data arrives", () => { const html = renderToStaticMarkup(); expect(html).toContain("AI 提供商管理"); expect(html).toContain("正在加载 AI 提供商"); }); it("renders an empty API state when the platform returns no providers", () => { const html = renderToStaticMarkup(); expect(html).toContain("暂无 AI 提供商"); expect(html).toContain("page-summary-chip"); expect(html).not.toContain("metric-card"); expect(html).toContain("平台还没有返回任何提供商"); expect(html).toContain("新增提供商"); expect(html).not.toContain('value="secret://providers/"'); expect(html).not.toContain("OpenAI Relay"); }); it("renders provider API failure with scoped retry instead of a browser reload", () => { const html = renderToStaticMarkup(); expect(html).toContain("AI 提供商加载失败"); expect(html).toContain("backend unavailable"); expect(html).toContain("重试"); expect(aiProvidersPageSource).toContain("refreshProviders"); expect(aiProvidersPageSource).not.toContain("window.location.reload"); }); it("renders local-development fixtures with an explicit status label", () => { const html = renderToStaticMarkup(); expect(html).toContain("OpenAI Relay"); expect(html).toContain("本地开发"); expect(html).toContain("已配置"); expect(html).not.toContain("secret://providers/openai"); expect(html).toContain("测试"); expect(html).toContain("模型"); expect(html).toContain("编辑"); expect(html).toContain("更多"); }); it("renders guided provider setup for an existing provider", () => { const html = renderToStaticMarkup(); expect(html).toContain("配置流程"); expect(html).toContain("提供商预设"); expect(html).toContain("系统 ID"); expect(html).toContain("自动生成,不需要手填"); expect(html).toContain("高级设置:Base URL、模型、模式、超时"); expect(html).toContain("保存前检查"); expect(html).toContain("测试已保存配置"); expect(html).toContain("发现模型并填入"); expect(html).toContain("secret://providers/..."); expect(html).not.toContain('name="id"'); expect(html).not.toContain("api.example.test"); expect(html).not.toContain("relay.example.test"); }); it("does not render raw key field names", () => { const html = renderToStaticMarkup(); expect(html).not.toContain("apiKey="); expect(html).not.toContain("rawApiKey"); expect(html).not.toContain('value="sk-'); expect(html).not.toContain(">sk-"); expect(html).not.toContain("api_key="); expect(html).not.toContain("Bearer "); }); it("keeps provider state actions confirmed and provider-scoped busy", () => { expect(aiProvidersPageSource).toContain("confirmStatus"); expect(aiProvidersPageSource).toContain("busyProviderIds.has(provider.id)"); expect(aiProvidersPageSource).toContain("确认提供商状态变更"); expect(aiProvidersPageSource).toContain("只读模式"); expect(aiProvidersPageSource).toContain("operations?.begin"); expect(aiProvidersPageSource).toContain("operations?.succeed"); expect(aiProvidersPageSource).toContain("operations?.fail"); }); });