79 lines
4.9 KiB
TypeScript
79 lines
4.9 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import { mockAgentApi } from "./support/mock-agent-api";
|
|
|
|
test("已批准的派单失败动作可重试,并在提交期间禁止重复点击", async ({ page }, testInfo) => {
|
|
await mockAgentApi(page);
|
|
await page.emulateMedia({ reducedMotion: "reduce" });
|
|
await page.goto("/", { waitUntil: "domcontentloaded" });
|
|
await page.setContent('<!doctype html><html lang="zh-CN"><head><link rel="stylesheet" href="/src/styles.css"></head><body><main id="reader" style="max-width:680px;margin:auto;padding:16px"></main></body></html>');
|
|
await page.evaluate(async () => {
|
|
const entry = await (await fetch("/src/main.tsx")).text();
|
|
const reactUrl = entry.match(/from "([^"\n]*\/react\.js[^"\n]*)"/)?.[1];
|
|
const clientUrl = entry.match(/from "([^"\n]*\/react-dom_client\.js[^"\n]*)"/)?.[1];
|
|
if (!reactUrl || !clientUrl) throw new Error("Vite React module paths unavailable");
|
|
const reactModule = await import(reactUrl);
|
|
const React = reactModule.default ?? reactModule;
|
|
const clientModule = await import(clientUrl);
|
|
const { createRoot } = clientModule.default ?? clientModule;
|
|
const { AgentExecutionPlanPanel } = await import("/src/features/workbench/components/agent-execution-plan-panel.tsx");
|
|
const now = "2026-11-07T13:36:15Z";
|
|
let task = {
|
|
task_id: "task-retry", task_type: "event_investigation", title: "SCADA 异常调查",
|
|
summary: "候选管段515870待现场核验", execution_generation: 1,
|
|
lifecycle_status: "waiting_human", status: "waiting_human", updated_at: now,
|
|
latest_report: { revision: 2, execution_generation: 1, published_at: now, report: {
|
|
title: "现场核验工单派发状态", stage: "final", outcome: "concluded",
|
|
current_conclusion: "工单已批准,执行适配器尚未配置,现场核验未派发。",
|
|
conclusion_boundary: "事件未闭环。", recommendations: [], pending_items: [],
|
|
data_gaps: [], evidence_refs: [], diagram: null
|
|
} },
|
|
latest_progress: null, latest_plan: null, active_run: null, evidence: [], access_requests: [],
|
|
permissions: { can_execute_work_orders: true },
|
|
actions: [{ action_id: "action-retry", task_id: "task-retry", version: 4,
|
|
kind: "create_work_order", reason: "候选管段515870需现场核验", proposed_at: now,
|
|
decided_at: now, executed_at: now, approval_status: "approved", execution_status: "unsupported",
|
|
execution_detail: "尚未配置该动作的外部执行适配器", evidence_refs: [], receipt: null,
|
|
payload: { title: "候选管段515870现场漏水核查", description: "核查渗漏、阀门状态并回填照片和压力复测。",
|
|
work_order_type: "general", priority: "normal" } }]
|
|
};
|
|
const calls: { actionId: string; version: number }[] = [];
|
|
let finish: () => void;
|
|
const root = createRoot(document.getElementById("reader"));
|
|
const render = () => root.render(React.createElement(AgentExecutionPlanPanel, {
|
|
task, onContinue: () => undefined, onDecision: async () => undefined,
|
|
onReconcile: async () => undefined, onRefresh: () => undefined,
|
|
onLoadEvidenceSnapshot: async () => undefined,
|
|
onExecute: async (actionId: string, version: number) => {
|
|
calls.push({ actionId, version });
|
|
await new Promise<void>((resolve) => { finish = resolve; });
|
|
task = { ...task, actions: [{ ...task.actions[0], version: 5,
|
|
execution_status: "submitted", execution_detail: "工单已提交,等待现场核验回执" }] };
|
|
render();
|
|
}
|
|
}));
|
|
Object.assign(window, { retryCalls: calls, finishRetry: () => finish() });
|
|
render();
|
|
});
|
|
const section = page.getByRole("region", { name: "当前需处理", exact: true });
|
|
await expect(section).toContainText("待重试");
|
|
await section.locator("summary").filter({ hasText: "待重试" }).click();
|
|
const retry = section.getByRole("button", { name: "重试执行", exact: true });
|
|
await expect(retry).toBeEnabled();
|
|
await retry.scrollIntoViewIfNeeded();
|
|
await page.screenshot({ path: testInfo.outputPath("retry-desktop.png") });
|
|
await page.setViewportSize({ width: 390, height: 844 });
|
|
await retry.scrollIntoViewIfNeeded();
|
|
await expect(retry).toBeInViewport();
|
|
expect(await page.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth)).toBe(true);
|
|
await page.screenshot({ path: testInfo.outputPath("retry-mobile.png") });
|
|
await retry.click();
|
|
await expect(retry).toBeDisabled();
|
|
expect(await page.evaluate(() => (window as unknown as { retryCalls: unknown[] }).retryCalls)).toEqual([
|
|
{ actionId: "action-retry", version: 4 }
|
|
]);
|
|
await page.evaluate(() => (window as unknown as { finishRetry: () => void }).finishRetry());
|
|
await expect(retry).toHaveCount(0);
|
|
await expect(section.getByRole("button", { name: "核对执行回执" })).toBeVisible();
|
|
await expect(section).toContainText("工单已提交,等待现场核验回执");
|
|
});
|