Files
pikasTech-HWLAB/web/hwlab-cloud-web/scripts/live-status-contract.test.mjs
T
2026-05-23 10:31:20 +00:00

314 lines
8.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import assert from "node:assert/strict";
import test from "node:test";
import { classifyWorkbenchLiveStatus } from "../live-status.mjs";
const okApi = Object.freeze({
ok: true,
status: 200,
data: {
serviceId: "hwlab-cloud-api",
status: "ok",
ready: true,
readiness: {
status: "ok",
ready: true,
durability: {
status: "ready",
ready: true
}
},
runtime: {
status: "ready",
durable: true,
ready: true,
liveRuntimeEvidence: true
}
}
});
const okRest = Object.freeze({
ok: true,
status: 200,
data: {
serviceId: "hwlab-cloud-api",
status: "ok",
ready: true,
codeAgent: {
endpoint: "POST /v1/agent/chat",
status: "available",
ready: true,
provider: "openai-responses",
backend: "hwlab-cloud-api/openai-responses",
capabilityLevel: "available"
}
}
});
const okM3Control = Object.freeze({
ok: true,
status: 200,
data: {
status: "available",
readiness: {
status: "ready",
controlReady: true,
sourceKind: "DEV-LIVE",
evidenceLevel: "DEV-LIVE"
}
}
});
const okM3Status = Object.freeze({
ok: true,
status: 200,
data: {
status: "live",
sourceKind: "DEV-LIVE",
summary: "M3 硬件状态与可信持久化均为 DEV-LIVE。"
}
});
test("classifies fully ready workbench runtime as API 正常", () => {
const status = classifyWorkbenchLiveStatus({
healthLive: okApi,
restIndex: okRest,
health: okApi,
adapter: okApi,
m3Control: okM3Control,
m3Status: okM3Status
});
assert.equal(status.kind, "pass");
assert.equal(status.label, "API 正常");
assert.match(status.detail, /hwlab-cloud-api \/health\/live/u);
assert.equal(status.internalRawStatuses.includes("degraded"), false);
});
test("classifies concrete API failure with service path and HTTP status", () => {
const status = classifyWorkbenchLiveStatus({
healthLive: {
ok: false,
path: "/health/live",
status: 503,
error: "/health/live HTTP 503runtime unavailable"
},
restIndex: okRest,
health: okApi,
adapter: okApi,
m3Control: okM3Control,
m3Status: okM3Status
});
assert.equal(status.kind, "error");
assert.equal(status.label, "API 错误");
assert.equal(status.serviceId, "hwlab-cloud-api");
assert.equal(status.apiPath, "/health/live");
assert.equal(status.reasonCode, "HTTP 503");
assert.match(status.detail, /错误:hwlab-cloud-api \/health\/live \/ HTTP 503/u);
});
test("classifies durable runtime degraded as explicit read-only mode", () => {
const status = classifyWorkbenchLiveStatus({
healthLive: {
ok: true,
status: 200,
data: {
serviceId: "hwlab-cloud-api",
status: "degraded",
ready: false,
runtime: {
durable: true,
ready: false,
liveRuntimeEvidence: false,
status: "blocked",
blocker: "runtime_durable_adapter_schema_blocked",
connection: {
queryResult: "schema_blocked"
}
},
readiness: {
status: "degraded",
ready: false,
durability: {
status: "blocked",
ready: false,
blocker: "runtime_durable_adapter_schema_blocked",
blockedLayer: "schema",
queryResult: "schema_blocked"
}
},
blockerCodes: ["runtime_durable_adapter_schema_blocked"]
}
},
restIndex: okRest,
health: okApi,
adapter: okApi,
m3Control: okM3Control,
m3Status: okM3Status
});
assert.equal(status.kind, "readonly");
assert.equal(status.label, "只读模式");
assert.equal(status.reasonCode, "runtime_durable_adapter_schema_blocked");
assert.match(status.detail, /只读:hwlab-cloud-api \/health\/live/u);
assert.match(status.detail, /schema_blocked/u);
assert.deepEqual(status.internalRawStatuses.filter((item) => item === "degraded"), ["degraded"]);
});
test("classifies missing probes as unverified instead of degraded", () => {
const status = classifyWorkbenchLiveStatus({});
assert.equal(status.kind, "unverified");
assert.equal(status.label, "等待验证");
assert.match(status.detail, /等待验证/u);
assert.doesNotMatch(`${status.label} ${status.detail}`, /降级/u);
});
test("classifies memory or non-durable runtime as read-only with explicit reason", () => {
const status = classifyWorkbenchLiveStatus({
healthLive: okApi,
restIndex: okRest,
health: {
ok: true,
status: 200,
data: {
serviceId: "hwlab-cloud-api",
status: "degraded",
runtime: {
adapter: "memory",
durable: false
}
}
},
adapter: okApi,
m3Control: okM3Control,
m3Status: okM3Status
});
assert.equal(status.kind, "readonly");
assert.equal(status.label, "只读模式");
assert.equal(status.reasonCode, "runtime_durable_false");
assert.match(status.detail, /runtime durable=false/u);
});
test("classifies raw degraded without durable/read-only reason as API error", () => {
const status = classifyWorkbenchLiveStatus({
healthLive: {
ok: true,
status: 200,
data: {
serviceId: "hwlab-cloud-api",
status: "degraded",
ready: false
}
},
restIndex: okRest,
health: okApi,
adapter: okApi,
m3Control: okM3Control,
m3Status: okM3Status
});
assert.equal(status.kind, "error");
assert.equal(status.label, "API 错误");
assert.equal(status.reasonCode, "ready_false_without_blocker");
assert.match(status.detail, /ready=false without a concrete blocker/u);
assert.equal(status.internalRawStatuses.includes("degraded"), true);
assert.doesNotMatch(`${status.label} ${status.detail}`, /API 降级/u);
});
test("classifies Code Agent provider timeout or fallback with concrete attribution", () => {
const providerTimeout = classifyWorkbenchLiveStatus({
healthLive: okApi,
restIndex: {
ok: true,
status: 200,
data: {
serviceId: "hwlab-cloud-api",
status: "ok",
ready: true,
codeAgent: {
endpoint: "POST /v1/agent/chat",
status: "blocked",
ready: false,
provider: "openai-responses",
backend: "hwlab-cloud-api/openai-responses",
error: {
providerStatus: 504
},
summary: "/v1/agent/chat timeout"
}
}
},
health: okApi,
adapter: okApi,
m3Control: okM3Control,
m3Status: okM3Status
});
assert.equal(providerTimeout.kind, "error");
assert.equal(providerTimeout.apiPath, "POST /v1/agent/chat");
assert.equal(providerTimeout.reasonCode, "provider_http_504");
assert.match(providerTimeout.detail, /hwlab-cloud-api POST \/v1\/agent\/chat/u);
const fallback = classifyWorkbenchLiveStatus({
healthLive: okApi,
restIndex: {
ok: true,
status: 200,
data: {
serviceId: "hwlab-cloud-api",
status: "ok",
ready: true,
codeAgent: {
endpoint: "POST /v1/agent/chat",
status: "available",
ready: true,
provider: "openai-responses",
backend: "hwlab-cloud-api/openai-responses",
capabilityLevel: "text-chat-only"
}
}
},
health: okApi,
adapter: okApi,
m3Control: okM3Control,
m3Status: okM3Status
});
assert.equal(fallback.kind, "readonly");
assert.equal(fallback.label, "只读模式");
assert.equal(fallback.reasonCode, "fallback_text_chat_only");
});
test("classifies M3 control blockers by cloud-api/gateway/box/patch-panel layer", () => {
const status = classifyWorkbenchLiveStatus({
healthLive: okApi,
restIndex: okRest,
health: okApi,
adapter: okApi,
m3Control: {
ok: true,
status: 200,
data: {
status: "blocked",
readiness: {
status: "blocked",
controlReady: false,
blocker: {
code: "m3_wiring_missing",
layer: "hwlab-patch-panel",
zh: "hwlab-patch-panel route unavailable"
}
}
}
},
m3Status: okM3Status
});
assert.equal(status.kind, "error");
assert.equal(status.serviceId, "hwlab-patch-panel");
assert.equal(status.apiPath, "/v1/m3/io");
assert.equal(status.reasonCode, "m3_wiring_missing");
assert.match(status.detail, /hwlab-patch-panel \/v1\/m3\/io/u);
});