import { test, expect } from "@playwright/test"; const ADMIN_USER = process.env.ADMIN_TEST_USERNAME || "admin"; const ADMIN_PASS = process.env.ADMIN_TEST_PASSWORD || "admin123"; async function checkBackendAvailable(): Promise { try { const ctrl = new AbortController(); const id = setTimeout(() => ctrl.abort(), 2000); const res = await fetch("http://localhost:3001/api/health", { signal: ctrl.signal }); clearTimeout(id); return res.ok; } catch { return false; } } async function uiLogin(page: Parameters[0]): Promise { try { await page.goto("/login"); await page.fill("input#username", ADMIN_USER); await page.fill("input#password", ADMIN_PASS); await page.click('button[type="submit"]'); await page.waitForURL((url) => !url.toString().includes("/login"), { timeout: 8000 }); return true; } catch { return false; } } test.describe("AI Provider/Model/Version CRUD API (需要 Rust 后端)", () => { test("GET /api/admin/ai/providers 返回提供商列表(需要 Rust 后端)", async ({ page }) => { if (!await checkBackendAvailable()) { test.skip(); } if (!await uiLogin(page)) { test.skip(); } const res = await page.request.get("/api/admin/ai/providers"); expect([200, 500]).toContain(res.status()); if (res.status() === 200) { const data = await res.json(); expect(Array.isArray(data.providers)).toBe(true); } }); test("POST /api/admin/ai/providers 创建提供商(需要 Rust 后端)", async ({ page }) => { if (!await checkBackendAvailable()) { test.skip(); } if (!await uiLogin(page)) { test.skip(); } const res = await page.request.post("/api/admin/ai/providers", { data: { name: "Test Provider", api_type: "openai" }, }); expect([200, 201, 400, 401, 500]).toContain(res.status()); }); test("PATCH /api/admin/ai/providers?id= 缺少id返回400", async ({ page }) => { if (!await checkBackendAvailable()) { test.skip(); } if (!await uiLogin(page)) { test.skip(); } const res = await page.request.patch("/api/admin/ai/providers", { data: { name: "Updated" }, }); expect(res.status()).toBe(400); }); test("DELETE /api/admin/ai/providers?id= 缺少id返回400", async ({ page }) => { if (!await checkBackendAvailable()) { test.skip(); } if (!await uiLogin(page)) { test.skip(); } const res = await page.request.delete("/api/admin/ai/providers"); expect(res.status()).toBe(400); }); test("GET /api/admin/ai/models 返回模型列表(需要 Rust 后端)", async ({ page }) => { if (!await checkBackendAvailable()) { test.skip(); } if (!await uiLogin(page)) { test.skip(); } const res = await page.request.get("/api/admin/ai/models"); expect([200, 500]).toContain(res.status()); if (res.status() === 200) { const data = await res.json(); expect(Array.isArray(data.models)).toBe(true); } }); test("POST /api/admin/ai/models 创建模型(需要 Rust 后端)", async ({ page }) => { if (!await checkBackendAvailable()) { test.skip(); } if (!await uiLogin(page)) { test.skip(); } const res = await page.request.post("/api/admin/ai/models", { data: { model_id: "test-model", provider: "openai" }, }); expect([200, 201, 400, 401, 500]).toContain(res.status()); }); test("PATCH /api/admin/ai/models?id= 缺少id返回400", async ({ page }) => { if (!await checkBackendAvailable()) { test.skip(); } if (!await uiLogin(page)) { test.skip(); } const res = await page.request.patch("/api/admin/ai/models", { data: { context_length: 8192 }, }); expect(res.status()).toBe(400); }); test("DELETE /api/admin/ai/models?id= 缺少id返回400", async ({ page }) => { if (!await checkBackendAvailable()) { test.skip(); } if (!await uiLogin(page)) { test.skip(); } const res = await page.request.delete("/api/admin/ai/models"); expect(res.status()).toBe(400); }); test("GET /api/admin/ai/versions 返回版本列表(需要 Rust 后端)", async ({ page }) => { if (!await checkBackendAvailable()) { test.skip(); } if (!await uiLogin(page)) { test.skip(); } const res = await page.request.get("/api/admin/ai/versions"); expect([200, 500]).toContain(res.status()); if (res.status() === 200) { const data = await res.json(); expect(Array.isArray(data.versions)).toBe(true); } }); test("POST /api/admin/ai/versions 创建版本(需要 Rust 后端)", async ({ page }) => { if (!await checkBackendAvailable()) { test.skip(); } if (!await uiLogin(page)) { test.skip(); } const res = await page.request.post("/api/admin/ai/versions", { data: { version: "1.0.0", model_id: "test" }, }); expect([200, 201, 400, 401, 500]).toContain(res.status()); }); test("PATCH /api/admin/ai/versions?id= 缺少id返回400", async ({ page }) => { if (!await checkBackendAvailable()) { test.skip(); } if (!await uiLogin(page)) { test.skip(); } const res = await page.request.patch("/api/admin/ai/versions", { data: { is_default: true }, }); expect(res.status()).toBe(400); }); test("DELETE /api/admin/ai/versions?id= 缺少id返回400", async ({ page }) => { if (!await checkBackendAvailable()) { test.skip(); } if (!await uiLogin(page)) { test.skip(); } const res = await page.request.delete("/api/admin/ai/versions"); expect(res.status()).toBe(400); }); test("PATCH /api/admin/ai/pricing/[id] 缺少配置返回500", async ({ page }) => { if (!await checkBackendAvailable()) { test.skip(); } if (!await uiLogin(page)) { test.skip(); } const res = await page.request.patch("/api/admin/ai/pricing/test-id", { data: { input_price: 0.001 }, }); expect([400, 401, 500]).toContain(res.status()); }); });