Files
codex-app-server/cloud/console-react/src/api/chv.test.ts
T

156 lines
7.1 KiB
TypeScript
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 { describe, expect, it } from "vitest";
import { chvAttachmentBlocked, chvAvailability, chvAvailabilityText, chvQueueHint, chvVmBadge, chvVmDisplay, chvVmStatusText, countChvWorkers, isChvExecutor, isWorkerAlive } from "./chv";
// 纯逻辑测试:只测 chv.ts,不渲染组件、不发请求、不读 localStorage。
// alive 规则与 WorkersSection 现有口径一致:alive 字段优先,
// 缺失时用 last_seen 距今 <= 120 秒判定在线。
describe("isWorkerAlive", () => {
it("alive 字段优先", () => {
expect(isWorkerAlive({ executor: "cloud-hypervisor", alive: true })).toBe(true);
expect(isWorkerAlive({ executor: "cloud-hypervisor", alive: false, last_seen: Date.now() / 1000 })).toBe(false);
});
it("无 alive 时用 last_seen 120 秒门槛", () => {
const now = Date.now() / 1000;
expect(isWorkerAlive({ executor: "cloud-hypervisor", last_seen: now - 10 })).toBe(true);
expect(isWorkerAlive({ executor: "cloud-hypervisor", last_seen: now - 121 })).toBe(false);
expect(isWorkerAlive({ executor: "cloud-hypervisor" })).toBe(false);
});
});
describe("countChvWorkers", () => {
it("只数 cloud-hypervisor,不数 docker/local", () => {
const now = Date.now() / 1000;
expect(countChvWorkers([
{ executor: "cloud-hypervisor", alive: true },
{ executor: "cloud-hypervisor", last_seen: now - 9999 },
{ executor: "docker", alive: true },
])).toEqual({ online: 1, total: 2 });
});
});
describe("chvAvailability", () => {
it("有清单时按清单数", () => {
expect(chvAvailability([{ executor: "cloud-hypervisor", alive: true }], "", "")).toEqual(
{ state: "known", online: 1, total: 1 },
);
});
it("无清单但聚合文案时是未知,不是 0", () => {
expect(chvAvailability(null, "在线 2 / 离线 1(共 3;完整 worker 清单仅全局管理员可见)", "")).toEqual(
{ state: "unknown", reason: "aggregate-only" },
);
});
it("无 worker 注册时是已知 0", () => {
expect(chvAvailability(null, "无 worker 注册", "")).toEqual({ state: "known", online: 0, total: 0 });
});
it("加载失败时是未知", () => {
expect(chvAvailability(null, "", "加载失败:x")).toEqual({ state: "unknown", reason: "load-failed" });
});
it("尚未加载时是未知", () => {
expect(chvAvailability(null, "未加载", "")).toEqual({ state: "unknown", reason: "not-loaded" });
});
});
describe("isChvExecutor", () => {
it("精确值才算 CHV,不做大小写/前缀宽松匹配", () => {
expect(isChvExecutor("cloud-hypervisor")).toBe(true);
expect(isChvExecutor("Cloud-Hypervisor")).toBe(false);
expect(isChvExecutor("cloud-hypervisor-x")).toBe(false);
expect(isChvExecutor("docker")).toBe(false);
expect(isChvExecutor(undefined)).toBe(false);
expect(isChvExecutor(null)).toBe(false);
});
});
describe("chvAttachmentBlocked", () => {
it("仅 CHV + 带附件时拦(后端 400 的前端提示口径)", () => {
expect(chvAttachmentBlocked("cloud-hypervisor", true)).toBe(true);
expect(chvAttachmentBlocked("cloud-hypervisor", false)).toBe(false);
expect(chvAttachmentBlocked("docker", true)).toBe(false);
expect(chvAttachmentBlocked("cloud", true)).toBe(false);
});
});
describe("chvVmStatusText", () => {
it("已报告死亡时给死亡文案", () => {
expect(chvVmStatusText({ executor: "cloud-hypervisor", chv_vm_dead: true })).toContain("VM 中途死亡");
});
it("CHV 无字段时给未报告文案,绝不写成活着", () => {
const text = chvVmStatusText({ executor: "cloud-hypervisor" });
expect(text).toContain("未报告 VM 死亡");
expect(text).toContain("不代表 VM 活着");
});
it("非 CHV 任务不显示 VM 行", () => {
expect(chvVmStatusText({ executor: "docker" })).toBe("");
expect(chvVmStatusText({ executor: "docker", chv_vm_dead: true })).toBe("");
});
});
describe("chvVmBadge", () => {
it("只有 CHV + 已报告死亡时才出徽标", () => {
expect(chvVmBadge({ executor: "cloud-hypervisor", chv_vm_dead: true })).toBe("VM 已报告死亡");
expect(chvVmBadge({ executor: "cloud-hypervisor" })).toBe("");
expect(chvVmBadge({ executor: "docker", chv_vm_dead: true })).toBe("");
});
});
describe("chvQueueHint", () => {
it("仅 CHV + 排队 + 已知零在线时给提示", () => {
const knownZero = { state: "known" as const, online: 0, total: 0 };
expect(chvQueueHint("cloud-hypervisor", "queued", knownZero)).toContain("可能原因");
expect(chvQueueHint("docker", "queued", knownZero)).toBe("");
expect(chvQueueHint("cloud-hypervisor", "running", knownZero)).toBe("");
expect(chvQueueHint("cloud-hypervisor", "queued", { state: "unknown" as const, reason: "aggregate-only" })).toBe("");
expect(chvQueueHint("cloud-hypervisor", "queued", { state: "known" as const, online: 1, total: 1 })).toBe("");
});
});
describe("chvVmDisplay(to10 四态)", () => {
it("字段 present=true → dead", () => {
const d = chvVmDisplay({ executor: "cloud-hypervisor", chv_vm_dead: true });
expect(d.state).toBe("dead");
expect(d.text).toContain("VM 中途死亡");
});
it("字段 absent → not-reported,不猜 live", () => {
const d = chvVmDisplay({ executor: "cloud-hypervisor" });
expect(d.state).toBe("not-reported");
expect(d.text).toContain("不代表 VM 活着");
});
it("任务未加载 → unknown", () => {
const d = chvVmDisplay(null);
expect(d.state).toBe("unknown");
expect(d.text).toContain("无法判断");
});
it("非 CHV → not-applicable,text 为空", () => {
const d = chvVmDisplay({ executor: "docker", chv_vm_dead: true });
expect(d.state).toBe("not-applicable");
expect(d.text).toBe("");
});
it("旧入口仍是 display 的 text(unknown/not-applicable 回空)", () => {
expect(chvVmStatusText({ executor: "cloud-hypervisor", chv_vm_dead: true })).toContain("VM 中途死亡");
expect(chvVmStatusText(null)).toBe("");
expect(chvVmStatusText({ executor: "docker" })).toBe("");
});
});
describe("chvAvailabilityText(to10 四处统一文案)", () => {
it("known 零在线:不拦提交、后端是最终权威", () => {
const text = chvAvailabilityText({ state: "known", online: 0, total: 2 });
expect(text).toContain("在线 0 / 共 2");
expect(text).toContain("不拦提交");
expect(text).toContain("最终权威");
});
it("known 非零:只有在线数,无排队警告", () => {
const text = chvAvailabilityText({ state: "known", online: 1, total: 1 });
expect(text).toContain("在线 1 / 共 1");
expect(text).not.toContain("排队");
});
it("未知三原因各有不同文案,绝不写成 0", () => {
expect(chvAvailabilityText({ state: "unknown", reason: "aggregate-only" })).toContain("仅全局管理员可见");
expect(chvAvailabilityText({ state: "unknown", reason: "load-failed" })).toContain("加载失败");
expect(chvAvailabilityText({ state: "unknown", reason: "not-loaded" })).toContain("尚未加载");
for (const reason of ["aggregate-only", "load-failed", "not-loaded"] as const) {
expect(chvAvailabilityText({ state: "unknown", reason })).not.toContain("在线 0");
}
});
});