71 lines
4.4 KiB
TypeScript
71 lines
4.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import type { GamePluginResponse } from "../api/types";
|
|
import { normalizeScumRouteKey, resolveScumOperationsPageContract } from "./scumOperations";
|
|
|
|
const plugin = {
|
|
id: "game.scum",
|
|
pages: [{
|
|
key: "files-config",
|
|
title: "文件与配置",
|
|
path: "/files-config",
|
|
permissions: ["server.game-client.read", "server.game-client.command", "server.remote.access", "unknown.permission"],
|
|
bridgeActions: ["server.instances.read", "logs.query", "remote.access.request", "unknown.action"]
|
|
}],
|
|
gameClientBridge: {
|
|
commands: [
|
|
{ type: "announcement.send", title: "Send announcement", permission: "server.game-client.command", approvalLevel: "operator", payloadSchemaRef: "schemas/bridge/announcement.json", timeoutSeconds: 30, maxPayloadBytes: 4096 },
|
|
{ type: "maintenance.prepare", title: "Prepare maintenance", permission: "server.game-client.maintenance", approvalLevel: "platform-admin", payloadSchemaRef: "schemas/bridge/maintenance.json", timeoutSeconds: 60, maxPayloadBytes: 4096 }
|
|
],
|
|
snapshots: [
|
|
{ type: "companion.health", schemaVersion: "1", schemaRef: "schemas/bridge/health.json", keepForSeconds: 3600, maxRecords: 24 },
|
|
{ type: "players", schemaVersion: "1", schemaRef: "schemas/bridge/players.json", keepForSeconds: 3600, maxRecords: 24 }
|
|
],
|
|
queryTemplates: [
|
|
{ key: "scum.player.search", title: "Search player", permission: "server.game-client.read", engine: "sqlite", transportKey: "sqlite-db", targetKey: "db/sqlite", parameterSchemaRef: "schemas/bridge/player-search.parameters.json", resultSchemaRef: "schemas/bridge/player-search.result.json", maxRows: 50, timeoutSeconds: 10 }
|
|
],
|
|
commandRetentionSeconds: 86400,
|
|
maxCommands: 1000,
|
|
pages: [{ pageKey: "files-config", commandTypes: ["announcement.send"], snapshotTypes: ["companion.health"], queryTemplateKeys: ["scum.player.search"] }]
|
|
},
|
|
runtimeProfiles: {
|
|
logSources: [{ key: "scum-chat-events", kind: "file.tail", streamKey: "scum.chat", retentionDays: 30 }],
|
|
logEvents: [{ key: "scum-chat", title: "SCUM chat", sourceKey: "scum-chat-events", eventType: "scum.chat", permission: "server.logs.read", schemaRef: "schemas/log-events/chat.json", retentionDays: 30, severity: "info" }]
|
|
},
|
|
productionLifecycle: { operations: ["install", "enable", "disable", "upgrade", "rollback", "retire", "dependency-check"], dependencyPolicy: "required", approvalRequired: ["disable", "rollback", "retire"] }
|
|
} satisfies Pick<GamePluginResponse, "id" | "pages" | "gameClientBridge" | "runtimeProfiles" | "productionLifecycle">;
|
|
|
|
describe("SCUM operations page contract", () => {
|
|
it("projects only declarations owned by the plugin operations page", () => {
|
|
const resolution = resolveScumOperationsPageContract(plugin, "server-1");
|
|
expect(resolution).toMatchObject({
|
|
available: true,
|
|
contract: {
|
|
pluginId: "game.scum",
|
|
routeKey: "files-config",
|
|
serverInstanceId: "server-1",
|
|
permissions: ["server.game-client.read", "server.game-client.command", "server.remote.access"],
|
|
bridgeActions: ["server.instances.read", "logs.query", "remote.access.request"],
|
|
commands: [{ type: "announcement.send" }],
|
|
snapshots: [{ type: "companion.health" }],
|
|
queryTemplates: [{ key: "scum.player.search", engine: "sqlite" }],
|
|
logEvents: [{ eventType: "scum.chat" }],
|
|
productionLifecycle: { dependencyPolicy: "required" }
|
|
}
|
|
});
|
|
expect(JSON.stringify(resolution)).not.toMatch(/sqlText|hostPath|sessionToken|componentKey|credential|socket/i);
|
|
});
|
|
|
|
it("reports declaration and server-context availability without inventing fallback semantics", () => {
|
|
expect(resolveScumOperationsPageContract({ ...plugin, id: "game.other" }, "server-1")).toMatchObject({ available: false });
|
|
expect(resolveScumOperationsPageContract(plugin, "")).toMatchObject({ available: false, reason: "缺少服务器实例上下文。" });
|
|
expect(resolveScumOperationsPageContract({ ...plugin, gameClientBridge: undefined }, "server-1")).toMatchObject({ available: false });
|
|
});
|
|
|
|
it("migrates only legacy SCUM page keys to the files-and-config workbench", () => {
|
|
expect(normalizeScumRouteKey("game.scum", "overview")).toBe("files-config");
|
|
expect(normalizeScumRouteKey("game.scum", "logs")).toBe("files-config");
|
|
expect(normalizeScumRouteKey("game.other", "logs")).toBe("logs");
|
|
});
|
|
});
|