/** * E2E 测试 — UIUX 新增路由导航与页面渲染验证。 * * 覆盖 2-task-uiux.md 中 P0/P2 任务的以下新路由: * - /today(今日行动中心) * - /compare(多企业对比) * - /threads(决策线程列表) * - /threads/[id](决策线程详情) * - /workspace(通用工作区) * - /ooda(OODA 决策循环) * - /ai-plus(AI+ 专项看板) * - /profiles(多主体画像) * * 前置条件:后端 http://localhost:8000 + 前端 http://localhost:3000 已启动。 */ import { test, expect, type Page } from "@playwright/test"; const API_BASE = "http://localhost:8000/api/v1"; const TEST_EMAIL = `e2e_nav_${Date.now()}@example.com`; const TEST_PASSWORD = "password123"; /** 登录并跳转到指定路径。 */ async function loginAndGoto(page: Page, path: string) { // 注册 await fetch(`${API_BASE}/auth/register`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email: TEST_EMAIL, password: TEST_PASSWORD, name: "E2E导航用户", tenant_name: "E2E导航机构", role: "investor", }), }); // 登录 await page.goto("/login"); await page.fill('input[id="email"]', TEST_EMAIL); await page.fill('input[id="password"]', TEST_PASSWORD); await page.click('button[type="submit"]'); await expect(page).toHaveURL(/\/dashboard|\/today/); // 导航到目标页面 await page.goto(path); } test.describe("UIUX 新增路由导航", () => { test("今日行动中心 /today 应显示页面标题和行动项", async ({ page }: { page: Page }) => { await loginAndGoto(page, "/today"); await expect(page).toHaveURL(/\/today/); await expect(page.locator("h1")).toContainText("今日行动中心"); // 应显示 AI 早报区域 await expect(page.locator("text=AI 早报").or(page.locator("text=早报"))).toBeVisible(); }); test("多企业对比 /compare 应显示对比表格", async ({ page }: { page: Page }) => { await loginAndGoto(page, "/compare"); await expect(page).toHaveURL(/\/compare/); await expect(page.locator("h1")).toContainText("多企业对比"); // 应显示默认企业列 await expect(page.locator("text=智链科技").first()).toBeVisible(); await expect(page.locator("text=云栈数据").first()).toBeVisible(); }); test("决策线程列表 /threads 应显示线程卡片", async ({ page }: { page: Page }) => { await loginAndGoto(page, "/threads"); await expect(page).toHaveURL(/\/threads/); await expect(page.locator("h1")).toContainText("决策线程"); // 应显示线程卡片或说明文字 await expect(page.locator("text=决策线程将风险")).toBeVisible(); }); test("决策线程详情 /threads/thread-001 应显示时间线", async ({ page }: { page: Page }) => { await loginAndGoto(page, "/threads/thread-001"); await expect(page).toHaveURL(/\/threads\/thread-001/); // 应显示状态机时间线节点 await expect(page.locator("text=已识别").or(page.locator("text=identified"))).toBeVisible(); }); test("通用工作区 /workspace 应显示页面标题", async ({ page }: { page: Page }) => { await loginAndGoto(page, "/workspace"); await expect(page).toHaveURL(/\/workspace/); await expect(page.locator("h1")).toContainText("工作区"); }); test("OODA 决策循环 /ooda 应显示四阶段", async ({ page }: { page: Page }) => { await loginAndGoto(page, "/ooda"); await expect(page).toHaveURL(/\/ooda/); await expect(page.locator("h1")).toContainText("OODA"); // 应显示 OODA 四阶段 await expect(page.locator("text=Observe").first()).toBeVisible(); await expect(page.locator("text=Orient").first()).toBeVisible(); await expect(page.locator("text=Decide").first()).toBeVisible(); await expect(page.locator("text=Act").first()).toBeVisible(); }); test("AI+ 专项看板 /ai-plus 应显示三个看板", async ({ page }: { page: Page }) => { await loginAndGoto(page, "/ai-plus"); await expect(page).toHaveURL(/\/ai-plus/); await expect(page.locator("h1")).toContainText("AI+"); await expect(page.locator("text=AI 商业化")).toBeVisible(); await expect(page.locator("text=模型成本")).toBeVisible(); await expect(page.locator("text=数据合规")).toBeVisible(); }); test("多主体画像 /profiles 应显示角色视角", async ({ page }: { page: Page }) => { await loginAndGoto(page, "/profiles"); await expect(page).toHaveURL(/\/profiles/); await expect(page.locator("h1")).toBeVisible(); }); });