Complete platform management workflows
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { PlatformApiClient, setPlatformApiSessionToken } from "./client";
|
||||
import type { AiProviderResponse, GamePluginResponse, JobResponse, MarketplacePluginResponse, RunEndpointResponse, ServerInstanceResponse } from "./types";
|
||||
import type { AiProviderResponse, ArtifactDownloadReferenceResponse, GamePluginResponse, JobResponse, MarketplacePluginResponse, RunEndpointResponse, ServerInstanceResponse } from "./types";
|
||||
|
||||
const provider: AiProviderResponse = {
|
||||
id: "ai.openai",
|
||||
@@ -105,6 +105,37 @@ const artifact = {
|
||||
updatedAt: "2026-07-03T00:00:00Z"
|
||||
};
|
||||
|
||||
const runtimeActions = {
|
||||
serverInstanceId: server.id,
|
||||
pluginId: plugin.id,
|
||||
runEndpointId: endpoint.id,
|
||||
runStatus: "online",
|
||||
actions: [
|
||||
{ key: "generate-run", label: "Generate run", available: true },
|
||||
{ key: "download-run", label: "Download run", available: true },
|
||||
{ key: "push-run-update", label: "Push run update", available: true },
|
||||
{ key: "generate-client-manager", label: "Generate client manager", available: true },
|
||||
{ key: "dependencies-check", label: "Check dependencies", available: true },
|
||||
{ key: "historical-logs", label: "Historical logs", available: true }
|
||||
]
|
||||
};
|
||||
|
||||
const runtimeDownload: ArtifactDownloadReferenceResponse = {
|
||||
artifactId: "artifact-run-1",
|
||||
ownerKind: "server-instance",
|
||||
ownerId: server.id,
|
||||
filename: "run-linux-amd64.zip",
|
||||
contentType: "application/zip",
|
||||
sizeBytes: 128,
|
||||
checksum: "sha256:runchecksum",
|
||||
state: "available",
|
||||
downloadUrl: "/api/v1/artifacts/artifact-run-1/content",
|
||||
expiresAt: "2026-07-03T00:15:00Z",
|
||||
rangeSupported: true,
|
||||
chunkSizeBytes: 1048576,
|
||||
storageBehavior: "platform-memory-transfer-session"
|
||||
};
|
||||
|
||||
describe("PlatformApiClient AI providers", () => {
|
||||
afterEach(() => {
|
||||
setPlatformApiSessionToken(null);
|
||||
@@ -160,6 +191,13 @@ describe("PlatformApiClient AI providers", () => {
|
||||
if (url.endsWith("/api/v1/server-instances") && (!init?.method || init.method === "GET")) {
|
||||
return jsonResponse({ items: [server], count: 1 });
|
||||
}
|
||||
if (url.endsWith("/api/v1/server-instances/server-1") && init?.method === "PUT") {
|
||||
expect(JSON.parse(String(init.body))).toEqual({ name: "Example Survival Renamed" });
|
||||
return jsonResponse({ ...server, name: "Example Survival Renamed" });
|
||||
}
|
||||
if (url.endsWith("/api/v1/server-instances/server-1") && init?.method === "DELETE") {
|
||||
return new Response(null, { status: 204 });
|
||||
}
|
||||
if (url.endsWith("/api/v1/metrics/platform")) {
|
||||
return jsonResponse({ cpuPercent: 28, memoryPercent: 42, diskPercent: 19, source: "platform-derived", collectedAt: "2026-07-03T00:00:00Z" });
|
||||
}
|
||||
@@ -314,6 +352,122 @@ describe("PlatformApiClient AI providers", () => {
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/administrators/user-2") && init?.method === "DELETE") {
|
||||
return jsonResponse({ ...server, adminUserIds: [] });
|
||||
}
|
||||
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/runtime/actions")) {
|
||||
return jsonResponse(runtimeActions);
|
||||
}
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/run/generate") && init?.method === "POST") {
|
||||
expect(JSON.parse(String(init.body))).toEqual({ targetOs: "linux", targetArch: "amd64", idempotencyKey: "idem-run-generate" });
|
||||
return jsonResponse({
|
||||
id: "run-dist-1",
|
||||
serverInstanceId: server.id,
|
||||
pluginId: plugin.id,
|
||||
runEndpointId: endpoint.id,
|
||||
targetOs: "linux",
|
||||
targetArch: "amd64",
|
||||
packageFormat: "zip",
|
||||
artifactId: "artifact-run-1",
|
||||
checksum: "sha256:runchecksum",
|
||||
keyGeneration: 1,
|
||||
secretRef: "secret://runtime-keys/server-1/run/current",
|
||||
status: "available",
|
||||
createdAt: "2026-07-03T00:00:00Z",
|
||||
updatedAt: "2026-07-03T00:00:00Z"
|
||||
});
|
||||
}
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/run/download") && init?.method === "POST") {
|
||||
return jsonResponse(runtimeDownload);
|
||||
}
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/run/key/reset") && init?.method === "POST") {
|
||||
return jsonResponse({
|
||||
id: "runtime-key-server-1-run-2",
|
||||
serverInstanceId: server.id,
|
||||
componentKind: "run",
|
||||
secretRef: "secret://runtime-keys/server-1/run/current",
|
||||
fingerprint: "abc123def456",
|
||||
generation: 2,
|
||||
status: "active",
|
||||
createdAt: "2026-07-03T00:00:00Z",
|
||||
updatedAt: "2026-07-03T00:00:00Z"
|
||||
});
|
||||
}
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/run/update") && init?.method === "POST") {
|
||||
expect(JSON.parse(String(init.body))).toEqual({ artifactId: "artifact-run-1", checksum: "sha256:runchecksum", idempotencyKey: "idem-run-update" });
|
||||
return jsonResponse({
|
||||
id: "run-update-1",
|
||||
serverInstanceId: server.id,
|
||||
runEndpointId: endpoint.id,
|
||||
artifactId: "artifact-run-1",
|
||||
checksum: "sha256:runchecksum",
|
||||
jobId: "job-run-update",
|
||||
idempotencyKey: "idem-run-update",
|
||||
status: "queued",
|
||||
createdAt: "2026-07-03T00:00:00Z",
|
||||
updatedAt: "2026-07-03T00:00:00Z"
|
||||
});
|
||||
}
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/client-managers/generate") && init?.method === "POST") {
|
||||
expect(JSON.parse(String(init.body))).toEqual({
|
||||
profileKey: "scum-client-manager",
|
||||
targetOs: "windows",
|
||||
targetArch: "amd64",
|
||||
repositoryUrl: "https://github.com/F88888/scum_client.git",
|
||||
sourceRevision: "main",
|
||||
idempotencyKey: "idem-client-generate"
|
||||
});
|
||||
return jsonResponse({
|
||||
id: "client-dist-1",
|
||||
serverInstanceId: server.id,
|
||||
pluginId: plugin.id,
|
||||
profileKey: "scum-client-manager",
|
||||
targetOs: "windows",
|
||||
targetArch: "amd64",
|
||||
repositoryUrl: "https://github.com/F88888/scum_client.git",
|
||||
sourceRevision: "main",
|
||||
buildJobId: "client-build-1",
|
||||
artifactId: "artifact-client-1",
|
||||
checksum: "sha256:clientchecksum",
|
||||
keyGeneration: 1,
|
||||
secretRef: "secret://runtime-keys/server-1/client-manager/scum-client-manager/current",
|
||||
status: "available",
|
||||
createdAt: "2026-07-03T00:00:00Z",
|
||||
updatedAt: "2026-07-03T00:00:00Z"
|
||||
});
|
||||
}
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/client-managers/download") && init?.method === "POST") {
|
||||
expect(JSON.parse(String(init.body))).toEqual({ profileKey: "scum-client-manager" });
|
||||
return jsonResponse({ ...runtimeDownload, artifactId: "artifact-client-1", filename: "scum-client-manager.exe" });
|
||||
}
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/client-managers/key/reset") && init?.method === "POST") {
|
||||
expect(JSON.parse(String(init.body))).toEqual({ componentKind: "client-manager", componentKey: "scum-client-manager" });
|
||||
return jsonResponse({
|
||||
id: "runtime-key-server-1-client-2",
|
||||
serverInstanceId: server.id,
|
||||
componentKind: "client-manager",
|
||||
componentKey: "scum-client-manager",
|
||||
secretRef: "secret://runtime-keys/server-1/client-manager/scum-client-manager/current",
|
||||
fingerprint: "def456abc123",
|
||||
generation: 2,
|
||||
status: "active",
|
||||
createdAt: "2026-07-03T00:00:00Z",
|
||||
updatedAt: "2026-07-03T00:00:00Z"
|
||||
});
|
||||
}
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/dependencies/check") && init?.method === "POST") {
|
||||
expect(JSON.parse(String(init.body))).toEqual({ probeKey: "java-21", idempotencyKey: "idem-dep-check" });
|
||||
return jsonResponse({ ...job, id: "job-dep-check", capability: "dependencies.check", targetKey: "dependencies/java-21" });
|
||||
}
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/dependencies/install") && init?.method === "POST") {
|
||||
expect(JSON.parse(String(init.body))).toEqual({ probeKey: "java-21", installPlanKey: "install-java-linux", idempotencyKey: "idem-dep-install" });
|
||||
return jsonResponse({ ...job, id: "job-dep-install", capability: "dependencies.install", targetKey: "dependencies/install/install-java-linux" });
|
||||
}
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/logs/live")) {
|
||||
return jsonResponse({ items: [], count: 0 });
|
||||
}
|
||||
if (url.endsWith("/api/v1/server-instances/server-1/logs/backfill") && init?.method === "POST") {
|
||||
expect(JSON.parse(String(init.body))).toEqual({ sourceKey: "latest-log", checkpointRef: "artifact://logs/checkpoint/1", limit: 200, idempotencyKey: "idem-log-backfill" });
|
||||
return jsonResponse({ ...job, id: "job-log-backfill", capability: "logs.backfill", targetKey: "logs/latest-log", inputRef: "artifact://logs/checkpoint/1" });
|
||||
}
|
||||
if (url.endsWith("/api/v1/plugin-bridge/authorize") && init?.method === "POST") {
|
||||
return jsonResponse({
|
||||
pluginId: plugin.id,
|
||||
@@ -371,6 +525,8 @@ describe("PlatformApiClient AI providers", () => {
|
||||
await expect(client.health()).resolves.toMatchObject({ status: "ok" });
|
||||
await expect(client.listGamePlugins()).resolves.toMatchObject({ count: 1 });
|
||||
await expect(client.listServerInstances()).resolves.toMatchObject({ count: 1 });
|
||||
await expect(client.updateServerInstance(server.id, { name: "Example Survival Renamed" })).resolves.toMatchObject({ name: "Example Survival Renamed" });
|
||||
await expect(client.archiveServerInstance(server.id)).resolves.toBeUndefined();
|
||||
await expect(client.getPlatformResourceUsage()).resolves.toMatchObject({ source: "platform-derived", cpuPercent: 28 });
|
||||
await expect(client.listServerMetrics()).resolves.toMatchObject({ count: 1, items: [{ serverInstanceId: server.id, online: true }] });
|
||||
await expect(client.getServerConfig(server.id)).resolves.toMatchObject({ content: "server.name=Example Survival #1\n" });
|
||||
@@ -398,6 +554,41 @@ describe("PlatformApiClient AI providers", () => {
|
||||
await expect(client.listServerAdministratorCandidates(server.id)).resolves.toMatchObject({ count: 1 });
|
||||
await expect(client.addServerAdministrator(server.id, { userId: "user-2" })).resolves.toMatchObject({ adminUserIds: ["user-admin-1", "user-2"] });
|
||||
await expect(client.removeServerAdministrator(server.id, "user-2")).resolves.toMatchObject({ adminUserIds: [] });
|
||||
|
||||
const runtime = await client.getServerRuntimeActions(server.id);
|
||||
expect(runtime.runStatus).toBe("online");
|
||||
expect(runtime.actions.some((action) => action.key === "generate-run" && action.available)).toBe(true);
|
||||
await expect(client.generateRunDistribution(server.id, { targetOs: "linux", targetArch: "amd64", idempotencyKey: "idem-run-generate" })).resolves.toMatchObject({
|
||||
artifactId: "artifact-run-1",
|
||||
keyGeneration: 1,
|
||||
secretRef: "secret://runtime-keys/server-1/run/current"
|
||||
});
|
||||
await expect(client.downloadLatestRunDistribution(server.id)).resolves.toMatchObject({ artifactId: "artifact-run-1", rangeSupported: true });
|
||||
await expect(client.resetRunKey(server.id)).resolves.toMatchObject({ componentKind: "run", generation: 2 });
|
||||
await expect(client.pushRunUpdate(server.id, { artifactId: "artifact-run-1", checksum: "sha256:runchecksum", idempotencyKey: "idem-run-update" })).resolves.toMatchObject({
|
||||
jobId: "job-run-update",
|
||||
status: "queued"
|
||||
});
|
||||
await expect(
|
||||
client.generateClientManager(server.id, {
|
||||
profileKey: "scum-client-manager",
|
||||
targetOs: "windows",
|
||||
targetArch: "amd64",
|
||||
repositoryUrl: "https://github.com/F88888/scum_client.git",
|
||||
sourceRevision: "main",
|
||||
idempotencyKey: "idem-client-generate"
|
||||
})
|
||||
).resolves.toMatchObject({ artifactId: "artifact-client-1", profileKey: "scum-client-manager" });
|
||||
await expect(client.downloadLatestClientManager(server.id, { profileKey: "scum-client-manager" })).resolves.toMatchObject({ artifactId: "artifact-client-1" });
|
||||
await expect(client.resetClientManagerKey(server.id, { componentKind: "client-manager", componentKey: "scum-client-manager" })).resolves.toMatchObject({ generation: 2 });
|
||||
await expect(client.checkDependencies(server.id, { probeKey: "java-21", idempotencyKey: "idem-dep-check" })).resolves.toMatchObject({ capability: "dependencies.check" });
|
||||
await expect(client.installDependencies(server.id, { probeKey: "java-21", installPlanKey: "install-java-linux", idempotencyKey: "idem-dep-install" })).resolves.toMatchObject({
|
||||
capability: "dependencies.install"
|
||||
});
|
||||
await expect(client.listServerLiveLogs(server.id)).resolves.toMatchObject({ count: 0 });
|
||||
await expect(client.requestLogBackfill(server.id, { sourceKey: "latest-log", checkpointRef: "artifact://logs/checkpoint/1", limit: 200, idempotencyKey: "idem-log-backfill" })).resolves.toMatchObject({
|
||||
capability: "logs.backfill"
|
||||
});
|
||||
await expect(client.authorizePluginBridge({ pluginId: plugin.id, routeKey: "logs", action: "logs.query" })).resolves.toMatchObject({
|
||||
allowed: true
|
||||
});
|
||||
@@ -408,7 +599,7 @@ describe("PlatformApiClient AI providers", () => {
|
||||
client.invokeAI({ requestId: "ai-1", serverInstanceId: server.id, purpose: "config.suggest", prompt: "Tune PVP safely", currentConfig: "server.name=Example Survival #1\n" })
|
||||
).resolves.toMatchObject({ status: "ok", usage: { mocked: true }, configRecommendation: { diffSummary: "review required" } });
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledTimes(24);
|
||||
expect(fetchMock).toHaveBeenCalledTimes(38);
|
||||
});
|
||||
|
||||
it("calls plugin marketplace endpoints with filter and state contracts", async () => {
|
||||
|
||||
Reference in New Issue
Block a user