feat(workbench): integrate runtime data and map tooling
This commit is contained in:
@@ -0,0 +1,513 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { mockWorkbenchContext } from "./support/mock-workbench-context";
|
||||
|
||||
const TODAY = shanghaiTimestamp(10, 30);
|
||||
const TODAY_10_10 = shanghaiTimestamp(10, 10);
|
||||
const TODAY_10_20 = shanghaiTimestamp(10, 20);
|
||||
const TODAY_10_25 = shanghaiTimestamp(10, 25);
|
||||
const TODAY_10_35 = shanghaiTimestamp(10, 35);
|
||||
const TODAY_11_00 = shanghaiTimestamp(11, 0);
|
||||
const YESTERDAY_10_10 = shanghaiTimestamp(10, 10, -1);
|
||||
const YESTERDAY_10_20 = shanghaiTimestamp(10, 20, -1);
|
||||
|
||||
test("history mode opens on the latest day with backend work orders", async ({ page }) => {
|
||||
await mockWorkbenchContext(page, {
|
||||
availability: "ready",
|
||||
source: "scheduled_tasks",
|
||||
scenario_availability: "not_configured",
|
||||
artifact_availability: "not_configured",
|
||||
schedule_availability: "ready",
|
||||
work_order_availability: "ready",
|
||||
alert_availability: "ready",
|
||||
generated_at: "2026-09-18T02:30:00Z",
|
||||
conditions: [{
|
||||
id: "backend-schedule-demo-day-next",
|
||||
task_id: "backend-schedule",
|
||||
session_id: "scheduled-condition-backend-schedule-demo-day",
|
||||
title: "历史 SCADA 诊断计划",
|
||||
summary: "来自后端持久化的目标明确的诊断计划。",
|
||||
status: "running",
|
||||
risk_level: "normal",
|
||||
scheduled_at: "2026-08-17T09:40:00Z",
|
||||
updated_at: "2026-08-17T09:40:00Z",
|
||||
detail: "按计划复核 SCADA 缺测与越界记录。",
|
||||
recommendation: null,
|
||||
evidence: ["调度 ID:demo-day"],
|
||||
model_name: "TJWater scheduler"
|
||||
}],
|
||||
alerts: [],
|
||||
scenarios: [],
|
||||
latest_analysis: null,
|
||||
work_orders: [{
|
||||
id: "wo-history-1",
|
||||
code: "WO-20260817-001",
|
||||
scheduled_at: "2026-08-17T09:40:00Z",
|
||||
title: "历史工单:阀门复核",
|
||||
summary: "来自后端工单投影的历史预约任务。",
|
||||
status: "pending",
|
||||
risk_level: "normal",
|
||||
updated_at: "2026-08-17T09:35:00Z",
|
||||
detail: "复核阀门状态并回传结果。",
|
||||
recommendation: null,
|
||||
duration_minutes: 30,
|
||||
source: "工单系统",
|
||||
dispatcher: "调度中心",
|
||||
priority: "normal",
|
||||
subtasks: [{
|
||||
id: "wo-history-1-subtask-1",
|
||||
title: "阀门状态复核",
|
||||
summary: "现场复核阀门状态并回传。",
|
||||
status: "running",
|
||||
scheduled_at: "2026-08-17T09:40:00Z",
|
||||
location: "北区阀门 V-17",
|
||||
assignee: "北区班组",
|
||||
duration_minutes: 30,
|
||||
reply_window_minutes: 15,
|
||||
stages: [
|
||||
{ id: "dispatch", sequence: 1, title: "派发", status: "done", owner: "调度中心", time_label: "17:20", description: "已派发。" },
|
||||
{ id: "execution", sequence: 2, title: "执行", status: "current", owner: "北区班组", time_label: "17:40-18:10", description: "现场复核中。" },
|
||||
{ id: "reply", sequence: 3, title: "复令", status: "pending", owner: "北区班组", time_label: "18:10-18:25", description: "等待结果回传。" }
|
||||
],
|
||||
reply_requirements: ["回传阀门状态"]
|
||||
}]
|
||||
}]
|
||||
}, undefined, {}, [], { runtimeMode: "history" });
|
||||
|
||||
await page.goto("/", { waitUntil: "domcontentloaded" });
|
||||
|
||||
await expect(page.getByText("历史 2026-08-17 17:40", { exact: true })).toBeVisible();
|
||||
await expect(page.getByRole("region", { name: "运行时间轴" })).toContainText("2026.08.17");
|
||||
await page.getByRole("button", { name: "工况任务", exact: true }).click();
|
||||
const panel = page.getByRole("region", { name: "工况任务", exact: true });
|
||||
await expect(panel).toContainText("工况演示数据 · 后端工单");
|
||||
await expect(panel).toContainText("SCADA 数据诊断");
|
||||
await panel.getByRole("button", { name: "展开工况任务" }).click();
|
||||
await expect(panel).toContainText("历史工单:阀门复核");
|
||||
await expect(panel).not.toContainText("历史 SCADA 诊断计划");
|
||||
});
|
||||
|
||||
test("keeps mock conditions while retaining explicit backend alerts", async ({ page }) => {
|
||||
await mockWorkbenchContext(page, {
|
||||
availability: "ready",
|
||||
source: "scheduled_tasks",
|
||||
scenario_availability: "not_configured",
|
||||
artifact_availability: "not_configured",
|
||||
schedule_availability: "not_configured",
|
||||
work_order_availability: "not_configured",
|
||||
alert_availability: "ready",
|
||||
generated_at: TODAY,
|
||||
conditions: [{
|
||||
id: "schedule-run-test-1",
|
||||
task_id: "backend-schedule",
|
||||
session_id: "scheduled-condition-schedule-run-test-1",
|
||||
title: "演示 合成低压调查",
|
||||
summary: "来自后端持久化 Action Run 的 演示 沙箱测试状态。",
|
||||
status: "error",
|
||||
risk_level: "critical",
|
||||
scheduled_at: TODAY_10_20,
|
||||
updated_at: TODAY_10_25,
|
||||
detail: "演示 测试运行状态:已失败。",
|
||||
recommendation: "请在 演示 调查任务中检查失败步骤与运行日志。",
|
||||
evidence: ["运行状态:failed"],
|
||||
model_name: "TJWater scheduler"
|
||||
}],
|
||||
alerts: [{
|
||||
id: "scheduled-condition-alert-schedule-run-test-1",
|
||||
condition_id: "schedule-run-test-1",
|
||||
source: {
|
||||
task_type: "analysis_task",
|
||||
task_id: "backend-schedule",
|
||||
run_id: "schedule-run-test-1"
|
||||
},
|
||||
title: "演示 测试待复核:演示 合成低压调查",
|
||||
description: "运行失败。演示 测试运行状态:已失败。",
|
||||
occurred_at: TODAY_10_25,
|
||||
severity: "critical"
|
||||
}],
|
||||
scenarios: [],
|
||||
latest_analysis: null,
|
||||
work_orders: []
|
||||
});
|
||||
await page.goto("/", { waitUntil: "domcontentloaded" });
|
||||
|
||||
await page.getByRole("button", { name: "工况任务", exact: true }).click();
|
||||
const panel = page.getByRole("region", { name: "工况任务", exact: true });
|
||||
await expect(panel).toContainText("工况演示数据 · 未接入工单");
|
||||
await expect(panel).toContainText("SCADA 数据诊断");
|
||||
await expect(panel).not.toContainText("演示 合成低压调查");
|
||||
|
||||
const alertButton = page.getByRole("button", {
|
||||
name: "查看异常处置面板,当前 1 条待复核工况"
|
||||
});
|
||||
await alertButton.focus();
|
||||
await page.keyboard.press("Enter");
|
||||
await expect(page.getByText("演示 测试待复核:演示 合成低压调查")).toBeVisible();
|
||||
});
|
||||
|
||||
test("opens the latest persisted analysis as the active visualization", async ({ page }) => {
|
||||
const latestAnalysis = {
|
||||
run_id: "analysis-1",
|
||||
name: "北区爆管定位",
|
||||
run_type: "burst_location",
|
||||
run_type_label: "爆管定位",
|
||||
status: "completed",
|
||||
status_label: "已完成",
|
||||
created_by: "alice",
|
||||
created_at: TODAY_10_20,
|
||||
started_at: TODAY_10_10,
|
||||
results: [{
|
||||
result_type: "burst_location",
|
||||
created_at: TODAY_10_20,
|
||||
facts: [{ label: "关联管段", value: "P-42" }]
|
||||
}],
|
||||
map_payload: {
|
||||
type: "FeatureCollection",
|
||||
features: [{
|
||||
type: "Feature",
|
||||
properties: { label: "后端爆管定位" },
|
||||
geometry: { type: "Point", coordinates: [121.5, 30.9] }
|
||||
}]
|
||||
}
|
||||
};
|
||||
const historicalAnalysis = {
|
||||
...latestAnalysis,
|
||||
run_id: "analysis-2",
|
||||
name: "南区历史定位",
|
||||
created_at: YESTERDAY_10_20,
|
||||
started_at: YESTERDAY_10_10,
|
||||
results: [{
|
||||
result_type: "burst_location",
|
||||
created_at: YESTERDAY_10_20,
|
||||
facts: [{ label: "关联管段", value: "P-older" }]
|
||||
}],
|
||||
map_payload: {
|
||||
type: "FeatureCollection",
|
||||
features: [{
|
||||
type: "Feature",
|
||||
properties: { label: "历史运行几何" },
|
||||
geometry: { type: "Point", coordinates: [121.4, 30.8] }
|
||||
}]
|
||||
}
|
||||
};
|
||||
await mockWorkbenchContext(page, {
|
||||
availability: "ready",
|
||||
source: "analysis_runs",
|
||||
scenario_availability: "ready",
|
||||
artifact_availability: "ready",
|
||||
schedule_availability: "ready",
|
||||
work_order_availability: "not_configured",
|
||||
alert_availability: "not_configured",
|
||||
generated_at: TODAY,
|
||||
conditions: [{
|
||||
id: "analysis-run-analysis-1",
|
||||
task_id: "backend-analysis",
|
||||
session_id: "scheduled-condition-analysis-run-analysis-1",
|
||||
title: "北区爆管定位",
|
||||
summary: "来自项目后端持久化分析运行:爆管定位。",
|
||||
status: "completed",
|
||||
risk_level: "normal",
|
||||
scheduled_at: TODAY_10_10,
|
||||
updated_at: TODAY_10_20,
|
||||
detail: "分析类型:爆管定位;后端状态:已完成。",
|
||||
recommendation: null,
|
||||
evidence: ["运行 ID:analysis-1"],
|
||||
model_name: "TJWater analysis runtime"
|
||||
}, {
|
||||
id: "analysis-run-analysis-2",
|
||||
task_id: "backend-analysis",
|
||||
session_id: "scheduled-condition-analysis-run-analysis-2",
|
||||
title: "南区历史定位",
|
||||
summary: "来自项目后端持久化分析运行:爆管定位。",
|
||||
status: "completed",
|
||||
risk_level: "normal",
|
||||
scheduled_at: YESTERDAY_10_10,
|
||||
updated_at: YESTERDAY_10_20,
|
||||
detail: "分析类型:爆管定位;后端状态:已完成。",
|
||||
recommendation: null,
|
||||
evidence: ["运行 ID:analysis-2"],
|
||||
model_name: "TJWater analysis runtime"
|
||||
}],
|
||||
alerts: [],
|
||||
scenarios: [
|
||||
{
|
||||
id: "analysis-run-analysis-1",
|
||||
run_id: "analysis-1",
|
||||
name: "北区爆管定位",
|
||||
description: "爆管定位 · 已完成 · 创建人 alice",
|
||||
status: "review",
|
||||
run_type: "burst_location",
|
||||
run_type_label: "爆管定位",
|
||||
run_status: "completed",
|
||||
created_at: TODAY_10_20
|
||||
},
|
||||
{
|
||||
id: "analysis-run-analysis-2",
|
||||
run_id: "analysis-2",
|
||||
name: "南区历史定位",
|
||||
description: "爆管定位 · 已完成 · 创建人 alice",
|
||||
status: "review",
|
||||
run_type: "burst_location",
|
||||
run_type_label: "爆管定位",
|
||||
run_status: "completed",
|
||||
created_at: YESTERDAY_10_20
|
||||
}
|
||||
],
|
||||
latest_analysis: latestAnalysis,
|
||||
work_orders: []
|
||||
}, undefined, {
|
||||
"analysis-1": latestAnalysis,
|
||||
"analysis-2": historicalAnalysis
|
||||
}, [{
|
||||
run_id: "analysis-1",
|
||||
name: "北区爆管定位",
|
||||
run_type: "burst_location",
|
||||
run_type_label: "爆管定位",
|
||||
status: "completed",
|
||||
status_label: "已完成",
|
||||
created_by: "alice",
|
||||
created_at: TODAY_10_20,
|
||||
started_at: TODAY_10_10,
|
||||
has_results: true
|
||||
}, {
|
||||
run_id: "analysis-2",
|
||||
name: "南区历史定位",
|
||||
run_type: "burst_location",
|
||||
run_type_label: "爆管定位",
|
||||
status: "completed",
|
||||
status_label: "已完成",
|
||||
created_by: "alice",
|
||||
created_at: YESTERDAY_10_20,
|
||||
started_at: YESTERDAY_10_10,
|
||||
has_results: true
|
||||
}, ...Array.from({ length: 9 }, (_, index) => ({
|
||||
run_id: `analysis-${index + 3}`,
|
||||
name: `批次分析 ${index + 3}`,
|
||||
run_type: "pressure_analysis",
|
||||
run_type_label: "压力分析",
|
||||
status: "completed",
|
||||
status_label: "已完成",
|
||||
created_by: "scheduler",
|
||||
created_at: YESTERDAY_10_20,
|
||||
started_at: YESTERDAY_10_10,
|
||||
has_results: index % 2 === 0
|
||||
}))]);
|
||||
await page.goto("/", { waitUntil: "domcontentloaded" });
|
||||
|
||||
await expect(page.getByRole("button", { name: "切换模拟方案" })).toHaveCount(0);
|
||||
await expect(page.getByRole("button", { name: /当前分析视图/ })).toHaveCount(0);
|
||||
|
||||
await page.getByRole("button", { name: "工况任务", exact: true }).click();
|
||||
const conditionPanel = page.getByRole("region", { name: "工况任务", exact: true });
|
||||
await expect(conditionPanel).toContainText("工况演示数据 · 未接入工单");
|
||||
await expect(conditionPanel).not.toContainText("北区爆管定位");
|
||||
await expect(conditionPanel).not.toContainText("南区历史定位");
|
||||
await expect(conditionPanel).toContainText("SCADA 数据诊断");
|
||||
await page.getByRole("button", { name: "工况任务", exact: true }).click();
|
||||
await expect(page.getByRole("region", { name: "工况任务", exact: true })).toHaveCount(0);
|
||||
|
||||
await page.getByRole("button", { name: "打开最新后端分析成果" }).click();
|
||||
await expect(page.getByRole("complementary", { name: "后端分析成果预览" })).toHaveCount(0);
|
||||
await expect(page.getByRole("heading", { name: "北区爆管定位" })).toBeVisible();
|
||||
await expect(page.getByText("Backend Analysis")).toBeVisible();
|
||||
await expect(page.getByText("关联管段:P-42")).toBeVisible();
|
||||
const analysisViewButton = page.getByRole("button", { name: "当前分析视图:北区爆管定位" });
|
||||
await expect(analysisViewButton).toContainText("分析视图 · 北区爆管定位");
|
||||
await expect.poll(() => page.evaluate(() =>
|
||||
window.__waterNetworkMap
|
||||
?.querySourceFeatures("simulation-backend-analysis")
|
||||
.map((feature) => feature.properties?.label) ?? []
|
||||
)).toContain("后端爆管定位");
|
||||
|
||||
await analysisViewButton.click();
|
||||
await expect(page.getByText(/爆管定位 · 项目后端分析运行 · 后端分析运行/)).toBeVisible();
|
||||
await page.getByText("关闭分析视图", { exact: true }).click();
|
||||
await expect(page.getByRole("button", { name: /当前分析视图/ })).toHaveCount(0);
|
||||
await expect.poll(() => page.evaluate(() =>
|
||||
window.__waterNetworkMap
|
||||
?.querySourceFeatures("simulation-backend-analysis").length ?? 0
|
||||
)).toBe(0);
|
||||
|
||||
await page.getByRole("button", { name: "项目分析成果" }).click();
|
||||
const resultsPanel = page.getByRole("complementary", { name: "项目分析成果" });
|
||||
await resultsPanel.getByText("浏览项目分析成果", { exact: true }).click();
|
||||
await expect(resultsPanel.getByRole("button", { name: "打开分析成果:北区爆管定位" })).toBeVisible();
|
||||
await expect(resultsPanel.getByRole("button", { name: "打开分析成果:批次分析 11" })).toHaveCount(0);
|
||||
await resultsPanel.getByRole("button", { name: "加载更多成果" }).click();
|
||||
await expect(resultsPanel.getByRole("button", { name: "打开分析成果:批次分析 11" })).toBeVisible();
|
||||
await resultsPanel.getByRole("button", { name: "打开分析成果:南区历史定位" }).click();
|
||||
await expect(resultsPanel).toHaveCount(0);
|
||||
await expect(page.getByRole("heading", { name: "南区历史定位" })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "当前分析视图:南区历史定位" })).toBeVisible();
|
||||
await expect.poll(() => page.evaluate(() =>
|
||||
window.__waterNetworkMap
|
||||
?.querySourceFeatures("simulation-backend-analysis")
|
||||
.map((feature) => feature.properties?.label) ?? []
|
||||
)).toContain("历史运行几何");
|
||||
});
|
||||
|
||||
test("keeps a non-spatial backend result in the analysis workspace without demo geometry", async ({ page }) => {
|
||||
await page.setViewportSize({ width: 1280, height: 900 });
|
||||
await mockWorkbenchContext(page, {
|
||||
availability: "ready",
|
||||
source: "analysis_runs",
|
||||
scenario_availability: "ready",
|
||||
artifact_availability: "ready",
|
||||
schedule_availability: "not_configured",
|
||||
work_order_availability: "not_configured",
|
||||
alert_availability: "not_configured",
|
||||
generated_at: TODAY,
|
||||
conditions: [],
|
||||
alerts: [],
|
||||
scenarios: [],
|
||||
latest_analysis: {
|
||||
run_id: "analysis-table-only",
|
||||
name: "压力统计结果",
|
||||
run_type: "pressure_analysis",
|
||||
run_type_label: "压力分析",
|
||||
status: "completed",
|
||||
status_label: "已完成",
|
||||
created_by: "alice",
|
||||
created_at: TODAY_10_20,
|
||||
started_at: TODAY_10_10,
|
||||
results: [{
|
||||
result_type: "pressure_analysis",
|
||||
created_at: TODAY_10_20,
|
||||
facts: [{ label: "结果状态", value: "已完成" }]
|
||||
}],
|
||||
map_payload: null
|
||||
},
|
||||
work_orders: []
|
||||
});
|
||||
await page.goto("/", { waitUntil: "domcontentloaded" });
|
||||
|
||||
await page.getByRole("button", { name: "打开最新后端分析成果" }).click();
|
||||
await expect(page.getByRole("heading", { name: "压力统计结果" })).toBeVisible();
|
||||
await page.getByRole("button", { name: "当前分析视图:压力统计结果" }).click();
|
||||
await expect(page.getByText("仅看地图", { exact: true })).toHaveCount(0);
|
||||
await page.getByRole("menuitem", { name: /半屏显示/ }).click();
|
||||
await expect(page.getByRole("menu")).toHaveCount(0);
|
||||
await expect(page.locator("#main-workspace")).toHaveAttribute("data-layout-mode", "map_split");
|
||||
await expect(page.locator("#workspace-map")).toBeVisible();
|
||||
await expect(page.locator("#artifact-workspace")).toBeVisible();
|
||||
await expect.poll(() => page.evaluate(() => ({
|
||||
backend: window.__waterNetworkMap
|
||||
?.querySourceFeatures("simulation-backend-analysis").length ?? 0,
|
||||
demo: window.__waterNetworkMap
|
||||
?.querySourceFeatures("simulation-impact-area").length ?? 0
|
||||
}))).toEqual({ backend: 0, demo: 0 });
|
||||
});
|
||||
|
||||
test("keeps mock conditions while using backend work orders and alerts", async ({ page }) => {
|
||||
await mockWorkbenchContext(page, {
|
||||
availability: "ready",
|
||||
source: "scheduled_tasks",
|
||||
scenario_availability: "not_configured",
|
||||
artifact_availability: "not_configured",
|
||||
schedule_availability: "ready",
|
||||
work_order_availability: "ready",
|
||||
alert_availability: "ready",
|
||||
generated_at: TODAY,
|
||||
conditions: [{
|
||||
id: "backend-schedule-diagnosis-next",
|
||||
task_id: "backend-schedule",
|
||||
session_id: "scheduled-condition-backend-schedule-diagnosis",
|
||||
title: "SCADA 后端定时诊断",
|
||||
summary: "来自项目数据库的持久化调度定义。",
|
||||
status: "pending",
|
||||
risk_level: "normal",
|
||||
scheduled_at: TODAY_10_35,
|
||||
updated_at: TODAY,
|
||||
detail: "每 5 分钟触发一次。",
|
||||
recommendation: null,
|
||||
evidence: ["调度 ID:diagnosis-5m"],
|
||||
model_name: "TJWater scheduler"
|
||||
}],
|
||||
alerts: [{
|
||||
id: "backend-alert-alarm-1",
|
||||
condition_id: null,
|
||||
source: {
|
||||
task_type: "scheduled_task",
|
||||
task_id: "diagnosis-5m",
|
||||
run_id: "trigger-1"
|
||||
},
|
||||
title: "后端告警:泵站通信中断",
|
||||
description: "由诊断任务明确推送到项目数据库。",
|
||||
occurred_at: TODAY,
|
||||
severity: "warning"
|
||||
}],
|
||||
scenarios: [],
|
||||
latest_analysis: null,
|
||||
work_orders: [{
|
||||
id: "wo-backend-1",
|
||||
code: "WO-20260917-001",
|
||||
scheduled_at: TODAY_11_00,
|
||||
title: "后端工单:北区阀门复核",
|
||||
summary: "现场复核阀门开度并回传。",
|
||||
status: "running",
|
||||
risk_level: "attention",
|
||||
updated_at: TODAY,
|
||||
detail: "来自正式工单同步适配器。",
|
||||
recommendation: "完成后复核压力。",
|
||||
duration_minutes: 45,
|
||||
source: "生产工单系统",
|
||||
dispatcher: "调度中心",
|
||||
priority: "urgent",
|
||||
subtasks: [{
|
||||
id: "wo-backend-1-subtask-1",
|
||||
title: "阀门开度复核",
|
||||
summary: "现场复核阀门开度。",
|
||||
status: "running",
|
||||
scheduled_at: TODAY_11_00,
|
||||
location: "北区阀门 V-1",
|
||||
assignee: "北区班组",
|
||||
duration_minutes: 45,
|
||||
reply_window_minutes: 20,
|
||||
stages: [
|
||||
{ id: "dispatch", sequence: 1, title: "派发", status: "done", owner: "调度中心", time_label: "10:50", description: "已派发。" },
|
||||
{ id: "execution", sequence: 2, title: "执行中", status: "current", owner: "北区班组", time_label: "11:00—11:45", description: "现场执行中。" },
|
||||
{ id: "reply", sequence: 3, title: "待复令", status: "pending", owner: "北区班组", time_label: "11:45—12:05", description: "等待复令。" }
|
||||
],
|
||||
reply_requirements: ["回传阀门开度"]
|
||||
}]
|
||||
}]
|
||||
});
|
||||
await page.goto("/", { waitUntil: "domcontentloaded" });
|
||||
|
||||
await page.getByRole("button", { name: "工况任务", exact: true }).click();
|
||||
const panel = page.getByRole("region", { name: "工况任务", exact: true });
|
||||
await expect(panel).toContainText("工况演示数据 · 后端工单");
|
||||
await expect(panel).toContainText("SCADA 数据诊断");
|
||||
await expect(panel).not.toContainText("SCADA 后端定时诊断");
|
||||
await panel.getByRole("button", { name: "展开工况任务" }).click();
|
||||
await expect(panel).toContainText("后端工单:北区阀门复核");
|
||||
await expect(panel).not.toContainText("工单演示回退");
|
||||
await panel.getByRole("button", { name: /后端工单:北区阀门复核/ }).click();
|
||||
const detail = panel.getByTestId("scheduled-condition-detail-scroll");
|
||||
await expect(detail.getByText("子任务", { exact: true })).toBeVisible();
|
||||
await expect(detail.getByText(/阀门开度复核/).first()).toBeVisible();
|
||||
await expect(detail.getByText("0/1 完成", { exact: true })).toBeVisible();
|
||||
await expect(
|
||||
detail.locator("details").filter({ hasText: "阀门开度复核" }).getByText("执行中", { exact: true })
|
||||
).toBeVisible();
|
||||
|
||||
const alertButton = page.getByRole("button", {
|
||||
name: "查看异常处置面板,当前 1 条待复核工况"
|
||||
});
|
||||
await alertButton.focus();
|
||||
await page.keyboard.press("Enter");
|
||||
await expect(page.getByText("来源:后端运行态", { exact: true })).toBeVisible();
|
||||
await expect(page.getByText("后端告警:泵站通信中断")).toBeVisible();
|
||||
});
|
||||
|
||||
function shanghaiTimestamp(hour: number, minute: number, dayOffset = 0) {
|
||||
const target = new Date(Date.now() + dayOffset * 24 * 60 * 60 * 1000);
|
||||
const parts = new Intl.DateTimeFormat("en-CA", {
|
||||
timeZone: "Asia/Shanghai",
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit"
|
||||
}).formatToParts(target);
|
||||
const get = (type: Intl.DateTimeFormatPartTypes) =>
|
||||
parts.find((part) => part.type === type)?.value ?? "";
|
||||
return `${get("year")}-${get("month")}-${get("day")}T${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}:00+08:00`;
|
||||
}
|
||||
Reference in New Issue
Block a user