Server responses now require execution_scope, but the strict frontend schema rejected it and prevented investigation and appointment loading. Declare it in the shared response schema and align task fixtures; regression coverage exercises summaries, details and both task categories.
78 lines
5.1 KiB
TypeScript
78 lines
5.1 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import type { OperationalTask, OperationalTaskSummary } from "../../src/features/workbench/api/operational-task-client";
|
|
import { mockAgentApi } from "./support/mock-agent-api";
|
|
import { mockWorkbenchContext } from "./support/mock-workbench-context";
|
|
|
|
test("调查和预约任务接收 Server 返回的执行范围与空回放上下文并展示详情", async ({ page }, testInfo) => {
|
|
await page.emulateMedia({ reducedMotion: "reduce" });
|
|
const now = new Date().toISOString();
|
|
const id = "72000000-0000-4000-8000-000000000001";
|
|
const appointmentId = "72000000-0000-4000-8000-000000000002";
|
|
const summary: OperationalTaskSummary = {
|
|
execution_scope: "production", project_id: "324ff7ee-c2d4-5184-a84b-48fb14a2933e", task_id: id,
|
|
task_type: "event_investigation", workflow: "burst_report",
|
|
lifecycle_status: "waiting_human", active_run: null, status: "waiting_human",
|
|
priority: "urgent", revision: 1, execution_generation: 1, execution_request_id: id,
|
|
title: "凤阳爆管调查加载核验", summary: "核对调查任务详情",
|
|
source: { kind: "external_system", external_id: id, external_revision: 1,
|
|
event_kind: "burst_report", replay_context: null },
|
|
trigger: { kind: "event", occurred_at: now, detail: "核对调查任务详情" },
|
|
scheduled_for: null, agent_session_id: null, agent_lease_expires_at: null,
|
|
current_plan_revision: null, current_report_revision: null, created_at: now, updated_at: now
|
|
};
|
|
const appointment: OperationalTaskSummary = {
|
|
...summary, task_id: appointmentId, task_type: "external_work_order", workflow: "external-work-order",
|
|
lifecycle_status: "open", status: "running", priority: "normal", execution_request_id: appointmentId,
|
|
title: "凤阳预约维修加载核验", summary: "核对预约任务详情", scheduled_for: now,
|
|
source: { ...summary.source, external_id: `peripheral_sample:${appointmentId}`, event_kind: "general" },
|
|
trigger: { kind: "external_sync", occurred_at: now, detail: "核对预约任务详情" }
|
|
};
|
|
const summaries = [summary, appointment];
|
|
const tasks: OperationalTask[] = summaries.map((item) => ({
|
|
...item, latest_plan: null, latest_report: null, evidence: [], actions: [],
|
|
permissions: { can_publish_artifacts: false, can_propose_actions: false,
|
|
can_sync_external_feedback: false, can_decide_work_orders: false,
|
|
can_execute_work_orders: false, can_decide_commands: false, can_execute_commands: false },
|
|
work_order_snapshot: item.task_type === "external_work_order" ? {
|
|
work_order_id: appointmentId, revision: 1, title: item.title, summary: item.summary,
|
|
status: "open", priority: "normal", assignee: "凤阳维修组", scheduled_at: now,
|
|
work_order_type: "general", location: "凤阳核验点", scenario_code: null,
|
|
origin: "system_data", updated_at: now
|
|
} : null
|
|
}));
|
|
const runtime = {
|
|
availability: "not_configured", source: "none", scenario_availability: "not_configured",
|
|
artifact_availability: "not_configured", schedule_availability: "not_configured",
|
|
work_order_availability: "not_configured", alert_availability: "not_configured",
|
|
generated_at: now, conditions: [], alerts: [], scenarios: [], latest_analysis: null, work_orders: []
|
|
};
|
|
await mockWorkbenchContext(page, runtime);
|
|
await mockAgentApi(page);
|
|
await page.route("https://tjwater-api.invalid/api/v1/workbench/sync-snapshot", (route) => route.fulfill({ json: {
|
|
schema: "workbench-sync-snapshot@1", event_cursor: 0, runtime,
|
|
tasks: summaries, notifications: [], generated_at: now
|
|
} }));
|
|
await page.route("https://tjwater-api.invalid/api/v1/operational-tasks/*", (route) => {
|
|
const taskId = new URL(route.request().url()).pathname.split("/").at(-1);
|
|
const task = tasks.find((item) => item.task_id === taskId);
|
|
return route.fulfill({ status: task ? 200 : 404, json: task ?? {} });
|
|
});
|
|
|
|
await page.goto("/");
|
|
await page.getByRole("button", { name: "工况任务", exact: true }).click();
|
|
const panel = page.getByRole("region", { name: "工况任务", exact: true });
|
|
await panel.getByRole("button", { name: "展开工况任务" }).click();
|
|
await panel.getByRole("button", { name: /调查任务/ }).click();
|
|
await panel.getByText(summary.title, { exact: true }).first().click();
|
|
await expect(panel.getByTestId("scheduled-condition-detail-scroll")).toContainText(summary.summary);
|
|
await testInfo.attach("investigation-loaded", { body: await panel.screenshot({ path: testInfo.outputPath("investigation-loaded.png") }), contentType: "image/png" });
|
|
|
|
await panel.getByRole("button", { name: /预约任务/ }).click();
|
|
await panel.getByText(appointment.title, { exact: true }).first().click();
|
|
const detail = panel.getByTestId("scheduled-condition-detail-scroll");
|
|
await expect(detail).toContainText("核对预约任务详情");
|
|
await expect(detail).toContainText("凤阳维修组");
|
|
await expect(detail).toContainText("凤阳核验点");
|
|
await testInfo.attach("appointment-loaded", { body: await panel.screenshot({ path: testInfo.outputPath("appointment-loaded.png") }), contentType: "image/png" });
|
|
});
|