import { beforeEach, describe, expect, it, vi } from "vitest"; import { resolveStatusGatewayHealth, resolveStatusGatewayHealthSafe, resolveStatusLastHeartbeat, resolveStatusRuntimeDetails, resolveStatusRuntimeSnapshot, resolveStatusSecurityAudit, resolveStatusServiceSummaries, resolveStatusUsageSummary, } from "./status-runtime-shared.ts"; const mocks = vi.hoisted(() => ({ loadProviderUsageSummary: vi.fn(), runSecurityAudit: vi.fn(), callGateway: vi.fn(), getDaemonStatusSummary: vi.fn(), getNodeDaemonStatusSummary: vi.fn(), })); vi.mock("../infra/provider-usage.js", () => ({ loadProviderUsageSummary: mocks.loadProviderUsageSummary, })); vi.mock("../security/audit.runtime.js", () => ({ runSecurityAudit: mocks.runSecurityAudit, })); vi.mock("../gateway/call.js", () => ({ callGateway: mocks.callGateway, })); vi.mock("./status.daemon.js", () => ({ getDaemonStatusSummary: mocks.getDaemonStatusSummary, getNodeDaemonStatusSummary: mocks.getNodeDaemonStatusSummary, })); describe("status-runtime-shared", () => { beforeEach(() => { vi.clearAllMocks(); mocks.loadProviderUsageSummary.mockResolvedValue({ providers: [] }); mocks.runSecurityAudit.mockResolvedValue({ summary: { critical: 0 }, findings: [] }); mocks.callGateway.mockResolvedValue({ ok: true }); mocks.getDaemonStatusSummary.mockResolvedValue({ label: "LaunchAgent" }); mocks.getNodeDaemonStatusSummary.mockResolvedValue({ label: "node" }); }); it("resolves the shared security audit payload", async () => { await resolveStatusSecurityAudit({ config: { gateway: {} }, sourceConfig: { gateway: {} }, }); expect(mocks.runSecurityAudit).toHaveBeenCalledWith({ config: { gateway: {} }, sourceConfig: { gateway: {} }, deep: false, includeFilesystem: true, includeChannelSecurity: true, }); }); it("resolves usage summaries with the provided timeout", async () => { await resolveStatusUsageSummary(1234); expect(mocks.loadProviderUsageSummary).toHaveBeenCalledWith({ timeoutMs: 1234 }); }); it("resolves gateway health with the shared probe call shape", async () => { await resolveStatusGatewayHealth({ config: { gateway: {} }, timeoutMs: 5000, }); expect(mocks.callGateway).toHaveBeenCalledWith({ method: "health", params: { probe: true }, timeoutMs: 5000, config: { gateway: {} }, }); }); it("returns a fallback health error when the gateway is unreachable", async () => { await expect( resolveStatusGatewayHealthSafe({ config: { gateway: {} }, gatewayReachable: false, gatewayProbeError: "timeout", }), ).resolves.toEqual({ error: "timeout" }); expect(mocks.callGateway).not.toHaveBeenCalled(); }); it("passes gateway call overrides through the safe health path", async () => { await resolveStatusGatewayHealthSafe({ config: { gateway: {} }, timeoutMs: 4321, gatewayReachable: true, callOverrides: { url: "ws://127.0.0.1:18789", token: "tok", }, }); expect(mocks.callGateway).toHaveBeenCalledWith({ method: "health", params: { probe: true }, timeoutMs: 4321, config: { gateway: {} }, url: "ws://127.0.0.1:18789", token: "tok", }); }); it("returns null for heartbeat when the gateway is unreachable", async () => { expect( await resolveStatusLastHeartbeat({ config: { gateway: {} }, timeoutMs: 1000, gatewayReachable: false, }), ).toBeNull(); expect(mocks.callGateway).not.toHaveBeenCalled(); }); it("catches heartbeat gateway errors and returns null", async () => { mocks.callGateway.mockRejectedValueOnce(new Error("boom")); expect( await resolveStatusLastHeartbeat({ config: { gateway: {} }, timeoutMs: 1000, gatewayReachable: true, }), ).toBeNull(); expect(mocks.callGateway).toHaveBeenCalledWith({ method: "last-heartbeat", params: {}, timeoutMs: 1000, config: { gateway: {} }, }); }); it("resolves daemon summaries together", async () => { await expect(resolveStatusServiceSummaries()).resolves.toEqual([ { label: "LaunchAgent" }, { label: "node" }, ]); }); it("resolves shared runtime details with optional usage and deep fields", async () => { await expect( resolveStatusRuntimeDetails({ config: { gateway: {} }, timeoutMs: 1234, usage: true, deep: true, gatewayReachable: true, }), ).resolves.toEqual({ usage: { providers: [] }, health: { ok: true }, lastHeartbeat: { ok: true }, gatewayService: { label: "LaunchAgent" }, nodeService: { label: "node" }, }); expect(mocks.loadProviderUsageSummary).toHaveBeenCalledWith({ timeoutMs: 1234 }); expect(mocks.callGateway).toHaveBeenNthCalledWith(1, { method: "health", params: { probe: true }, timeoutMs: 1234, config: { gateway: {} }, }); expect(mocks.callGateway).toHaveBeenNthCalledWith(2, { method: "last-heartbeat", params: {}, timeoutMs: 1234, config: { gateway: {} }, }); }); it("skips optional runtime details when flags are off", async () => { await expect( resolveStatusRuntimeDetails({ config: { gateway: {} }, timeoutMs: 1234, usage: false, deep: false, gatewayReachable: true, }), ).resolves.toEqual({ usage: undefined, health: undefined, lastHeartbeat: null, gatewayService: { label: "LaunchAgent" }, nodeService: { label: "node" }, }); expect(mocks.loadProviderUsageSummary).not.toHaveBeenCalled(); expect(mocks.callGateway).not.toHaveBeenCalled(); }); it("suppresses health failures inside shared runtime details", async () => { mocks.callGateway.mockRejectedValueOnce(new Error("boom")); await expect( resolveStatusRuntimeDetails({ config: { gateway: {} }, timeoutMs: 1234, deep: true, gatewayReachable: false, suppressHealthErrors: true, }), ).resolves.toEqual({ usage: undefined, health: undefined, lastHeartbeat: null, gatewayService: { label: "LaunchAgent" }, nodeService: { label: "node" }, }); }); it("resolves the shared runtime snapshot with security audit and runtime details", async () => { await expect( resolveStatusRuntimeSnapshot({ config: { gateway: {} }, sourceConfig: { gateway: { mode: "local" } }, timeoutMs: 1234, usage: true, deep: true, gatewayReachable: true, includeSecurityAudit: true, }), ).resolves.toEqual({ securityAudit: { summary: { critical: 0 }, findings: [] }, usage: { providers: [] }, health: { ok: true }, lastHeartbeat: { ok: true }, gatewayService: { label: "LaunchAgent" }, nodeService: { label: "node" }, }); expect(mocks.runSecurityAudit).toHaveBeenCalledWith({ config: { gateway: {} }, sourceConfig: { gateway: { mode: "local" } }, deep: false, includeFilesystem: true, includeChannelSecurity: true, }); }); });