import { afterEach, describe, expect, it, vi } from "vitest"; import { fetchWorkbenchAnalysisRun, parseWorkbenchRuntimeSnapshot } from "./workbench-runtime-client"; const projectPage = { items: [{ project_id: "project-1", gs_workspace: "tjwater_next", status: "active" }], total: 1, limit: 1000, offset: 0 }; const runtimeSnapshot = { availability: "ready", source: "scheduled_tasks", scenario_availability: "ready", artifact_availability: "ready", schedule_availability: "not_configured", work_order_availability: "not_configured", alert_availability: "ready", generated_at: "2026-09-17T02:30:00Z", conditions: [{ id: "schedule-run-1", task_id: "backend-schedule", session_id: "scheduled-condition-schedule-run-1", title: "演示 合成低压调查", summary: "来自后端持久化 Action Run 的 演示 沙箱测试状态。", status: "error", risk_level: "critical", scheduled_at: "2026-09-17T02:20:00Z", updated_at: "2026-09-17T02:25:00Z", detail: "演示 测试运行状态:已失败。", recommendation: "请检查失败步骤。", evidence: ["运行状态:failed"], model_name: "TJWater scheduler" }], alerts: [{ id: "scheduled-condition-alert-schedule-run-1", condition_id: "schedule-run-1", source: { task_type: "analysis_task", task_id: "backend-schedule", run_id: "schedule-run-1" }, title: "演示 测试待复核:演示 合成低压调查", description: "运行失败。", occurred_at: "2026-09-17T02:25:00Z", severity: "critical" }], 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: "2026-09-17T02:20:00Z" }], latest_analysis: { run_id: "analysis-1", name: "北区爆管定位", run_type: "burst_location", run_type_label: "爆管定位", status: "completed", status_label: "已完成", created_by: "alice", created_at: "2026-09-17T02:20:00Z", started_at: "2026-09-17T02:10:00Z", results: [{ result_type: "burst_location", created_at: "2026-09-17T02:20:00Z", facts: [{ label: "关联管段", value: "P-42" }] }], map_payload: { type: "FeatureCollection", features: [{ type: "Feature", properties: { label: "后端爆管定位" }, geometry: { type: "Point", coordinates: [121.5, 30.9] } }] } }, work_orders: [] }; describe("workbench runtime API client", () => { afterEach(() => vi.unstubAllGlobals()); it("maps a persisted scheduled condition", () => { const snapshot = parseWorkbenchRuntimeSnapshot(runtimeSnapshot); expect(snapshot.source).toBe("scheduled_tasks"); expect(snapshot.conditions).toEqual([ expect.objectContaining({ id: "schedule-run-1", kind: "condition", taskId: "backend-schedule", status: "error", modelName: "TJWater scheduler" }) ]); expect(snapshot.alerts[0]).toEqual(expect.objectContaining({ conditionId: "schedule-run-1", id: "scheduled-condition-alert-schedule-run-1", title: "演示 测试待复核:演示 合成低压调查", source: { taskType: "analysis_task", taskId: "backend-schedule", runId: "schedule-run-1" } })); expect(snapshot.scenarios[0]).toEqual(expect.objectContaining({ id: "analysis-run-analysis-1", runId: "analysis-1", runType: "burst_location" })); expect(snapshot.latestAnalysisArtifact).toEqual(expect.objectContaining({ id: "persisted-analysis-analysis-1", title: "北区爆管定位", confidence: "后端未提供", mapRelation: "required", spatialOverlay: expect.objectContaining({ type: "FeatureCollection" }), sources: ["项目 BizDB · analysis.runs", "项目 BizDB · analysis.results"] })); expect(snapshot.latestAnalysisArtifact?.blocks).toEqual(expect.arrayContaining([ expect.objectContaining({ kind: "data-table", rows: [expect.objectContaining({ facts: "关联管段:P-42" })] }) ])); expect(snapshot.simulationOverlay?.features).toHaveLength(1); }); it("keeps legacy analysis conditions out of the operational task feed", () => { const snapshot = parseWorkbenchRuntimeSnapshot({ ...runtimeSnapshot, source: "analysis_runs", 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: "2026-09-17T02:10:00Z", updated_at: "2026-09-17T02:20:00Z", detail: "分析结果已完成。", recommendation: null, evidence: ["运行 ID:analysis-1"], model_name: "TJWater analysis runtime" }] }); expect(snapshot.source).toBe("none"); expect(snapshot.conditions).toEqual([]); expect(snapshot.latestAnalysisArtifact).toEqual(expect.objectContaining({ id: "persisted-analysis-analysis-1", title: "北区爆管定位" })); expect(snapshot.scenarios).toHaveLength(1); }); it("rejects an untyped runtime payload instead of treating it as real data", () => { expect(() => parseWorkbenchRuntimeSnapshot({ ...runtimeSnapshot, source: "production" })).toThrow(); }); it("loads the requested analysis run instead of reusing the latest result", async () => { const runId = "86fd7c19-5b75-434f-999c-ec8fdf67d10b"; const selectedAnalysis = { ...runtimeSnapshot.latest_analysis, run_id: runId, name: "历史爆管定位", results: [{ result_type: "burst_location", created_at: "2026-09-17T01:20:00Z", facts: [{ label: "关联管段", value: "P-older" }] }], map_payload: { type: "FeatureCollection", features: [{ type: "Feature", properties: { label: "历史运行几何" }, geometry: { type: "Point", coordinates: [121.4, 30.8] } }] } }; const fetchMock = vi .fn() .mockResolvedValueOnce(new Response(JSON.stringify(projectPage), { status: 200 })) .mockResolvedValueOnce(new Response(JSON.stringify(selectedAnalysis), { status: 200 })); vi.stubGlobal("fetch", fetchMock); const projection = await fetchWorkbenchAnalysisRun( runId, vi.fn().mockResolvedValue("access-token") ); expect(projection.runId).toBe(runId); expect(projection.artifact).toEqual(expect.objectContaining({ id: `persisted-analysis-${runId}`, title: "历史爆管定位" })); expect(projection.artifact.blocks).toEqual(expect.arrayContaining([ expect.objectContaining({ kind: "data-table", rows: [expect.objectContaining({ facts: "关联管段:P-older" })] }) ])); expect(projection.simulationOverlay?.features[0]?.properties).toEqual({ label: "历史运行几何" }); expect(String(fetchMock.mock.calls[1]?.[0])).toContain( `/api/v1/workbench/analysis-runs/${runId}` ); const headers = new Headers(fetchMock.mock.calls[1]?.[1]?.headers); expect(headers.get("Authorization")).toBe("Bearer access-token"); expect(headers.get("X-Project-Id")).toBe("project-1"); }); it("drops invalid backend map geometry without discarding other real sections", () => { const snapshot = parseWorkbenchRuntimeSnapshot({ ...runtimeSnapshot, latest_analysis: { ...runtimeSnapshot.latest_analysis, map_payload: { type: "FeatureCollection", features: [{ type: "Feature", properties: {}, geometry: { type: "Point", coordinates: ["east", "north"] } }] } } }); expect(snapshot.source).toBe("scheduled_tasks"); expect(snapshot.scenarios).toHaveLength(1); expect(snapshot.simulationOverlay).toBeNull(); expect(snapshot.latestAnalysisArtifact?.mapRelation).toBe("none"); expect(snapshot.latestAnalysisArtifact).not.toHaveProperty("spatialOverlay"); }); it("maps provisioned backend work orders without using the demo shape", () => { const backendWorkOrder = { id: "wo-1", code: "WO-20260917-001", scheduled_at: "2026-09-17T03:00:00Z", title: "北区阀门现场复核", summary: "复核阀门开度并回传。", status: "completed", risk_level: "attention", updated_at: "2026-09-17T02:30:00Z", detail: "来自正式工单同步适配器。", recommendation: "完成后复核压力。", duration_minutes: 45, source: "生产工单系统", dispatcher: "调度中心", priority: "urgent", location: "北区阀门 V-1", assignee: "北区班组", feedback_requirements: ["回传阀门开度"], activity: [{ sequence: 1, occurred_at: "2026-09-17T02:30:00Z", actor: "调度中心", kind: "created", title: "工单创建", detail: "等待现场复核。" }] }; const snapshot = parseWorkbenchRuntimeSnapshot({ ...runtimeSnapshot, work_order_availability: "ready", work_orders: [backendWorkOrder] }); expect(snapshot.workOrderAvailability).toBe("ready"); expect(snapshot.workOrders).toEqual([expect.objectContaining({ id: "demo-work-order:wo-1", kind: "work_order", code: "WO-20260917-001", status: "completed", source: "生产工单系统", location: "北区阀门 V-1", assignee: "北区班组", feedbackRequirements: ["回传阀门开度"], activity: [expect.objectContaining({ title: "工单创建" })] })]); }); it("maps a provisioned backend alert without inventing a condition link", () => { const snapshot = parseWorkbenchRuntimeSnapshot({ ...runtimeSnapshot, alert_availability: "ready", alerts: [{ id: "backend-alert-alarm-1", condition_id: null, source: { task_type: "scheduled_task", task_id: "scada-diagnosis-5m", run_id: "trigger-1" }, title: "泵站通信告警", description: "由 SCADA 数据诊断任务明确推送。", occurred_at: "2026-09-17T02:29:00Z", severity: "warning" }] }); expect(snapshot.alertAvailability).toBe("ready"); expect(snapshot.alerts).toEqual([expect.objectContaining({ id: "backend-alert-alarm-1", title: "泵站通信告警", severity: "warning", source: { taskType: "scheduled_task", taskId: "scada-diagnosis-5m", runId: "trigger-1" } })]); expect(snapshot.alerts[0]).not.toHaveProperty("conditionId"); }); });