import { afterEach, describe, expect, it, vi } from "vitest"; import { PlatformApiClient } from "./client"; const lifecycle = { id: "installation-1", serverInstanceId: "server-1", pluginId: "game.scum", profileKey: "scum-client-manager", targetOs: "windows", targetArch: "amd64", status: "available", phase: "artifact available", desiredVersion: "1.0.0", desiredRevision: "rev-1", desiredArtifactId: "artifact-1", keyGeneration: 1, deploymentGeneration: 0, health: "unknown", healthReason: "component is not installed", retryable: false, requiresRedeploy: false, updatedAt: "2026-07-18T08:00:00Z", distribution: { id: "distribution-1", artifactId: "artifact-1", sourceRevision: "rev-1", targetOs: "windows", targetArch: "amd64", checksum: `sha256:${"a".repeat(64)}`, keyGeneration: 1, status: "available" }, actions: [{ operation: "deploy", available: true }, { operation: "uninstall", available: false, reason: "not installed" }] }; describe("PlatformApiClient Client Manager lifecycle", () => { afterEach(() => vi.unstubAllGlobals()); it("uses typed Platform lifecycle routes and preserves action bodies", async () => { const calls: Array<{ url: string; method: string; body?: unknown }> = []; vi.stubGlobal("fetch", vi.fn(async (input: RequestInfo | URL, init?: RequestInit) => { const url = String(input); calls.push({ url, method: init?.method ?? "GET", body: init?.body ? JSON.parse(String(init.body)) : undefined }); return new Response(JSON.stringify(url.endsWith("/client-managers") && (init?.method ?? "GET") === "GET" ? { items: [lifecycle], count: 1 } : lifecycle), { status: 200, headers: { "Content-Type": "application/json" } }); })); const client = new PlatformApiClient("/api/v1", () => "session-token"); await expect(client.listClientManagerLifecycles("server-1")).resolves.toMatchObject({ count: 1 }); await expect(client.getClientManagerLifecycle("server-1", "scum-client-manager")).resolves.toMatchObject({ profileKey: "scum-client-manager" }); await client.deployClientManager("server-1", { profileKey: "scum-client-manager", distributionId: "distribution-1", expectedDeploymentGeneration: 0, idempotencyKey: "deploy-1" }); await client.controlClientManager("server-1", { profileKey: "scum-client-manager", operation: "start", expectedDeploymentGeneration: 1, idempotencyKey: "start-1" }); await client.updateClientManager("server-1", { profileKey: "scum-client-manager", distributionId: "distribution-2", expectedDeploymentGeneration: 1, approved: true, idempotencyKey: "update-1" }); await client.retryClientManagerLifecycle("server-1", { profileKey: "scum-client-manager", expectedDeploymentGeneration: 2, idempotencyKey: "retry-1" }); await client.revokeClientManagerSession("server-1", { profileKey: "scum-client-manager", reason: "operator revoked component session" }); await client.uninstallClientManager("server-1", { profileKey: "scum-client-manager", expectedDeploymentGeneration: 2, confirmed: true, idempotencyKey: "uninstall-1" }); expect(calls.map((call) => `${call.method} ${call.url}`)).toEqual([ "GET /api/v1/server-instances/server-1/client-managers", "GET /api/v1/server-instances/server-1/client-managers/scum-client-manager", "POST /api/v1/server-instances/server-1/client-managers/deploy", "POST /api/v1/server-instances/server-1/client-managers/control", "POST /api/v1/server-instances/server-1/client-managers/update", "POST /api/v1/server-instances/server-1/client-managers/retry", "POST /api/v1/server-instances/server-1/client-managers/revoke-session", "POST /api/v1/server-instances/server-1/client-managers/uninstall" ]); expect(calls[4]?.body).toMatchObject({ approved: true, distributionId: "distribution-2" }); expect(calls[7]?.body).toMatchObject({ confirmed: true }); }); });