const { expect, test } = require("@playwright/test"); async function authenticate(page) { await page.goto("/"); await page.getByLabel("账号名").fill("stage4admin"); await page.getByLabel("密码").fill("Stage4-pass-123!"); await page.getByRole("button", { name: "登录", exact: true }).click(); await expect(page.locator(".sidebar, .field-error")).toBeVisible(); if (!(await page.locator(".sidebar").isVisible())) { await page.getByRole("tab", { name: "注册" }).click(); await page.getByRole("button", { name: "注册并登录" }).click(); } } test("administrator can audit jobs, backfill and govern market events", async ({ page }) => { const calls = []; const job = { id: 7, kind: "market.refresh", run_key: "2026-07-30:final:1", requested_date: "2026-07-30", trigger: "after-close", status: "failed", attempt: 1, started_at: "2026-07-30T15:10:00+08:00", finished_at: "2026-07-30T15:10:02+08:00", duration_ms: 2000, coverage: null, source_set: [], output_version: "", payload: {}, error_code: "ProviderError", error_message: "上游暂不可用,保留最后成功快照", }; await page.route("**/api/admin/system/credentials", (route) => route.fulfill({ contentType: "application/json", body: JSON.stringify([ { name: "tushare_token", configured: true, updated_at: "2026-07-30T09:00:00+08:00" }, { name: "ifind_refresh_token", configured: true, updated_at: "2026-07-30T09:00:00+08:00" }, { name: "ifind_access_token", configured: true, updated_at: "2026-07-30T09:00:00+08:00" }, ]), })); await page.route("**/api/admin/operations/jobs", (route) => route.fulfill({ contentType: "application/json", body: JSON.stringify([job]), })); await page.route("**/api/admin/operations/backfill", async (route) => { calls.push({ kind: "backfill", payload: route.request().postDataJSON() }); await route.fulfill({ contentType: "application/json", body: JSON.stringify({ completed: 2 }) }); }); await page.route("**/api/admin/operations/events/supplement?*", async (route) => { calls.push({ kind: "supplement" }); await route.fulfill({ contentType: "application/json", body: JSON.stringify({ matched: 3 }) }); }); await page.route("**/api/admin/operations/events/*/*/history", (route) => route.fulfill({ contentType: "application/json", body: JSON.stringify([{ id: 2, created_at: "2026-07-30T15:20:00+08:00", source: "admin", event_type: "limit_up", reason: "人工核验原因", created_by_name: "stage4admin", }]), })); await page.route("**/api/admin/operations/events/*/*", async (route) => { calls.push({ kind: "revision", payload: route.request().postDataJSON() }); await route.fulfill({ contentType: "application/json", body: JSON.stringify({ id: 2 }) }); }); await authenticate(page); await page.getByRole("button", { name: "系统管理" }).click(); await expect(page.getByRole("heading", { name: "后台任务状态" })).toBeVisible(); await expect(page.getByText("上游暂不可用,保留最后成功快照")).toBeVisible(); const backfill = page.locator(".operation-form"); await backfill.getByLabel("开始日期").fill("2026-07-29"); await backfill.getByLabel("结束日期").fill("2026-07-30"); await backfill.getByRole("button", { name: "开始回补" }).click(); await expect(page.getByRole("status")).toContainText("历史数据回补已完成"); const event = page.locator(".event-form"); await event.getByLabel("数据日期").fill("2026-07-30"); await event.getByLabel("股票代码").fill("000001.SZ"); await event.getByLabel("原因").fill("人工核验原因"); await event.getByRole("button", { name: "保存修订" }).click(); await expect(page.getByText("人工核验原因", { exact: true })).toBeVisible(); await event.getByRole("button", { name: "自动补充" }).click(); await expect(page.getByRole("status")).toContainText("事件原因补充完成"); expect(calls).toEqual([ { kind: "backfill", payload: { start_date: "2026-07-29", end_date: "2026-07-30" } }, { kind: "revision", payload: { event_type: "limit_up", reason: "人工核验原因", first_time: "", last_time: "", open_times: null, }, }, { kind: "supplement" }, ]); }); test("administrator tests a selected model without exposing its key", async ({ page }) => { await page.route("**/api/admin/models", (route) => route.fulfill({ contentType: "application/json", body: JSON.stringify([{ id: 1, display_name: "主模型", base_url: "https://model.example.com/v1", model_identifier: "reasoning-model", has_api_key: true, is_primary: true, is_fallback: false, updated_at: "2026-07-30T10:00:00+08:00", }]), })); await page.route("**/api/admin/models/1/test", (route) => route.fulfill({ contentType: "application/json", body: JSON.stringify({ connected: true, message: "连接成功", duration_ms: 286, request_id: "audit-request", }), })); await authenticate(page); await page.getByRole("button", { name: "系统管理" }).click(); await page.getByRole("button", { name: "模型池" }).click(); await page.getByRole("button", { name: "主模型 reasoning-model 主模型" }).click(); await page.getByRole("button", { name: "测试连接" }).click(); await expect(page.getByText("连接成功 · 286 ms", { exact: true })).toBeVisible(); await expect(page.locator("body")).not.toContainText(/secret|api[_ -]?key/i); });