Files
ITWorx_MCP_Hub-Public/apps/web/tests/operator-data.test.ts
T

52 lines
3.3 KiB
TypeScript

import { describe, expect, it } from "vitest";
import type { DashboardSnapshot } from "../src/contracts";
import { actionInbox, aggregateTrend, alertDestination } from "../src/operator-data";
const snapshot: DashboardSnapshot = {
generatedAt: "2026-10-01T10:00:00Z", staleAfterSeconds: 90,
health: { hub: "healthy", gateway: "healthy", detail: "Available" },
projects: [], connectors: [{ id: "gitea-alpha", name: "gitea", project: "alpha", state: "degraded", registrationState: "registered", readiness: { state: "unknown", detail: "Not probed", observedAt: null, source: "not-probed" }, detail: "Readiness failed" }],
denials: { count: 2, window: "24h", latestTool: "gitea.repository.get" },
drift: { count: 1, projects: ["alpha"], known: true, detail: "Catalog differs" },
activeClients: 1, backup: { state: "degraded", lastSuccessfulAt: null, detail: "No backup observed" },
version: { application: "1.0.0", schema: "1" },
};
describe("operator signals", () => {
it("routes a connector signal to its exact project binding context", () => {
const item = actionInbox(snapshot, false, false).find((signal) => signal.project === "alpha" && signal.subsystem === "gitea");
expect(item?.href).toBe("/connectors/gitea-alpha");
expect(item?.detail).toBe("Readiness failed");
expect(item?.observedAt).toBe("2026-10-01T10:00:00Z");
});
it("exposes audit navigation only to an authorized auditor", () => {
expect(actionInbox(snapshot, false, false).find((signal) => signal.subsystem === "Authorization")?.href).toBe("/operations?section=alerts");
expect(actionInbox(snapshot, false, true).find((signal) => signal.subsystem === "Authorization")?.href).toBe("/audit?q=gitea.repository.get");
});
it("links drift and backup to their bounded resolution workspace", () => {
const signals = actionInbox(snapshot, false, true);
expect(signals.find((signal) => signal.subsystem === "Catalog")?.href).toBe("/operations?section=checks");
expect(signals.find((signal) => signal.subsystem === "Recovery")?.href).toBe("/operations?section=recovery");
expect(alertDestination("BACKUP_STALE", false)).toBe("/operations?section=recovery");
});
it("keeps unknown and stale state explicit without claiming a diagnosis", () => {
const signals = actionInbox({ ...snapshot, drift: { ...snapshot.drift, known: false } }, true, false);
expect(signals[0]?.subsystem).toBe("Freshness");
expect(signals.find((signal) => signal.subsystem === "Catalog")?.status).toBe("unknown");
});
});
describe("mobile call buckets", () => {
it("aggregates each four-hour interval without dropping outcomes", () => {
const trend = Array.from({ length: 24 }, (_, hour) => ({ hour: `2026-10-01T${String(hour).padStart(2, "0")}:00:00Z`, success: 1, denied: 2, error: 3, rate_limited: 4 }));
const buckets = aggregateTrend(trend, 4);
expect(buckets).toHaveLength(6);
expect(buckets[0]).toEqual({ hour: "2026-10-01T00:00:00Z", endHour: "2026-10-01T03:00:00Z", success: 4, denied: 8, error: 12, rate_limited: 16 });
expect(buckets[5]?.success).toBe(4);
});
it("retains partial buckets and handles empty observations", () => {
expect(aggregateTrend([], 4)).toEqual([]);
expect(aggregateTrend([{ hour: "2026-10-01T00:00:00Z", success: 2, denied: 0, error: 1, rate_limited: 0 }], 4)[0]?.error).toBe(1);
});
});