import { expect, test } from "@playwright/test"; import { investigationFixture, mockInvestigationPresentation, selectInvestigation, type SavedPresentationEvent } from "./support/mock-investigation-presentation"; const first = investigationFixture(71, "切换性能调查甲"); const second = investigationFixture(72, "切换性能调查乙"); const events: SavedPresentationEvent[] = [first, second].flatMap((task, taskIndex) => Array.from({ length: 4 }, (_, index) => ({ task_id: task.task_id, run_id: task.active_run!.run_id, execution_generation: 1, event_seq: 11 + taskIndex * 4 + index, occurred_at: "2026-11-10T00:00:00Z", command: { action: "open_chart", chart_id: `${taskIndex}-${index}`, evidence_refs: ["synthetic:reading"], chart: { title: `${taskIndex ? "乙" : "甲"}任务图表${index}`, chart_type: "line", x_data: ["07:30", "07:45", "08:00"], series: [{ name: taskIndex ? "乙任务序列" : "甲任务序列", data: [30, 29, 25] }] } }, }))); test("shows the selected report and skeleton while history waits, without rebuilding the previous task's charts", async ({ page }, testInfo) => { await mockInvestigationPresentation(page, [first, second], [...events]); await selectInvestigation(page, first.title); const panel = page.locator('[data-presentation-scope="investigation"]'); await expect(panel.getByRole("img", { name: "甲任务图表0", exact: true })).toBeVisible(); await page.evaluate(async () => { const source = await (await fetch("/src/features/agent/answer-ui/responsive-chart.tsx")).text(); const url = source.match(/from "([^"\n]*echarts-for-react[^"\n]*)"/)?.[1]; if (!url) throw new Error("Vite chart module unavailable"); const { default: Chart } = await import(url); const calls: string[] = []; Object.assign(window, { taskSwitchChartInitializations: calls }); let prototype = Chart.prototype; while (prototype && !Object.hasOwn(prototype, "initEchartsInstance")) prototype = Object.getPrototypeOf(prototype); const original = prototype.initEchartsInstance; prototype.initEchartsInstance = function (...args: unknown[]) { calls.push(this.props.option.series[0].name); return original.apply(this, args); }; }); let release!: () => void; const waiting = new Promise((resolve) => { release = resolve; }); await page.route(`**/operational-tasks/${second.task_id}/presentation-events**`, async (route) => { await waiting; await route.fallback(); }); await page.getByRole("region", { name: "工况任务", exact: true }).getByText(second.title, { exact: true }).first().click(); await expect(page.locator('article[aria-label="调查任务报告"] h2')).toHaveText(second.title); await expect(panel.getByRole("status", { name: "正在加载调查展示", exact: true })).toBeVisible(); await expect(panel.getByRole("img", { name: "甲任务图表0", exact: true })).toHaveCount(0); expect(await page.evaluate(() => (window as unknown as { taskSwitchChartInitializations: string[] }) .taskSwitchChartInitializations.filter((name) => name === "甲任务序列"))).toEqual([]); await panel.screenshot({ path: testInfo.outputPath("task-switch-loading-desktop.png") }); release(); await expect(panel.getByRole("img", { name: "乙任务图表0", exact: true })).toBeVisible(); await expect(panel.getByRole("status", { name: "正在加载调查展示", exact: true })).toHaveCount(0); await expect(page.getByRole("dialog", { name: "图表管理", exact: true })).toHaveCount(0); expect(await page.evaluate(() => (window as unknown as { taskSwitchChartInitializations: string[] }) .taskSwitchChartInitializations.filter((name) => name === "甲任务序列"))).toEqual([]); }); test("keeps loading feedback readable on a narrow viewport and discards a late task response", async ({ page }, testInfo) => { await page.setViewportSize({ width: 375, height: 800 }); await mockInvestigationPresentation(page, [first, second], [...events]); await selectInvestigation(page, first.title); let release!: () => void; const waiting = new Promise((resolve) => { release = resolve; }); await page.route(`**/operational-tasks/${second.task_id}/presentation-events**`, async (route) => { await waiting; await route.fallback(); }); // The map task selector remains available independently of the report reader. const taskPanel = page.getByRole("region", { name: "工况任务", exact: true }).filter({ visible: true }); await taskPanel.getByRole("button", { name: "收起工况任务", exact: true }).click(); await taskPanel.getByText(second.title, { exact: true }).first().click(); await expect(page.locator('article[aria-label="调查任务报告"] h2').filter({ visible: true })).toHaveText(second.title); const loading = page.getByRole("status", { name: "正在加载调查展示", exact: true }); await expect(loading).toBeVisible(); await taskPanel.getByRole("button", { name: "关闭工况任务", exact: true }).click(); await expect(loading).toBeVisible(); await page.screenshot({ path: testInfo.outputPath("task-switch-loading-mobile.png") }); expect(await page.evaluate(() => document.documentElement.scrollWidth)).toBeLessThanOrEqual(375); await selectInvestigation(page, first.title); release(); await expect(page.locator('article[aria-label="调查任务报告"] h2').filter({ visible: true })).toHaveText(first.title); await expect(page.getByRole("img", { name: "乙任务图表0", exact: true })).toHaveCount(0); });