441 lines
23 KiB
TypeScript
441 lines
23 KiB
TypeScript
import { renderToStaticMarkup } from "react-dom/server";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
import { HomePage } from "./HomePage";
|
|
import { MaintenancePage } from "./MaintenancePage";
|
|
import { PluginsPage } from "./PluginsPage";
|
|
import { ProfileSettingsPage } from "./ProfileSettingsPage";
|
|
import { ServerDetailPage } from "./ServerDetailPage";
|
|
import { ServersPage } from "./ServersPage";
|
|
import { UsersPage } from "./UsersPage";
|
|
import runtimeTaskProgressSource from "../components/RuntimeTaskProgress.tsx?raw";
|
|
import serverDeploymentWorkflowSource from "../components/ServerDeploymentWorkflow.tsx?raw";
|
|
import serverLiveOperationsSource from "../components/ServerLiveOperations.tsx?raw";
|
|
import serverCreateSchemaSource from "../schemas/serverManagement.ts?raw";
|
|
import serversPageSource from "./ServersPage.tsx?raw";
|
|
import serverDetailPageSource from "./ServerDetailPage.tsx?raw";
|
|
import type { PageComponentProps } from "../contracts/page";
|
|
import { capabilitiesForRoles, type CurrentUserView } from "../contracts/workspace";
|
|
import type { OperationTracker } from "../stores/operations";
|
|
import type { UserResponse } from "../api/types";
|
|
|
|
const adminUser: CurrentUserView = {
|
|
id: "user-admin",
|
|
displayName: "Operator",
|
|
status: "active",
|
|
roles: ["platformAdmin"],
|
|
capabilities: capabilitiesForRoles(["platformAdmin"]),
|
|
profile: {},
|
|
source: "local"
|
|
};
|
|
|
|
const noopOperations: OperationTracker = {
|
|
operations: [],
|
|
begin: () => "op-test",
|
|
update: () => undefined,
|
|
succeed: () => undefined,
|
|
fail: () => undefined,
|
|
isPending: () => false
|
|
};
|
|
|
|
const reviewUser: UserResponse = {
|
|
id: "user-reviewer",
|
|
displayName: "Plugin Reviewer",
|
|
email: "reviewer@example.test",
|
|
status: "pending",
|
|
roles: ["server-admin"],
|
|
profile: { contactNote: "needs approval" },
|
|
createdAt: "2026-07-03T00:00:00Z",
|
|
updatedAt: "2026-07-03T00:00:00Z"
|
|
};
|
|
|
|
function pageProps(params: PageComponentProps["params"] = {}): PageComponentProps {
|
|
return {
|
|
session: adminUser,
|
|
params,
|
|
operations: noopOperations,
|
|
onNavigate: () => undefined,
|
|
onLogout: async () => undefined,
|
|
onProfileSave: async () => adminUser,
|
|
onThemePreferenceSave: async () => ({ userId: adminUser.id, paletteId: "mecha-black", backgroundPresetId: "mecha-grid", persistence: "api", updatedAt: "2026-07-03T00:00:00Z" })
|
|
};
|
|
}
|
|
|
|
describe("first-party console pages", () => {
|
|
it("renders the platform overview with first-screen health modules", () => {
|
|
const html = renderToStaticMarkup(<HomePage {...pageProps()} />);
|
|
|
|
expect(html).toContain("平台概览");
|
|
expect(html).toContain("资源负载");
|
|
expect(html).toContain("游戏类型分布");
|
|
expect(html).toContain("最近运营信号");
|
|
expect(html).not.toContain("sk-");
|
|
});
|
|
|
|
it("keeps unavailable overview modules visible instead of claiming an empty healthy state", () => {
|
|
const html = renderToStaticMarkup(
|
|
<HomePage
|
|
{...pageProps()}
|
|
initialState={{
|
|
core: {
|
|
status: "ready",
|
|
refreshedAt: "2026-07-18T10:00:00Z",
|
|
data: {
|
|
instances: [],
|
|
endpoints: [],
|
|
jobs: [
|
|
{
|
|
id: "job-failed-1",
|
|
serverInstanceId: "server-1",
|
|
runEndpointId: "endpoint-1",
|
|
capability: "server.lifecycle.start",
|
|
idempotencyKey: "idem-1",
|
|
state: "failed",
|
|
progress: { percent: 42 },
|
|
retryPolicy: { maxAttempts: 3, initialBackoffSeconds: 1, maxBackoffSeconds: 10 },
|
|
attempt: 3,
|
|
reconcileCount: 0,
|
|
createdAt: "2026-07-18T09:59:00Z",
|
|
updatedAt: "2026-07-18T10:00:00Z"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
metrics: { status: "error", reason: "metrics unavailable", diagnosticId: "metrics-1" },
|
|
usage: { status: "error", reason: "usage unavailable", diagnosticId: "usage-1" },
|
|
providers: { status: "error", reason: "providers unavailable", diagnosticId: "providers-1" },
|
|
signals: { status: "error", reason: "audit unavailable", diagnosticId: "audit-1" }
|
|
}}
|
|
/>
|
|
);
|
|
|
|
expect(html).toContain("4 个模块不可用");
|
|
expect(html).toContain("资源指标不可用");
|
|
expect(html).toContain("审计信号不可用");
|
|
expect(html).toContain("AI 提供商信号不可用");
|
|
expect(html).toContain("server.lifecycle.start");
|
|
expect(html).not.toContain("暂无异常信号");
|
|
});
|
|
|
|
it("explains read-only overview access when the session cannot create servers", () => {
|
|
const readOnlySession: CurrentUserView = {
|
|
...adminUser,
|
|
roles: ["serverAdmin"],
|
|
capabilities: ["platform.overview.read", "servers.read"]
|
|
};
|
|
const html = renderToStaticMarkup(
|
|
<HomePage
|
|
{...pageProps()}
|
|
session={readOnlySession}
|
|
initialState={{
|
|
core: { status: "ready", data: { instances: [], endpoints: [], jobs: [] }, refreshedAt: "2026-07-18T10:00:00Z" },
|
|
metrics: { status: "ready", data: [], refreshedAt: "2026-07-18T10:00:00Z" },
|
|
usage: { status: "error", reason: "unavailable", diagnosticId: "usage" },
|
|
providers: { status: "ready", data: [], refreshedAt: "2026-07-18T10:00:00Z" },
|
|
signals: { status: "ready", data: [], refreshedAt: "2026-07-18T10:00:00Z" }
|
|
}}
|
|
/>
|
|
);
|
|
|
|
expect(html).toContain("没有创建服务器的权限");
|
|
expect(html).toContain("前往服务器管理");
|
|
});
|
|
|
|
it("renders the server list workspace with search and status filters", () => {
|
|
const html = renderToStaticMarkup(<ServersPage {...pageProps()} />);
|
|
|
|
expect(html).toContain("服务器管理");
|
|
expect(html).toContain("搜索服务器");
|
|
expect(html).toContain("autoComplete=\"off\"");
|
|
expect(html).toContain("data-1p-ignore=\"true\"");
|
|
expect(html).toContain("data-lpignore=\"true\"");
|
|
expect(html).toContain("在线");
|
|
expect(html).toContain("离线");
|
|
expect(html).not.toContain("run socket");
|
|
expect(html).not.toContain("/Users/");
|
|
});
|
|
|
|
it("keeps server metrics unavailable and runtime commands permission-gated", () => {
|
|
expect(serversPageSource).toContain("metricsUnavailable");
|
|
expect(serversPageSource).toContain("指标不可用");
|
|
expect(serversPageSource).toContain("canManageServers");
|
|
expect(serversPageSource).toContain("当前账号没有运行操作权限");
|
|
expect(serversPageSource).toContain("failedJobs");
|
|
expect(serversPageSource).toContain("refreshMetrics");
|
|
expect(serversPageSource).toContain("onClick={() => void refreshMetrics()}");
|
|
});
|
|
|
|
it("exposes run key reset from the compact server list danger menu", () => {
|
|
expect(serversPageSource).toContain("reset-run-key");
|
|
expect(serversPageSource).toContain("重置 run 密钥");
|
|
expect(serversPageSource).toContain("runtimeKeyResetStages");
|
|
expect(serversPageSource).toContain("platformApiClient.resetRunKey");
|
|
expect(serversPageSource).toContain("旧 run 会话已失效");
|
|
});
|
|
|
|
it("keeps deployment startup inputs in the create wizard without exposing protected values", () => {
|
|
expect(serversPageSource).toContain("<ServerDeploymentWorkflow");
|
|
expect(serversPageSource).toContain("openEditDeployment");
|
|
expect(serversPageSource).toContain("编辑部署");
|
|
expect(serversPageSource).not.toContain('instance.state === "running" || instance.state === "installing"');
|
|
expect(serverDetailPageSource).not.toContain("<ServerDeploymentWorkflow");
|
|
expect(serverDetailPageSource).toContain("ServerDeploymentSection");
|
|
expect(serverDeploymentWorkflowSource).toContain("基本信息");
|
|
expect(serverDeploymentWorkflowSource).toContain("部署方式");
|
|
expect(serverDeploymentWorkflowSource).toContain("相关配置");
|
|
expect(serverDeploymentWorkflowSource).toContain("专属 Run");
|
|
expect(serverDeploymentWorkflowSource).toContain("创建服务器");
|
|
expect(serverDeploymentWorkflowSource).toContain("执行目录(可选)");
|
|
expect(serverDeploymentWorkflowSource).toContain("默认使用服务器目录");
|
|
expect(serverDeploymentWorkflowSource).toContain("安装目录{isScum ? \"(必填)\" : \"(可选)\"}");
|
|
expect(serverDeploymentWorkflowSource).toContain("新建并安装执行流程");
|
|
expect(serverDeploymentWorkflowSource).toContain("安装目录”就是游戏服务端、数据和配置将落地的位置");
|
|
expect(serverDeploymentWorkflowSource).toContain("通过 SteamCMD 安装 App 3792580 到该目录");
|
|
expect(serverDeploymentWorkflowSource).toContain("全部 4 步通过才算安装成功");
|
|
expect(serverDeploymentWorkflowSource).toContain("已有服务器目录");
|
|
expect(serverDeploymentWorkflowSource).toContain("不会重装或覆盖现有游戏配置");
|
|
expect(serverDeploymentWorkflowSource).toContain("接管已有服务器执行流程");
|
|
expect(serverDeploymentWorkflowSource).toContain("不需要填写 SteamCMD 目录");
|
|
expect(serverDeploymentWorkflowSource).toContain("当前平台尚未提供 SCUM 服务端的受控升级任务");
|
|
expect(serverDeploymentWorkflowSource).toContain("已绑定服务器编辑时会直接进入相关配置");
|
|
expect(serverDeploymentWorkflowSource).toContain("可在此调整部署方式;不会重复要求选择已绑定的运行节点");
|
|
expect(serversPageSource).toContain('onNavigate("serverDetail", { serverId: result.instance.id })');
|
|
expect(serverDetailPageSource).not.toContain("运行配置绑定");
|
|
expect(serverDetailPageSource).not.toContain('type={field.sensitive ? "password" : "text"}');
|
|
expect(serverDeploymentWorkflowSource).toContain("显示已保存配置");
|
|
expect(serverDeploymentWorkflowSource).toContain("revealSavedInputs");
|
|
expect(serversPageSource).toContain("revealServerDeployment");
|
|
expect(serverDetailPageSource).toContain("最近 Run 调度");
|
|
expect(serversPageSource).toContain("serverCreateRequestFromForm(nextForm)");
|
|
expect(serverDeploymentWorkflowSource).not.toContain('name="id"');
|
|
expect(serverDeploymentWorkflowSource).not.toContain("实例 ID");
|
|
for (const forbidden of ["secret://", "/Users/", "/var/run/", "unix://", "tcp://"]) {
|
|
expect(serverDeploymentWorkflowSource).not.toContain(forbidden);
|
|
}
|
|
});
|
|
|
|
it("keeps live logs and management terminal on server detail instead of the server list", () => {
|
|
expect(serversPageSource).not.toContain("ServerLiveLogDrawer");
|
|
expect(serversPageSource).not.toContain("ServerManagementTerminalDrawer");
|
|
expect(serversPageSource).not.toContain("live-logs");
|
|
expect(serversPageSource).not.toContain("管理终端");
|
|
expect(serverDetailPageSource).toContain("ServerManagementTerminalDrawer");
|
|
expect(serverDetailPageSource).not.toContain("ServerLiveLogDrawer");
|
|
expect(serverDetailPageSource).not.toContain('<span>实时日志</span>');
|
|
expect(serverDetailPageSource).toContain("runtimeObservationFreshness");
|
|
expect(serverDetailPageSource).toContain("Run 未验证");
|
|
expect(serverDetailPageSource).toContain("管理终端");
|
|
});
|
|
|
|
it("keeps create target and profile controls out while preserving deployment steps", () => {
|
|
expect(serverDeploymentWorkflowSource).not.toContain('name="deploymentTargetId"');
|
|
expect(serverDeploymentWorkflowSource).not.toContain("请选择部署目标");
|
|
expect(serverDeploymentWorkflowSource).not.toContain("saveAsDraft");
|
|
expect(serverDeploymentWorkflowSource).not.toContain("暂不指定部署目标");
|
|
expect(serverDeploymentWorkflowSource).toContain('if (step === pluginStep) return Boolean(form.pluginId) && Boolean(form.name.trim());');
|
|
expect(serverDeploymentWorkflowSource).toContain("await onSubmit(form)");
|
|
expect(serverDeploymentWorkflowSource).not.toContain('kind === "create" && <label>运行预设');
|
|
expect(serverDeploymentWorkflowSource).not.toContain('kind === "create" && bindingFields');
|
|
expect(serverDeploymentWorkflowSource).toContain("配置启动项");
|
|
expect(serverDeploymentWorkflowSource).toContain("本次保存创建向导配置");
|
|
expect(serverDeploymentWorkflowSource).toContain('const modeStep = kind === "create" ? 1 : -1;');
|
|
expect(serverDeploymentWorkflowSource).toContain('const configurationStep = kind === "create" ? 2 : needsTargetSelection ? 1 : 0;');
|
|
expect(serverDeploymentWorkflowSource).toContain('const needsTargetSelection = kind === "edit" && !initialForm.runEndpointId;');
|
|
expect(serversPageSource).toContain("serverCreateRequestFromForm(nextForm)");
|
|
expect(serverCreateSchemaSource).not.toContain("runEndpointId: form.runEndpointId");
|
|
expect(serverCreateSchemaSource).not.toContain("deploymentTargetId: form.deploymentTargetId");
|
|
expect(serverCreateSchemaSource).not.toContain("profileKey: form.profileKey");
|
|
expect(serverCreateSchemaSource).not.toContain("runtimeBindings:");
|
|
});
|
|
|
|
it("renders server runtime actions as a compact popover trigger instead of an in-card details stack", () => {
|
|
expect(serversPageSource).toContain('aria-haspopup="menu"');
|
|
expect(serversPageSource).toContain("createPortal");
|
|
expect(serversPageSource).toContain("runtime-action-popover");
|
|
expect(serversPageSource).not.toContain("runtime-action-menu");
|
|
expect(serversPageSource).not.toContain("<details");
|
|
});
|
|
|
|
it("places server deletion in the list runtime actions with password confirmation", () => {
|
|
const deleteHandlerSource = serversPageSource.split("async function handleDeleteServer")[1]?.split("function openRunTargetSelection")[0] ?? "";
|
|
expect(deleteHandlerSource).toContain("deleteServerInstance(deleteConfirmation.serverInstanceId, {");
|
|
expect(deleteHandlerSource).toContain("password: deletePassword");
|
|
expect(deleteHandlerSource).toContain("force: forceDelete");
|
|
expect(deleteHandlerSource).toContain("confirmation: forceDelete ? deleteForceConfirmation : undefined");
|
|
expect(serversPageSource).toContain("serverDeleteConfirmation(card.instance)");
|
|
expect(serversPageSource).toContain("serverDeleteDisabledReason(session, card.instance)");
|
|
expect(serversPageSource).toContain("FORCE DELETE");
|
|
expect(serversPageSource).toContain("不会停止远端进程");
|
|
expect(serversPageSource).toContain("危险操作");
|
|
expect(serversPageSource).toContain("删除服务器");
|
|
expect(serversPageSource).toContain("请输入当前登录密码");
|
|
expect(serversPageSource).toContain("name=\"server-delete-password-confirmation\"");
|
|
expect(serversPageSource).toContain("autoComplete=\"new-password\"");
|
|
expect(serversPageSource).not.toContain("autoComplete=\"current-password\"");
|
|
expect(serversPageSource).toContain("canOpenActions");
|
|
expect(deleteHandlerSource).toContain("await refresh();");
|
|
expect(deleteHandlerSource).not.toContain("onNavigate");
|
|
expect(serverDetailPageSource).not.toContain("deleteServerInstance");
|
|
expect(serverDetailPageSource).not.toContain("serverDeleteConfirmation");
|
|
});
|
|
|
|
it("surfaces runtime actions through progress dialogs with build stages", () => {
|
|
const generateRunSource = serversPageSource.split("async function generateRunForTarget")[1]?.split("async function handleQuickRuntimeAction")[0] ?? "";
|
|
expect(serversPageSource).toContain("RuntimeTaskProgressDialog");
|
|
expect(serversPageSource).toContain("选择生成平台");
|
|
expect(serversPageSource).toContain("runTargetSelection");
|
|
expect(serversPageSource).toContain("runtimeRunBuildStages");
|
|
expect(serversPageSource).toContain("requireQuickRuntimeActionAvailable(instance.id, action)");
|
|
expect(serversPageSource).toContain("该操作不可用");
|
|
expect(generateRunSource.indexOf("runtimeTask.runTrackedTask")).toBeLessThan(generateRunSource.indexOf('await requireQuickRuntimeActionAvailable(instance.id, "generate-run")'));
|
|
expect(serverDetailPageSource).not.toContain("RuntimeTaskProgressDialog");
|
|
expect(serverDetailPageSource).not.toContain("runtimeRunBuildStages");
|
|
expect(runtimeTaskProgressSource).toContain("runtimeBuildStages");
|
|
expect(runtimeTaskProgressSource).toContain("runtimeRunBuildStages");
|
|
expect(runtimeTaskProgressSource).toContain("进度展示");
|
|
expect(runtimeTaskProgressSource).toContain("activeStepLabel");
|
|
expect(runtimeTaskProgressSource).toContain("平台正在执行当前阶段");
|
|
expect(runtimeTaskProgressSource).toContain("拉取 run 更新");
|
|
expect(runtimeTaskProgressSource).toContain("检测构建环境");
|
|
expect(runtimeTaskProgressSource).toContain("构建中");
|
|
expect(runtimeTaskProgressSource).toContain("构建完成");
|
|
expect(runtimeTaskProgressSource).toContain("拉取代码");
|
|
expect(runtimeTaskProgressSource).toContain("安装环境");
|
|
expect(runtimeTaskProgressSource).toContain("编译构建");
|
|
expect(runtimeTaskProgressSource).toContain("打包成功");
|
|
expect(runtimeTaskProgressSource).toContain("构建成功");
|
|
});
|
|
|
|
it("renders server detail sections for daily operations", () => {
|
|
const html = renderToStaticMarkup(<ServerDetailPage {...pageProps({ serverId: "server-example-1" })} />);
|
|
|
|
expect(html).toContain("返回列表");
|
|
expect(html).not.toContain("概览");
|
|
expect(html).toContain("日志");
|
|
expect(html).toContain("管理终端");
|
|
expect(html).toContain("配置");
|
|
expect(html).not.toContain("运行操作");
|
|
expect(html).not.toContain("插件控制");
|
|
expect(html).toContain("AI 助手");
|
|
expect(html).toContain("操作历史");
|
|
});
|
|
|
|
it("renders management terminal as a large command console with quick commands", () => {
|
|
expect(serverLiveOperationsSource).toContain("management-terminal-drawer");
|
|
expect(serverLiveOperationsSource).toContain("terminal-output-topbar");
|
|
expect(serverLiveOperationsSource).toContain("terminal-command-dock");
|
|
expect(serverLiveOperationsSource).toContain("terminalQuickCommandCatalog");
|
|
expect(serverLiveOperationsSource).toContain("terminalQuickCommandsForPlugin");
|
|
expect(serverLiveOperationsSource).toContain("queueGameClientBridgeCommand");
|
|
expect(serverLiveOperationsSource).toContain("scumManagementRCONCommandRequest");
|
|
expect(serverLiveOperationsSource).toContain("#ListSquads");
|
|
expect(serverLiveOperationsSource).toContain("#ListSpawnedVehicles");
|
|
expect(serverLiveOperationsSource).toContain("selectQuickCommand(item)");
|
|
expect(serverLiveOperationsSource).toContain("hideHeader");
|
|
expect(serverLiveOperationsSource).toContain("handleCommandKeyDown");
|
|
expect(serverLiveOperationsSource).toContain("commandHistory");
|
|
expect(serverLiveOperationsSource).toContain("ArrowUp");
|
|
expect(serverLiveOperationsSource).not.toContain("listServerLiveLogs");
|
|
expect(serverLiveOperationsSource).toContain("openServerLogEvents");
|
|
expect(serverLiveOperationsSource).toContain("getGameClientBridgeCommand");
|
|
expect(serverLiveOperationsSource).toContain("terminalLineFromBridgeCommand");
|
|
expect(serverLiveOperationsSource).not.toContain("terminalRelevantStreams");
|
|
expect(serverLiveOperationsSource).toContain("SSE 实时推送");
|
|
expect(serverLiveOperationsSource).toContain("mergeTerminalLines");
|
|
expect(serverLiveOperationsSource).toContain("terminalInitialHistoryWindow = 500");
|
|
expect(serverLiveOperationsSource).toContain("maxTerminalLines = 10000");
|
|
expect(serverLiveOperationsSource).toContain("followLatestRef");
|
|
expect(serverLiveOperationsSource).toContain("initialHistoryPendingRef");
|
|
expect(serverLiveOperationsSource).toContain("lockTerminalFollow");
|
|
expect(serverLiveOperationsSource).toContain("handleTerminalScroll");
|
|
expect(serverLiveOperationsSource).toContain("scrollHeight - output.clientHeight - output.scrollTop <= 24");
|
|
expect(serverLiveOperationsSource).not.toContain("terminalLogPollMs = 1000");
|
|
expect(serverLiveOperationsSource).not.toContain("logStreamPollMs = 5000");
|
|
expect(serverLiveOperationsSource).not.toContain("queryLogStream(");
|
|
expect(serverLiveOperationsSource).not.toContain("SaveWorld");
|
|
});
|
|
|
|
it("uses declared SCUM log source keys for log backfill defaults", () => {
|
|
expect(serversPageSource).toContain("scum-server-events");
|
|
expect(serversPageSource).not.toContain("server-log");
|
|
expect(serverDetailPageSource).not.toContain("server-log");
|
|
});
|
|
|
|
it("renders plugin catalog bridge readiness", () => {
|
|
const html = renderToStaticMarkup(<PluginsPage />);
|
|
|
|
expect(html).toContain("插件市场");
|
|
expect(html).toContain("平台 API");
|
|
expect(html).toContain("正在加载插件市场");
|
|
expect(html).not.toContain("billing");
|
|
});
|
|
|
|
it("renders user access review context", () => {
|
|
const html = renderToStaticMarkup(<UsersPage {...pageProps()} initialState={{ users: [reviewUser], loading: false, source: "local-development" }} />);
|
|
|
|
expect(html).toContain("用户管理");
|
|
expect(html).toContain("Plugin Reviewer");
|
|
expect(html).toContain("needs approval");
|
|
expect(html).toContain("本地开发样例 / 仅查看");
|
|
});
|
|
|
|
it("renders maintenance triage entry points", () => {
|
|
const html = renderToStaticMarkup(<MaintenancePage {...pageProps()} />);
|
|
|
|
expect(html).toContain("系统维护");
|
|
expect(html).toContain("维护排障入口");
|
|
expect(html).toContain("节点详情");
|
|
expect(html).toContain("最近失败任务");
|
|
expect(html).toContain("审计异常");
|
|
});
|
|
|
|
it("renders profile settings as a full page", () => {
|
|
const html = renderToStaticMarkup(<ProfileSettingsPage {...pageProps()} />);
|
|
|
|
expect(html).toContain("个人设置");
|
|
expect(html).toContain("个人资料");
|
|
expect(html).toContain("界面偏好");
|
|
expect(html).not.toContain("role=\"dialog\"");
|
|
});
|
|
|
|
it("keeps profile background controls focused on custom uploads", () => {
|
|
const originalWindow = globalThis.window;
|
|
Object.defineProperty(globalThis, "window", {
|
|
configurable: true,
|
|
value: {
|
|
localStorage: {
|
|
getItem: (key: string) => {
|
|
if (key === "platform-web.theme.palette") {
|
|
return "magical-girl";
|
|
}
|
|
if (key === "platform-web.theme.backgroundPreset") {
|
|
return "mecha-grid";
|
|
}
|
|
if (key === "platform-web.theme.background") {
|
|
return "data:image/png;base64,custom";
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
try {
|
|
const html = renderToStaticMarkup(<ProfileSettingsPage {...pageProps()} />);
|
|
|
|
expect(html).toContain("自定义背景");
|
|
expect(html).toContain("上传背景");
|
|
expect(html).toContain("移除背景");
|
|
expect(html).toContain("当前显示自定义上传背景;移除后回到主题配色背景。");
|
|
expect(html).not.toContain("机甲格纳库");
|
|
expect(html).not.toContain("粉月魔法阵");
|
|
expect(html).not.toContain("备用");
|
|
} finally {
|
|
Object.defineProperty(globalThis, "window", {
|
|
configurable: true,
|
|
value: originalWindow
|
|
});
|
|
}
|
|
});
|
|
});
|