Refresh ops center in realtime
This commit is contained in:
121
tests/ops-repair-ticket-events.test.ts
Normal file
121
tests/ops-repair-ticket-events.test.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { mkdtemp, rm } from "node:fs/promises";
|
||||
|
||||
let runtimeRoot = "";
|
||||
let readState: (typeof import("../src/lib/boss-data"))["readState"];
|
||||
let writeState: (typeof import("../src/lib/boss-data"))["writeState"];
|
||||
let approveRepairTicket: (typeof import("../src/lib/boss-data"))["approveRepairTicket"];
|
||||
let verifyRepairTicket: (typeof import("../src/lib/boss-data"))["verifyRepairTicket"];
|
||||
let subscribeBossEvents: (typeof import("../src/lib/boss-events"))["subscribeBossEvents"];
|
||||
|
||||
async function setup() {
|
||||
if (runtimeRoot) return;
|
||||
|
||||
runtimeRoot = await mkdtemp(path.join(os.tmpdir(), "boss-ops-events-"));
|
||||
process.env.BOSS_RUNTIME_ROOT = runtimeRoot;
|
||||
process.env.BOSS_STATE_FILE = path.join(runtimeRoot, "boss-state.json");
|
||||
|
||||
const data = await import("../src/lib/boss-data.ts");
|
||||
const events = await import("../src/lib/boss-events.ts");
|
||||
readState = data.readState;
|
||||
writeState = data.writeState;
|
||||
approveRepairTicket = data.approveRepairTicket;
|
||||
verifyRepairTicket = data.verifyRepairTicket;
|
||||
subscribeBossEvents = events.subscribeBossEvents;
|
||||
}
|
||||
|
||||
async function resetOpsState() {
|
||||
const state = await readState();
|
||||
state.opsFaults = [
|
||||
{
|
||||
faultId: "fault-win-camera",
|
||||
faultKey: "WIN_CAMERA_UPLOAD_DELAY",
|
||||
severity: "high",
|
||||
status: "open",
|
||||
nodeId: "mac-studio",
|
||||
serviceName: "boss-local-agent",
|
||||
projectId: "master-agent",
|
||||
threadRef: "thread-ops-1",
|
||||
traceId: "trace-ops-1",
|
||||
runbookId: "runbook-camera-sync",
|
||||
firstSeenAt: "2026-03-25T11:34:00+08:00",
|
||||
lastSeenAt: "2026-03-25T11:58:00+08:00",
|
||||
summary: "摄像头证据上传延迟。",
|
||||
suggestedNextAction: "重试本地 agent 上传。",
|
||||
autoRepairable: true,
|
||||
},
|
||||
];
|
||||
state.opsRepairTickets = [
|
||||
{
|
||||
ticketId: "ticket-win-camera",
|
||||
faultId: "fault-win-camera",
|
||||
title: "重试摄像头证据上传",
|
||||
approvalStatus: "approved",
|
||||
executionStatus: "running",
|
||||
requestedBy: "运维 Agent",
|
||||
approvedBy: "主 Agent",
|
||||
targetNodeId: "mac-studio",
|
||||
actionSummary: "重新触发本地 agent 心跳和摄像头证据上传。",
|
||||
resultSummary: "等待复验中。",
|
||||
createdAt: "2026-03-25T11:42:00+08:00",
|
||||
updatedAt: "2026-03-25T11:57:00+08:00",
|
||||
},
|
||||
];
|
||||
state.opsRepairVerifications = [
|
||||
{
|
||||
verificationId: "verify-win-camera",
|
||||
ticketId: "ticket-win-camera",
|
||||
verifier: "运维审计 Agent",
|
||||
status: "watching",
|
||||
summary: "等待关键帧落库后关闭工单。",
|
||||
verifiedAt: "2026-03-25T11:58:00+08:00",
|
||||
},
|
||||
];
|
||||
await writeState(state);
|
||||
}
|
||||
|
||||
test.beforeEach(async () => {
|
||||
await setup();
|
||||
await resetOpsState();
|
||||
});
|
||||
|
||||
test.after(async () => {
|
||||
if (runtimeRoot) {
|
||||
await rm(runtimeRoot, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("approve repair ticket publishes project context risk event", async () => {
|
||||
const events: Array<{ event: string; payload: { status?: string; note?: string } }> = [];
|
||||
const unsubscribe = subscribeBossEvents((event, payload) => {
|
||||
events.push({ event, payload });
|
||||
});
|
||||
|
||||
await approveRepairTicket("ticket-win-camera");
|
||||
unsubscribe();
|
||||
|
||||
const latest = events.at(-1);
|
||||
assert.ok(latest);
|
||||
assert.equal(latest.event, "project.context_risk.updated");
|
||||
assert.equal(latest.payload.status, "approved");
|
||||
assert.equal(latest.payload.note, "ticket-win-camera");
|
||||
});
|
||||
|
||||
test("verify repair ticket publishes project context risk event", async () => {
|
||||
const events: Array<{ event: string; payload: { status?: string; note?: string } }> = [];
|
||||
const unsubscribe = subscribeBossEvents((event, payload) => {
|
||||
events.push({ event, payload });
|
||||
});
|
||||
|
||||
await verifyRepairTicket("ticket-win-camera");
|
||||
unsubscribe();
|
||||
|
||||
const latest = events.at(-1);
|
||||
assert.ok(latest);
|
||||
assert.equal(latest.event, "project.context_risk.updated");
|
||||
assert.equal(latest.payload.status, "verified");
|
||||
assert.equal(latest.payload.note, "ticket-win-camera");
|
||||
});
|
||||
Reference in New Issue
Block a user