real-artifact.spec.ts 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import { expect, test } from "@playwright/test";
  2. const realRunId = process.env.REAL_RUN_ID;
  3. test("真实 Run 的最终脚本保留原版完整表达", async ({ page }, testInfo) => {
  4. test.skip(!realRunId || !testInfo.project.name.includes("desktop"), "仅在显式指定只读真实 Run 时验收");
  5. await page.goto("/");
  6. await page.locator("#build-id").fill(realRunId!);
  7. await page.locator("#build-id").press("Enter");
  8. await expect(page.locator("#build-id")).toHaveValue(realRunId!);
  9. await expect(page.getByRole("article", { name: "最终结果" })).toBeVisible();
  10. const trigger = page.getByRole("button", { name: "查看完整主脚本" });
  11. await expect(trigger).toBeVisible();
  12. await trigger.evaluate((element: HTMLElement) => element.click());
  13. const dialog = page.getByRole("dialog");
  14. await expect(dialog).toBeVisible();
  15. await expect(dialog.getByRole("columnheader", { name: "创作目录大纲(段本身)" })).toBeVisible();
  16. await expect(dialog.getByRole("columnheader", { name: "完整描述" })).toBeVisible();
  17. await expect(dialog.getByText(/图\d+(?:-\d+)?/).first()).toBeVisible();
  18. await expect(dialog.getByText("标题", { exact: true }).first()).toBeVisible();
  19. await expect(dialog.getByText(/正文:/).first()).toBeVisible();
  20. await expect(dialog.getByText(/^\[元素:\d+\]$/)).toHaveCount(0);
  21. await expect(dialog.locator(".elem-hl-extended").first()).toBeVisible();
  22. await dialog.screenshot({ path: testInfo.outputPath(`run-${realRunId}-script-table.png`) });
  23. });
  24. test("真实 Run 的实现方案能展开取数树", async ({ page }, testInfo) => {
  25. test.skip(!realRunId || !testInfo.project.name.includes("desktop"), "仅在显式指定只读真实 Run 时验收");
  26. await page.goto("/");
  27. await page.locator("#build-id").fill(realRunId!);
  28. await page.locator("#build-id").press("Enter");
  29. await expect(page.locator("#build-id")).toHaveValue(realRunId!);
  30. const expandRound = page.getByRole("button", { name: /展开本轮/ }).first();
  31. if (await expandRound.count()) await expandRound.click();
  32. const expandBranch = page.getByRole("button", { name: /展开方案过程/ }).first();
  33. await expect(expandBranch).toBeVisible();
  34. await expandBranch.click();
  35. const canvas = page.locator(".flowShell");
  36. await expect(canvas.locator(".retrievalStageFrame").first()).toBeAttached();
  37. await expect(canvas.locator(".retrievalCard").first()).toBeAttached();
  38. await expect(canvas.locator(".retrievalAgentCard").first()).toBeAttached();
  39. await expect(canvas.getByText("数据取舍", { exact: true }).first()).toBeAttached();
  40. await page.screenshot({ path: testInfo.outputPath(`run-${realRunId}-retrieval-tree.png`), fullPage: true });
  41. });
  42. test("真实 Run 的多方案评审与主 Agent 决策分层展示", async ({ page }, testInfo) => {
  43. test.skip(!realRunId || !testInfo.project.name.includes("desktop"), "仅在显式指定只读真实 Run 时验收");
  44. await page.goto("/");
  45. await page.locator("#build-id").fill(realRunId!);
  46. await page.locator("#build-id").press("Enter");
  47. await expect(page.locator("#build-id")).toHaveValue(realRunId!);
  48. const expandRound = page.getByRole("button", { name: /展开本轮/ }).first();
  49. if (await expandRound.count()) await expandRound.click();
  50. const canvas = page.locator(".flowShell");
  51. const review = canvas.locator('[data-id^="multipath-review:"]').first();
  52. const decision = canvas.locator('[data-id^="multipath-decision:"]').first();
  53. await expect(review).toBeAttached();
  54. await expect(decision).toBeAttached();
  55. await expect(review.getByText("多方案评审 Agent", { exact: true })).toBeAttached();
  56. await expect(review.getByText("评审建议", { exact: true }).first()).toBeAttached();
  57. await expect(decision.getByText("主 Agent 多路决策", { exact: true })).toBeAttached();
  58. await expect(decision.getByText("最终决定", { exact: true }).first()).toBeAttached();
  59. await expect(canvas.getByText("主脚本整体评审", { exact: true }).first()).toBeAttached();
  60. await expect(canvas.getByText("独立评审", { exact: true })).toHaveCount(0);
  61. await review.getByRole("button", { name: "查看决策" }).evaluate((element: HTMLElement) => element.click());
  62. const inspector = page.getByRole("dialog", { name: /三列来源详情$/ });
  63. await expect(inspector).toBeVisible();
  64. await expect(inspector.getByText("评审对象", { exact: true })).toBeVisible();
  65. await expect(inspector.getByText("逐项结论", { exact: true })).toBeVisible();
  66. await expect(inspector.getByText("script_build_event")).toHaveCount(0);
  67. });
  68. test("真实 Run 的收敛卡在缩放后仍保持在所属区域内", async ({ page }, testInfo) => {
  69. test.skip(!realRunId || !testInfo.project.name.includes("desktop"), "仅在显式指定只读真实 Run 时验收");
  70. await page.goto("/");
  71. await page.locator("#build-id").fill(realRunId!);
  72. await page.locator("#build-id").press("Enter");
  73. await expect(page.locator("#build-id")).toHaveValue(realRunId!);
  74. const expandButtons = page.getByRole("button", { name: /展开本轮/ });
  75. if (await expandButtons.count()) await expandButtons.last().click();
  76. const frame = page.locator(".react-flow__node-roundFrame").last();
  77. await expect(frame).toBeAttached();
  78. const frameId = await frame.getAttribute("data-id");
  79. const roundIndex = frameId?.match(/frame:round:(\d+)/)?.[1];
  80. expect(roundIndex).toBeTruthy();
  81. const assertContained = async (cardSelector: string, regionSuffix: string) => {
  82. const region = page.locator(`[data-id="region:round:${roundIndex}:${regionSuffix}"]`);
  83. const cards = page.locator(cardSelector);
  84. await expect(region).toBeAttached();
  85. await expect(cards.first()).toBeAttached();
  86. const regionBox = await region.boundingBox();
  87. expect(regionBox).not.toBeNull();
  88. for (let index = 0; index < await cards.count(); index += 1) {
  89. const box = await cards.nth(index).boundingBox();
  90. expect(box).not.toBeNull();
  91. expect(box!.y, `${cardSelector} 不应越过区域顶部`).toBeGreaterThanOrEqual(regionBox!.y - 1);
  92. expect(box!.y + box!.height, `${cardSelector} 不应越过区域底部`).toBeLessThanOrEqual(regionBox!.y + regionBox!.height + 1);
  93. }
  94. };
  95. const assertConvergence = async () => {
  96. await assertContained('[data-id^="multipath-review:"]', "multipath-review");
  97. await assertContained('[data-id^="multipath-decision:"]', "convergence");
  98. };
  99. await assertConvergence();
  100. await page.locator(".react-flow__controls-zoomout").click();
  101. await page.locator(".react-flow__controls-zoomout").click();
  102. await expect(page.locator(".flowShell")).toHaveAttribute("data-detail-level", "compact");
  103. await assertConvergence();
  104. await page.locator(".react-flow__controls-zoomout").click();
  105. await page.locator(".react-flow__controls-zoomout").click();
  106. await page.locator(".react-flow__controls-zoomout").click();
  107. await expect(page.locator(".flowShell")).toHaveAttribute("data-detail-level", "overview");
  108. await assertConvergence();
  109. await expect(page.locator(".react-flow__node-agentRegion").last()).toBeAttached();
  110. });
  111. test("真实 Run 的最终结果使用结论、摘要和指标分层", async ({ page }, testInfo) => {
  112. test.skip(!realRunId || !testInfo.project.name.includes("desktop"), "仅在显式指定只读真实 Run 时验收");
  113. await page.goto("/");
  114. await page.locator("#build-id").fill(realRunId!);
  115. await page.locator("#build-id").press("Enter");
  116. const card = page.getByRole("article", { name: "最终结果" });
  117. await expect(card.locator(".finalOutcome")).toBeAttached();
  118. await expect(card.getByText("构建摘要", { exact: true })).toBeAttached();
  119. await expect(card.locator(".artifactStats")).toBeAttached();
  120. const box = await card.boundingBox();
  121. expect(box).not.toBeNull();
  122. expect(box!.height).toBeLessThan(560);
  123. await page.mouse.move(720, 480);
  124. for (let attempt = 0; attempt < 12; attempt += 1) {
  125. const current = await card.boundingBox();
  126. if (current && current.x >= 0 && current.x + current.width <= 1280) break;
  127. await page.mouse.wheel(1200, 0);
  128. await page.waitForTimeout(40);
  129. }
  130. await expect(card).toBeInViewport();
  131. await card.screenshot({ path: testInfo.outputPath(`run-${realRunId}-final-result.png`) });
  132. });