import { expect, test } from "@playwright/test"; const realRunId = process.env.REAL_RUN_ID; test("真实 Run 的最终脚本保留原版完整表达", async ({ page }, testInfo) => { test.skip(!realRunId || !testInfo.project.name.includes("desktop"), "仅在显式指定只读真实 Run 时验收"); await page.goto("/"); await page.locator("#build-id").fill(realRunId!); await page.locator("#build-id").press("Enter"); await expect(page.locator("#build-id")).toHaveValue(realRunId!); await expect(page.getByRole("article", { name: "最终结果" })).toBeVisible(); const trigger = page.getByRole("button", { name: "查看完整主脚本" }); await expect(trigger).toBeVisible(); await trigger.evaluate((element: HTMLElement) => element.click()); const dialog = page.getByRole("dialog"); await expect(dialog).toBeVisible(); await expect(dialog.getByRole("columnheader", { name: "创作目录大纲(段本身)" })).toBeVisible(); await expect(dialog.getByRole("columnheader", { name: "完整描述" })).toBeVisible(); await expect(dialog.getByText(/图\d+(?:-\d+)?/).first()).toBeVisible(); await expect(dialog.getByText("标题", { exact: true }).first()).toBeVisible(); await expect(dialog.getByText(/正文:/).first()).toBeVisible(); await expect(dialog.getByText(/^\[元素:\d+\]$/)).toHaveCount(0); await expect(dialog.locator(".elem-hl-extended").first()).toBeVisible(); await dialog.screenshot({ path: testInfo.outputPath(`run-${realRunId}-script-table.png`) }); }); test("真实 Run 的实现方案能展开取数树", async ({ page }, testInfo) => { test.skip(!realRunId || !testInfo.project.name.includes("desktop"), "仅在显式指定只读真实 Run 时验收"); await page.goto("/"); await page.locator("#build-id").fill(realRunId!); await page.locator("#build-id").press("Enter"); await expect(page.locator("#build-id")).toHaveValue(realRunId!); const expandRound = page.getByRole("button", { name: /展开本轮/ }).first(); if (await expandRound.count()) await expandRound.click(); const expandBranch = page.getByRole("button", { name: /展开方案过程/ }).first(); await expect(expandBranch).toBeVisible(); await expandBranch.click(); const canvas = page.locator(".flowShell"); await expect(canvas.locator(".retrievalStageFrame").first()).toBeAttached(); await expect(canvas.locator(".retrievalCard").first()).toBeAttached(); await expect(canvas.locator(".retrievalAgentCard").first()).toBeAttached(); await expect(canvas.getByText("数据取舍", { exact: true }).first()).toBeAttached(); await page.screenshot({ path: testInfo.outputPath(`run-${realRunId}-retrieval-tree.png`), fullPage: true }); }); test("真实 Run 的多方案评审与主 Agent 决策分层展示", async ({ page }, testInfo) => { test.skip(!realRunId || !testInfo.project.name.includes("desktop"), "仅在显式指定只读真实 Run 时验收"); await page.goto("/"); await page.locator("#build-id").fill(realRunId!); await page.locator("#build-id").press("Enter"); await expect(page.locator("#build-id")).toHaveValue(realRunId!); const expandRound = page.getByRole("button", { name: /展开本轮/ }).first(); if (await expandRound.count()) await expandRound.click(); const canvas = page.locator(".flowShell"); const review = canvas.locator('[data-id^="multipath-review:"]').first(); const decision = canvas.locator('[data-id^="multipath-decision:"]').first(); await expect(review).toBeAttached(); await expect(decision).toBeAttached(); await expect(review.getByText("多方案评审 Agent", { exact: true })).toBeAttached(); await expect(review.getByText("评审建议", { exact: true }).first()).toBeAttached(); await expect(decision.getByText("主 Agent 多路决策", { exact: true })).toBeAttached(); await expect(decision.getByText("最终决定", { exact: true }).first()).toBeAttached(); await expect(canvas.getByText("主脚本整体评审", { exact: true }).first()).toBeAttached(); await expect(canvas.getByText("独立评审", { exact: true })).toHaveCount(0); await review.getByRole("button", { name: "查看决策" }).evaluate((element: HTMLElement) => element.click()); const inspector = page.getByRole("dialog", { name: /三列来源详情$/ }); await expect(inspector).toBeVisible(); await expect(inspector.getByText("评审对象", { exact: true })).toBeVisible(); await expect(inspector.getByText("逐项结论", { exact: true })).toBeVisible(); await expect(inspector.getByText("script_build_event")).toHaveCount(0); }); test("真实 Run 的收敛卡在缩放后仍保持在所属区域内", async ({ page }, testInfo) => { test.skip(!realRunId || !testInfo.project.name.includes("desktop"), "仅在显式指定只读真实 Run 时验收"); await page.goto("/"); await page.locator("#build-id").fill(realRunId!); await page.locator("#build-id").press("Enter"); await expect(page.locator("#build-id")).toHaveValue(realRunId!); const expandButtons = page.getByRole("button", { name: /展开本轮/ }); if (await expandButtons.count()) await expandButtons.last().click(); const frame = page.locator(".react-flow__node-roundFrame").last(); await expect(frame).toBeAttached(); const frameId = await frame.getAttribute("data-id"); const roundIndex = frameId?.match(/frame:round:(\d+)/)?.[1]; expect(roundIndex).toBeTruthy(); const assertContained = async (cardSelector: string, regionSuffix: string) => { const region = page.locator(`[data-id="region:round:${roundIndex}:${regionSuffix}"]`); const cards = page.locator(cardSelector); await expect(region).toBeAttached(); await expect(cards.first()).toBeAttached(); const regionBox = await region.boundingBox(); expect(regionBox).not.toBeNull(); for (let index = 0; index < await cards.count(); index += 1) { const box = await cards.nth(index).boundingBox(); expect(box).not.toBeNull(); expect(box!.y, `${cardSelector} 不应越过区域顶部`).toBeGreaterThanOrEqual(regionBox!.y - 1); expect(box!.y + box!.height, `${cardSelector} 不应越过区域底部`).toBeLessThanOrEqual(regionBox!.y + regionBox!.height + 1); } }; const assertConvergence = async () => { await assertContained('[data-id^="multipath-review:"]', "multipath-review"); await assertContained('[data-id^="multipath-decision:"]', "convergence"); }; await assertConvergence(); await page.locator(".react-flow__controls-zoomout").click(); await page.locator(".react-flow__controls-zoomout").click(); await expect(page.locator(".flowShell")).toHaveAttribute("data-detail-level", "compact"); await assertConvergence(); await page.locator(".react-flow__controls-zoomout").click(); await page.locator(".react-flow__controls-zoomout").click(); await page.locator(".react-flow__controls-zoomout").click(); await expect(page.locator(".flowShell")).toHaveAttribute("data-detail-level", "overview"); await assertConvergence(); await expect(page.locator(".react-flow__node-agentRegion").last()).toBeAttached(); }); test("真实 Run 的最终结果使用结论、摘要和指标分层", async ({ page }, testInfo) => { test.skip(!realRunId || !testInfo.project.name.includes("desktop"), "仅在显式指定只读真实 Run 时验收"); await page.goto("/"); await page.locator("#build-id").fill(realRunId!); await page.locator("#build-id").press("Enter"); const card = page.getByRole("article", { name: "最终结果" }); await expect(card.locator(".finalOutcome")).toBeAttached(); await expect(card.getByText("构建摘要", { exact: true })).toBeAttached(); await expect(card.locator(".artifactStats")).toBeAttached(); const box = await card.boundingBox(); expect(box).not.toBeNull(); expect(box!.height).toBeLessThan(560); await page.mouse.move(720, 480); for (let attempt = 0; attempt < 12; attempt += 1) { const current = await card.boundingBox(); if (current && current.x >= 0 && current.x + current.width <= 1280) break; await page.mouse.wheel(1200, 0); await page.waitForTimeout(40); } await expect(card).toBeInViewport(); await card.screenshot({ path: testInfo.outputPath(`run-${realRunId}-final-result.png`) }); });