Files
browser/platform_web/pages/PluginsPage.test.tsx
T

86 lines
3.6 KiB
TypeScript

import { renderToStaticMarkup } from "react-dom/server";
import { describe, expect, it } from "vitest";
import { PluginsPage } from "./PluginsPage";
import type { MarketplacePluginResponse } from "../api/types";
const marketplacePlugin: MarketplacePluginResponse = {
id: "game.example",
name: "Example Server",
description: "Development plugin",
version: "0.1.0",
serverType: "example",
serverDisplayName: "Example Server",
supportedOs: ["linux", "darwin"],
manifestRef: "artifact://manifests/game.example/0.1.0",
createFormSchemaRef: "schemas/create-form.schema.json",
capabilities: ["process.install", "process.start", "logs.read"],
declaredPermissions: ["server.read", "server.logs.read", "ai.invoke"],
permissions: { ai: true, logs: true, files: false, jobs: true, artifacts: false },
lifecycleActions: { install: "actions/install.json", start: "actions/start.json", stop: "actions/stop.json" },
bridgeActions: ["server.instances.read", "logs.query", "ai.invoke"],
pages: [{ key: "logs", title: "Logs", path: "/logs", permissions: ["server.logs.read"], bridgeActions: ["logs.query"] }],
tags: ["example"],
aiPurposes: ["logs.diagnose"],
status: "installed",
source: "platform-registry"
};
describe("PluginsPage", () => {
it("renders the loading state before API data arrives", () => {
const html = renderToStaticMarkup(<PluginsPage initialState={{ listState: "loading" }} />);
expect(html).toContain("插件市场");
expect(html).toContain("page-summary-chip");
expect(html).not.toContain("metric-card");
expect(html).toContain("正在加载插件市场");
});
it("renders API error state without falling back in production state", () => {
const html = renderToStaticMarkup(<PluginsPage initialState={{ listState: "error", listError: "backend unavailable" }} />);
expect(html).toContain("插件市场加载失败");
expect(html).toContain("backend unavailable");
expect(html).not.toContain("本地演示数据仅用于前端开发");
});
it("renders API-backed plugin detail and state actions without unsafe fragments", () => {
const html = renderToStaticMarkup(
<PluginsPage initialState={{ listState: "ready", plugins: [marketplacePlugin], selectedId: marketplacePlugin.id, detail: marketplacePlugin }} />
);
expect(html).toContain("Example Server");
expect(html).toContain("平台 API");
expect(html).toContain("logs.query");
expect(html).toContain("logs.diagnose");
expect(html).toContain("安装");
expect(html).toContain("启用");
expect(html).toContain("停用");
expect(html).toContain('role="dialog"');
expect(html).not.toContain("billing");
expect(html).not.toContain("/Users/");
expect(html).not.toContain("unix://");
expect(html).not.toContain("Bearer ");
expect(html).not.toContain("sk-");
expect(html).not.toContain("password=");
expect(html).not.toContain("apiKeyRef");
});
it("keeps standalone fallback visibly isolated", () => {
const html = renderToStaticMarkup(
<PluginsPage initialState={{ listState: "ready", plugins: [marketplacePlugin], selectedId: marketplacePlugin.id, detail: marketplacePlugin, usingFallback: true }} />
);
expect(html).toContain("本地演示数据");
expect(html).toContain("本地演示数据仅用于前端开发");
});
it("does not open a plugin detail pane until a plugin is selected", () => {
const html = renderToStaticMarkup(<PluginsPage initialState={{ listState: "ready", plugins: [marketplacePlugin] }} />);
expect(html).toContain("Example Server");
expect(html).not.toContain('role="dialog"');
expect(html).not.toContain("manifest validated");
});
});