Files
browser/platform_web/pages/PluginPageHostPage.test.tsx
T
2026-07-20 16:42:33 +08:00

92 lines
4.3 KiB
TypeScript

import { renderToStaticMarkup } from "react-dom/server";
import { describe, expect, it } from "vitest";
import type { GamePluginResponse } from "../api/types";
import type { PageComponentProps } from "../contracts/page";
import { capabilitiesForRoles } from "../contracts/workspace";
import type { OperationTracker } from "../stores/operations";
import { PluginPageHostPage } from "./PluginPageHostPage";
const operations: OperationTracker = {
operations: [],
begin: () => "operation-test",
update: () => undefined,
succeed: () => undefined,
fail: () => undefined,
isPending: () => false
};
const plugin: GamePluginResponse = {
id: "game.scum",
name: "SCUM Server",
version: "1.0.0",
serverType: "scum",
serverDisplayName: "SCUM Server",
manifestRef: "artifact://manifests/game.scum/1.0.0",
createFormSchemaRef: "schemas/create-form.schema.json",
requiredRunCapabilities: [],
declaredPermissions: ["server.read", "server.logs.read", "server.remote.access", "server.game-client.read", "server.game-client.command"],
permissions: { ai: false, logs: true, files: false, jobs: true, artifacts: false, remoteAccess: true },
lifecycleActions: {},
bridgeActions: ["server.instances.read", "logs.query", "remote.access.request"],
pages: [{
key: "operations",
title: "SCUM 运维",
path: "/operations",
permissions: ["server.game-client.read", "server.game-client.command", "server.logs.read", "server.remote.access"],
bridgeActions: ["server.instances.read", "logs.query", "remote.access.request"]
}],
tags: ["scum"],
aiPurposes: [],
productionLifecycle: { operations: ["install", "enable", "disable", "upgrade", "rollback", "retire", "dependency-check"], dependencyPolicy: "required", approvalRequired: ["disable", "rollback", "retire"] },
gameClientBridge: {
commands: [{ type: "announcement.send", title: "Send announcement", permission: "server.game-client.command", approvalLevel: "operator", payloadSchemaRef: "schemas/bridge/announcement.json", timeoutSeconds: 30, maxPayloadBytes: 4096 }],
snapshots: [{ type: "companion.health", schemaVersion: "1", schemaRef: "schemas/bridge/health.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: "operations", commandTypes: ["announcement.send"], snapshotTypes: ["companion.health"], queryTemplateKeys: ["scum.player.search"] }]
},
status: "installed"
};
function props(serverId = "server-1"): PageComponentProps {
const session = {
id: "operator-1",
displayName: "Operator",
status: "active" as const,
roles: ["platformAdmin" as const],
capabilities: capabilitiesForRoles(["platformAdmin"]),
profile: {},
source: "local" as const
};
return {
session,
params: { pluginId: "game.scum", routeKey: "operations", serverId },
operations,
onNavigate: () => undefined,
onLogout: async () => undefined,
onProfileSave: async () => session,
onThemePreferenceSave: async () => ({ userId: session.id, paletteId: "mecha-black", backgroundPresetId: "mecha-grid", persistence: "api", updatedAt: "2026-07-20T00:00:00Z" })
};
}
describe("PluginPageHostPage", () => {
it("renders SCUM operations from manifest-owned declarations", () => {
const html = renderToStaticMarkup(<PluginPageHostPage {...props()} initialPlugin={plugin} />);
expect(html).toContain("SCUM 运维");
expect(html).toContain("平台托管上下文");
expect(html).toContain("命令目录");
expect(html).toContain("快照目录");
expect(html).toContain("查询模板");
expect(html).toContain("返回服务器");
expect(html).not.toMatch(/sessionToken|componentKey|hostPath|dsn|runSocket|credential/i);
});
it("shows a declared availability reason when server context is missing", () => {
const html = renderToStaticMarkup(<PluginPageHostPage {...props("")} initialPlugin={plugin} />);
expect(html).toContain("SCUM 运维声明不可用");
expect(html).toContain("缺少服务器实例上下文");
});
});