Files
ModelForge-Public/frontend/src/components/CapabilityWorkspace.test.tsx
T

355 lines
23 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 { act, cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { setOperatorCredential, clearOperatorCredential } from "../lib/api";
import { CapabilityWorkspace } from "./CapabilityWorkspace";
import type { CapabilityDeployment, SchedulerBudget } from "../types";
const deployment: CapabilityDeployment = {
id: "deployment-1", capability: "rag.embedding", contract_version: 1,
deployment_candidate_id: "candidate-1", production_approval_id: "approval-1",
artifact_set_id: "artifact-set-1", runtime_profile_id: "profile-1",
compute_node_id: "node-1", accelerator_id: "gpu-1",
embedding_space: { id: "space-1", identity_digest: "a".repeat(64), dimension: 1024, normalized: true, migration_class: "requires_reindex", identity_facts: {}, created_at: "2026-08-25T12:00:00Z" },
resource_envelope: { id: "envelope-1", runtime_probe_id: "probe-1", accelerator_kind: "NVIDIA RTX 4080 SUPER", accelerator_uuid: "GPU-test", environment_fingerprint: "b".repeat(64), concurrency: 1, batch_size: 8, max_sequence_length: 8192, baseline_vram_bytes: 1_100_000_000, resident_vram_bytes: 1_500_000_000, peak_vram_bytes: 2_700_000_000, required_vram_bytes: 1_600_000_000, cold_load_time_ms: 3690, inference_latency_ms: 1203, stale: false },
residency: { id: "residency-1", state: "warm", worker_instance_id: "worker-1", load_count: 1, active_requests: 0, measured_resident_vram_bytes: 1_500_000_000, external_baseline_vram_bytes: 636_000_000, health: { functional: true }, resident_since: "2026-08-25T12:00:00Z", last_used_at: "2026-08-25T12:01:00Z" },
channel: "stable", status: "stable", production: true, health_status: "healthy",
routing_weight: 100, fallback_policy: {}, residency_policy: "keep_warm",
keep_warm_seconds: 900, max_concurrency: 1, max_queue_depth: 16,
config_fingerprint: "c".repeat(64), provenance: { runtime_probe_id: "probe-1", compatibility_assessment_id: "assessment-1" },
rollback_policy: { mode: "drain_to_unavailable" }, promoted_at: "2026-08-25T12:00:00Z", created_at: "2026-08-25T12:00:00Z",
};
const budget: SchedulerBudget = {
compute_node_id: "node-1", node_name: "GPU Node", accelerator_id: "gpu-1",
accelerator_uuid: "GPU-test", accelerator_name: "NVIDIA RTX 4080 SUPER",
total_vram_bytes: 17_171_480_576, observed_used_vram_bytes: 2_200_000_000,
external_vram_bytes: 700_000_000, resident_vram_bytes: 1_500_000_000,
leased_vram_bytes: 0, safety_reserve_bytes: 1_073_741_824,
schedulable_free_vram_bytes: 13_897_738_752, pressure: false, observed_at: "2026-08-25T12:00:00Z",
pressure_state: "NORMAL", attribution_confidence: "KNOWN", invariant_delta_bytes: 0,
policy_revision: "m10-v1",
};
function mockServing(options: { deployments?: CapabilityDeployment[]; invokeError?: boolean; calls?: string[] } = {}): void {
vi.stubGlobal("fetch", vi.fn((input: RequestInfo | URL, init?: RequestInit) => {
const url = String(input);
let payload: unknown = [];
let status = 200;
if (url.endsWith("/api/v1/capabilities")) payload = [{ key: "rag.embedding", version: 1, description: "Local retrieval", stable_deployment: null, contract: { capability: "rag.embedding", version: 1, description: "Local retrieval", modalities: { input: ["text"], output: ["vector"] }, upgrade_class: "requires_reindex", vector: { dimensionality: 1024, normalized: true, cross_deployment_compatible: false }, slo: {}, privacy: { classification: "confidential", allow_persistence: false, allow_logging_payloads: false, allow_network_egress: false }, resources: { accelerator_required: true, cpu_fallback_allowed: false }, fallback: { allowed: false, mode: "hard_fail" }, production_priority: "production", default_residency: "keep_warm", estate: { category: "RAG", purpose: "Local retrieval", stability: "stable", resource_class: "MEDIUM", evaluation_type: "retrieval", consumers: [] } } }];
if (url.endsWith("/api/v1/capability-deployments")) payload = options.deployments ?? [deployment];
if (url.endsWith("/api/v1/capability-estate")) payload = [
{ capability: "rag.embedding", version: 1, category: "RAG", purpose: "Local retrieval", declared_stability: "stable", operational_state: options.deployments?.length === 0 ? "not_deployed" : "stable", current_deployment_id: "deployment-1", model: "Nomic", revision: "a".repeat(40), runtime: "sentence_transformers", node: "node-1", resource_class: "MEDIUM", measured_required_vram_bytes: 1_600_000_000, consumers: ["examplerag"], privacy_class: "confidential", evaluation_type: "retrieval", evaluation_state: "completed" },
{ capability: "document.ocr", version: 1, category: "DOCUMENT", purpose: "Local OCR", declared_stability: "experimental", operational_state: "not_deployed", resource_class: "MEDIUM", consumers: ["examplerag"], privacy_class: "restricted", evaluation_type: "ocr", evaluation_state: "not_evaluated" },
{ capability: "vision.embedding", version: 1, category: "VISION", purpose: "Visual retrieval", declared_stability: "experimental", operational_state: "not_deployed", resource_class: "HEAVY", consumers: ["examplevision"], privacy_class: "confidential", evaluation_type: "visual-retrieval", evaluation_state: "not_evaluated" },
{ capability: "speech.transcription", version: 1, category: "AUDIO", purpose: "Local transcription", declared_stability: "experimental", operational_state: "not_deployed", resource_class: "HEAVY", consumers: [], privacy_class: "restricted", evaluation_type: "asr", evaluation_state: "not_evaluated" },
];
if (url.endsWith("/api/v1/scheduler")) payload = [budget];
if (url.endsWith("/api/v1/deployment-candidates")) payload = [];
if (url.includes("/api/v1/gateway/requests")) payload = [{ request_id: "request-1", capability: "rag.embedding@1", client: "acceptance", status: "completed", cold: false, queue_time_ms: 1, total_latency_ms: 20, created_at: "2026-08-25T12:00:00Z" }];
if (url.endsWith("/api/v1/admin/production-approvals")) payload = [];
if (url.includes("/api/v1/admin/scheduler/placements")) payload = [];
if (url.endsWith("/api/v1/admin/scheduler/policy")) payload = { revision: "m10-v1", active: true, configuration: { lab_paused: false }, created_at: "2026-08-25T12:00:00Z" };
if (url.includes("/unload")) { options.calls?.push(url); payload = { unloaded: true }; }
if (url.endsWith("/api/v1/admin/service-clients") && init?.method !== "POST") payload = [];
if (url.endsWith("/api/v1/admin/service-clients") && init?.method === "POST") payload = { id: "client-1", name: "modelforge-m5-acceptance", status: "active", allowed_capabilities: ["rag.embedding@1"], requests_per_minute: 60, max_concurrent_requests: 1, credential_prefix: "mf_test", created_at: "2026-08-25T12:00:00Z", credential: "mf_test_one_time_secret" };
if (url.endsWith("/api/v1/capabilities/rag.embedding@1/invoke")) {
if (options.invokeError) { status = 429; payload = { error: { message: "rate limit exceeded", details: { failure_code: "RATE_LIMITED" } } }; }
else payload = { capability: "rag.embedding@1", dimension: 1024, normalized: true, embedding_space_id: "space-1", data: [Array(1024).fill(0.03125)], request_id: "request-2", execution: { cold: false, node: "GPU Node", residency: "warm", load_count: 1, timings: { gateway_ms: 1, queue_ms: 0, load_ms: 0, inference_ms: 12, total_ms: 14 } }, usage: { input_count: 1, input_tokens: 4 } };
}
return Promise.resolve(new Response(JSON.stringify(payload), { status }));
}));
}
afterEach(() => { clearOperatorCredential(); cleanup(); vi.unstubAllGlobals(); vi.restoreAllMocks(); });
describe("M5 capability operations UI", () => {
it("shows the healthy stable capability and warm residency", async () => {
mockServing(); setOperatorCredential("test-admin"); render(<CapabilityWorkspace role="admin" onError={vi.fn()} />);
expect(await screen.findByText("rag.embedding@1")).toBeInTheDocument();
fireEvent.click(screen.getByRole("button", { name: "Inspect rag.embedding@1" }));
fireEvent.click(screen.getByRole("button", { name: "Inspect deployment deployment-1" }));
expect(screen.getByText("healthy")).toBeInTheDocument();
expect(screen.getAllByText("warm").length).toBeGreaterThan(0);
expect(screen.getAllByText("requires_reindex").length).toBeGreaterThan(0);
});
it("shows unavailable honestly when promotion has not happened", async () => {
mockServing({ deployments: [] }); render(<CapabilityWorkspace onError={vi.fn()} />);
fireEvent.click(await screen.findByRole("button", { name: "Inspect rag.embedding@1" }));
expect(screen.getByText(/No deployment records exist/)).toBeInTheDocument();
});
it("renders real scheduler budget categories including external usage", async () => {
mockServing(); setOperatorCredential("test-admin"); render(<CapabilityWorkspace role="admin" onError={vi.fn()} />);
fireEvent.click(await screen.findByRole("tab", { name: "scheduler" }));
expect(screen.getByText(/GPU SCHEDULING COCKPIT · GPU Node/)).toBeInTheDocument();
expect(screen.getByText("External / unmanaged")).toBeInTheDocument();
expect(screen.getByText("Safety reserve")).toBeInTheDocument();
expect(screen.getByText("Schedulable free")).toBeInTheDocument();
});
it("shows a newly created credential exactly in the one-time result", async () => {
mockServing(); setOperatorCredential("test-admin"); render(<CapabilityWorkspace role="admin" onError={vi.fn()} />);
fireEvent.click(await screen.findByRole("tab", { name: "clients" }));
fireEvent.click(await screen.findByRole("button", { name: /Create one-time credential/ }));
expect(await screen.findByText("mf_test_one_time_secret")).toBeInTheDocument();
expect(screen.getByText(/Only its hash is stored/)).toBeInTheDocument();
});
it("invokes by capability without asking for a concrete model name", async () => {
mockServing(); setOperatorCredential("test-admin"); render(<CapabilityWorkspace role="admin" onError={vi.fn()} />);
fireEvent.click(await screen.findByRole("tab", { name: "playground" }));
expect(screen.queryByLabelText(/model name/i)).not.toBeInTheDocument();
expect(screen.getByRole("option", { name: "document.ocr@1" })).toBeInTheDocument();
expect(screen.getByRole("option", { name: "vision.embedding@1" })).toBeInTheDocument();
expect(screen.getByRole("option", { name: "speech.transcription@1" })).toBeInTheDocument();
fireEvent.change(screen.getByLabelText("Service credential"), { target: { value: "client-secret" } });
fireEvent.click(screen.getByRole("button", { name: "Invoke capability" }));
expect(await screen.findByText("1 × 1024 finite values")).toBeInTheDocument();
});
it("surfaces typed gateway failures", async () => {
mockServing({ invokeError: true }); render(<CapabilityWorkspace onError={vi.fn()} />);
fireEvent.click(await screen.findByRole("tab", { name: "playground" }));
fireEvent.change(screen.getByLabelText("Service credential"), { target: { value: "client-secret" } });
fireEvent.click(screen.getByRole("button", { name: "Invoke capability" }));
expect(await screen.findByText("rate limit exceeded (RATE_LIMITED)")).toBeInTheDocument();
});
});
describe("Capability state read semantics", () => {
it("shows a typed initial failure and retries instead of displaying an empty estate", async () => {
mockServing();
const normalFetch = fetch;
let failFirstRead = true;
vi.stubGlobal("fetch", vi.fn((input: RequestInfo | URL, init?: RequestInit) => {
if (failFirstRead && String(input).endsWith("/api/v1/capability-estate")) {
failFirstRead = false;
return Promise.resolve(new Response(JSON.stringify({ error: {
code: "SERVICE_UNAVAILABLE", message: "Capability estate read failed", correlation_id: "corr-capability-123",
details: { failure_code: "CAPABILITY_READ_UNAVAILABLE" },
} }), { status: 503 }));
}
return normalFetch(input, init);
}));
const onError = vi.fn();
render(<CapabilityWorkspace onError={onError} />);
expect(await screen.findByRole("alert")).toHaveTextContent("Capability serving state is unavailable");
expect(screen.getByText(/No authoritative snapshot was loaded/)).toBeInTheDocument();
expect(screen.getByText("CAPABILITY_READ_UNAVAILABLE")).toBeInTheDocument();
expect(screen.getByText("corr-capability-123")).toBeInTheDocument();
expect(screen.getByText("Yes")).toBeInTheDocument();
expect(screen.queryByText(/0 declared contracts/)).not.toBeInTheDocument();
expect(screen.queryByText(/0 deployment records/)).not.toBeInTheDocument();
expect(onError).not.toHaveBeenCalled();
fireEvent.click(screen.getByRole("button", { name: "Retry capability state" }));
expect(await screen.findByRole("heading", { name: "1 declared contracts" })).toBeInTheDocument();
expect(screen.getByText("1 deployment records")).toBeInTheDocument();
});
it("discloses an offline polling failure with its stale snapshot and recovers on retry", async () => {
mockServing();
const pollCallbacks: Array<() => void> = [];
vi.spyOn(window, "setInterval").mockImplementation(((callback: TimerHandler) => {
if (typeof callback === "function") pollCallbacks.push(callback as () => void);
return 1;
}) as typeof window.setInterval);
vi.spyOn(window, "clearInterval").mockImplementation(() => undefined);
const onError = vi.fn();
render(<CapabilityWorkspace onError={onError} />);
expect(await screen.findByRole("heading", { name: "1 declared contracts" })).toBeInTheDocument();
expect(pollCallbacks.length).toBeGreaterThan(0);
const normalFetch = fetch;
let failNextRead = true;
let offlineRequestAttempted = false;
vi.stubGlobal("fetch", vi.fn((input: RequestInfo | URL, init?: RequestInit) => {
if (failNextRead && String(input).endsWith("/api/v1/capability-estate")) {
failNextRead = false;
offlineRequestAttempted = true;
return Promise.reject(new TypeError("Failed to fetch"));
}
return normalFetch(input, init);
}));
await act(async () => { pollCallbacks.forEach(callback => callback()); });
expect(offlineRequestAttempted).toBe(true);
expect(await screen.findByText("Capability data may be out of date")).toBeInTheDocument();
expect(screen.getByText("OFFLINE")).toBeInTheDocument();
expect(screen.getByText("NETWORK_UNAVAILABLE")).toBeInTheDocument();
expect(screen.getByText("Retryable").parentElement).toHaveTextContent("Yes");
expect(screen.getByRole("heading", { name: "1 declared contracts" })).toBeInTheDocument();
expect(screen.getByText("1 deployment records")).toBeInTheDocument();
expect(onError).not.toHaveBeenCalled();
fireEvent.click(screen.getByRole("button", { name: "Retry capability state" }));
await waitFor(() => expect(screen.queryByText("Capability data may be out of date")).not.toBeInTheDocument());
expect(screen.getByRole("heading", { name: "1 declared contracts" })).toBeInTheDocument();
});
it("keeps manual refresh inside the public boundary when an admin-role session is inactive", async () => {
mockServing();
setOperatorCredential("viewer-session");
const normalFetch = fetch;
const requestedUrls: string[] = [];
vi.stubGlobal("fetch", vi.fn((input: RequestInfo | URL, init?: RequestInit) => {
requestedUrls.push(String(input));
return normalFetch(input, init);
}));
render(<CapabilityWorkspace role="viewer" onError={vi.fn()} />);
expect(await screen.findByRole("heading", { name: "1 declared contracts" })).toBeInTheDocument();
fireEvent.click(screen.getByRole("button", { name: "Refresh capability state" }));
await waitFor(() => expect(requestedUrls.filter(url => url.endsWith("/api/v1/capability-deployments")).length).toBe(2));
expect(requestedUrls.some(url => url.includes("/api/v1/admin/"))).toBe(false);
});
});
describe("M18 closure · capability tabs and guarded residency unload", () => {
async function openScheduler(calls: string[]) {
mockServing({ calls });
setOperatorCredential("test-admin"); render(<CapabilityWorkspace role="admin" onError={vi.fn()} />);
fireEvent.click(await screen.findByRole("tab", { name: "scheduler" }));
return await screen.findByRole("button", { name: "Unload idle" });
}
it("pairs each capability tab with the panel it controls", async () => {
mockServing(); setOperatorCredential("test-admin"); render(<CapabilityWorkspace role="admin" onError={vi.fn()} />);
await screen.findByRole("tablist", { name: "Capability operations" });
const selected = screen.getByRole("tab", { selected: true });
const panel = screen.getByRole("tabpanel");
expect(selected.getAttribute("aria-controls")).toBe(panel.getAttribute("id"));
expect(panel.getAttribute("aria-labelledby")).toBe(selected.getAttribute("id"));
const ids = screen.getAllByRole("tab").map((tab) => tab.getAttribute("id"));
expect(new Set(ids).size).toBe(ids.length);
});
it("guards residency unload with the console safety dialog instead of a native confirm", async () => {
const confirmSpy = vi.spyOn(window, "confirm");
const calls: string[] = [];
fireEvent.click(await openScheduler(calls));
const dialog = await screen.findByRole("alertdialog", { name: "Unload idle residency?" });
expect(dialog).toBeInTheDocument();
// The native dialog is gone for good: it cannot carry this impact evidence.
expect(confirmSpy).not.toHaveBeenCalled();
expect(screen.getByText("rag.embedding@1")).toBeInTheDocument();
expect(screen.getByText("Resident VRAM released")).toBeInTheDocument();
expect(calls).toHaveLength(0);
confirmSpy.mockRestore();
});
it("performs no mutation when the guarded unload is cancelled", async () => {
const calls: string[] = [];
fireEvent.click(await openScheduler(calls));
await screen.findByRole("alertdialog", { name: "Unload idle residency?" });
fireEvent.click(screen.getByRole("button", { name: "Cancel" }));
await waitFor(() => expect(screen.queryByRole("alertdialog")).not.toBeInTheDocument());
expect(calls).toHaveLength(0);
});
it("requires acknowledgement and then unloads exactly once", async () => {
const calls: string[] = [];
fireEvent.click(await openScheduler(calls));
await screen.findByRole("alertdialog", { name: "Unload idle residency?" });
const confirm = screen.getByRole("button", { name: "Unload residency" });
expect(confirm).toBeDisabled();
fireEvent.click(screen.getByRole("checkbox", { name: /cold-load cost/ }));
expect(confirm).toBeEnabled();
fireEvent.click(confirm);
fireEvent.click(confirm);
expect(await screen.findByRole("status")).toHaveTextContent(/was unloaded/);
// Exactly one mutation, even though confirm was clicked twice.
expect(calls).toHaveLength(1);
});
it("dismisses the guarded unload with Escape", async () => {
const calls: string[] = [];
fireEvent.click(await openScheduler(calls));
await screen.findByRole("alertdialog", { name: "Unload idle residency?" });
fireEvent.keyDown(window, { key: "Escape" });
await waitFor(() => expect(screen.queryByRole("alertdialog")).not.toBeInTheDocument());
expect(calls).toHaveLength(0);
});
});
describe("Capability administrative role boundary", () => {
it.each(["viewer", "operator"] as const)("does not fetch admin data or offer another credential for %s", async role => {
mockServing(); setOperatorCredential("test-read-session"); render(<CapabilityWorkspace role={role} onError={vi.fn()} />);
fireEvent.click(await screen.findByRole("tab", { name: "promotion" }));
expect(screen.getByText(/Read-only access/)).toBeInTheDocument();
expect(screen.queryByLabelText("Operator API key")).not.toBeInTheDocument();
expect(screen.queryByRole("button", { name: /Record reviewed/ })).not.toBeInTheDocument();
expect(vi.mocked(fetch).mock.calls.some(([url]) => String(url).includes("/admin/"))).toBe(false);
});
it("keeps a locked admin session read-only", async () => {
mockServing(); render(<CapabilityWorkspace role="admin" onError={vi.fn()} />);
fireEvent.click(await screen.findByRole("tab", { name: "promotion" }));
expect(screen.getByText(/Read-only access/)).toBeInTheDocument();
expect(vi.mocked(fetch).mock.calls.some(([url]) => String(url).includes("/admin/"))).toBe(false);
});
it("renders nullable embedding metadata without blocking access to promotion", async () => {
mockServing({ deployments: [{ ...deployment, embedding_space: null }] }); setOperatorCredential("test-admin"); render(<CapabilityWorkspace role="admin" onError={vi.fn()} />);
fireEvent.click(await screen.findByRole("tab", { name: "promotion" }));
expect(screen.getByRole("heading", { name: "Promotion evidence" })).toBeInTheDocument();
});
});
describe("Capability declaration refresh ordering", () => {
async function pendingRefreshes() {
mockServing();
const onError = vi.fn();
render(<CapabilityWorkspace onError={onError} />);
fireEvent.click(await screen.findByRole("button", { name: "Inspect rag.embedding@1" }));
await screen.findByRole("region", { name: "Details for rag.embedding@1" });
const originalFetch = fetch;
const pending: Array<(response: Response) => void> = [];
vi.stubGlobal("fetch", vi.fn((input: RequestInfo | URL, init?: RequestInit) => {
if (String(input).endsWith("/api/v1/capabilities")) return new Promise<Response>(resolve => pending.push(resolve));
return originalFetch(input, init);
}));
const refresh = () => fireEvent.click(screen.getByRole("button", { name: "Refresh capability state" }));
const finish = async (index: number, success: boolean) => {
await act(async () => {
const response = success ? await originalFetch("/api/v1/capabilities") : new Response(JSON.stringify({ detail: "Declarations unavailable" }), { status: 503 });
pending[index](response);
});
};
return { refresh, finish, onError };
}
it("keeps the last good snapshot disclosed after a newer refresh failed", async () => {
const { refresh, finish } = await pendingRefreshes();
refresh(); refresh();
await finish(1, false);
expect(screen.getByText("Capability data may be out of date")).toBeInTheDocument();
expect(screen.getByRole("region", { name: "Details for rag.embedding@1" })).toBeInTheDocument();
await finish(0, true);
expect(screen.getByText("Capability data may be out of date")).toBeInTheDocument();
expect(screen.getByRole("region", { name: "Details for rag.embedding@1" })).toBeInTheDocument();
});
it("does not clear newer declarations or report an older refresh failure", async () => {
const { refresh, finish, onError } = await pendingRefreshes();
refresh(); refresh();
await finish(1, true);
onError.mockClear();
await finish(0, false);
expect(screen.getByRole("region", { name: "Details for rag.embedding@1" })).toBeInTheDocument();
expect(onError).not.toHaveBeenCalled();
});
it("ignores a pending contract failure after the operator session changes", async () => {
const { refresh, finish, onError } = await pendingRefreshes();
refresh();
setOperatorCredential("replacement-viewer-session");
onError.mockClear();
await finish(0, false);
expect(onError).not.toHaveBeenCalled();
expect(screen.getByRole("region", { name: "Details for rag.embedding@1" })).toBeInTheDocument();
});
});