Files
tutti/packages/agent/gui/agent-gui/agentGuiNode/AgentSlashCommandPalette.spec.tsx
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

298 lines
9.3 KiB
TypeScript

import "@testing-library/jest-dom/vitest";
import { fireEvent, render, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { AgentSlashCommandPalette } from "./AgentSlashCommandPalette";
describe("AgentSlashCommandPalette", () => {
it("renders the Side icon for the provider-neutral slash command", () => {
render(
<AgentSlashCommandPalette
label="Slash commands"
commandsGroupLabel="Commands"
capabilitiesGroupLabel="Capabilities"
skillsGroupLabel="Skills"
pluginsGroupLabel="Plugins"
connectorsGroupLabel="Connectors"
connectorConnectedLabel="Connected"
connectorNotConnectedLabel="Not connected"
connectorUnsupportedLabel="Unsupported"
mcpGroupLabel="MCP"
highlightedIndex={0}
entries={[
{
type: "command",
key: "command:side",
label: "side",
command: {
name: "side",
description: "Open a temporary conversation"
}
}
]}
onHighlightChange={vi.fn()}
onSelect={vi.fn()}
onSelectCapability={vi.fn()}
onSelectSkill={vi.fn()}
/>
);
expect(
screen.getByRole("option", { name: /side/i }).querySelector("svg")
).toHaveClass("lucide-message-circle-plus");
});
it("renders a capability section and dispatches capability selection", () => {
const onSelectCapability = vi.fn();
render(
<AgentSlashCommandPalette
label="Slash commands"
commandsGroupLabel="Commands"
capabilitiesGroupLabel="Capabilities"
skillsGroupLabel="Skills"
pluginsGroupLabel="Plugins"
connectorsGroupLabel="Connectors"
connectorConnectedLabel="Connected"
connectorNotConnectedLabel="Not connected"
connectorUnsupportedLabel="Unsupported"
mcpGroupLabel="MCP"
highlightedIndex={0}
entries={[
{
type: "capability",
key: "capability:browserUse",
label: "Browser",
description: "Let the agent use a browser.",
capability: {
kind: "capability",
capability: "browserUse",
name: "browser",
aliases: ["浏览器"]
}
}
]}
onHighlightChange={vi.fn()}
onSelect={vi.fn()}
onSelectCapability={onSelectCapability}
onSelectSkill={vi.fn()}
/>
);
expect(screen.getByText("Capabilities")).toBeInTheDocument();
screen.getByRole("option", { name: /Browser/i }).click();
expect(onSelectCapability).toHaveBeenCalledWith({
kind: "capability",
capability: "browserUse",
name: "browser",
aliases: ["浏览器"]
});
expect(
screen.getByRole("option", { name: /Browser/i }).querySelector("svg")
).toBeTruthy();
});
it("renders inline settings on capability entries and dispatches settings selection", () => {
const onSelectCapabilitySettings = vi.fn();
render(
<AgentSlashCommandPalette
label="Slash commands"
commandsGroupLabel="Commands"
capabilitiesGroupLabel="Capabilities"
skillsGroupLabel="Skills"
pluginsGroupLabel="Plugins"
connectorsGroupLabel="Connectors"
connectorConnectedLabel="Connected"
connectorNotConnectedLabel="Not connected"
connectorUnsupportedLabel="Unsupported"
mcpGroupLabel="MCP"
highlightedIndex={0}
entries={[
{
type: "capability",
key: "capability:computerUse",
label: "Computer",
description: "Install or grant access.",
settingsAriaLabel: "Computer use setup",
settingsLabel: "Settings",
capability: {
kind: "capability",
capability: "computerUse",
name: "computer",
aliases: ["电脑"]
}
}
]}
onHighlightChange={vi.fn()}
onSelect={vi.fn()}
onSelectCapability={vi.fn()}
onSelectCapabilitySettings={onSelectCapabilitySettings}
onSelectSkill={vi.fn()}
/>
);
expect(screen.getByText("Capabilities")).toBeInTheDocument();
screen.getByRole("button", { name: "Computer use setup" }).click();
expect(onSelectCapabilitySettings).toHaveBeenCalledWith({
kind: "capability",
capability: "computerUse",
name: "computer",
aliases: ["电脑"]
});
});
it("keeps a read-only capability visible without dispatching mutations", () => {
const onSelectCapability = vi.fn();
const onSelectCapabilitySettings = vi.fn();
render(
<AgentSlashCommandPalette
label="Slash commands"
commandsGroupLabel="Commands"
capabilitiesGroupLabel="Capabilities"
skillsGroupLabel="Skills"
pluginsGroupLabel="Plugins"
connectorsGroupLabel="Connectors"
connectorConnectedLabel="Connected"
connectorNotConnectedLabel="Not connected"
connectorUnsupportedLabel="Unsupported"
mcpGroupLabel="MCP"
highlightedIndex={0}
entries={[
{
type: "capability",
key: "capability:computerUse",
label: "Computer",
disabled: true,
settingsAriaLabel: "Computer use setup",
settingsLabel: "Settings",
capability: {
kind: "capability",
capability: "computerUse",
name: "computer"
}
}
]}
onHighlightChange={vi.fn()}
onSelect={vi.fn()}
onSelectCapability={onSelectCapability}
onSelectCapabilitySettings={onSelectCapabilitySettings}
onSelectSkill={vi.fn()}
/>
);
const capability = screen.getByRole("option", { name: /computer/i });
expect(capability).toHaveAttribute("aria-disabled", "true");
capability.click();
screen.getByRole("button", { name: "Computer use setup" }).click();
expect(onSelectCapability).not.toHaveBeenCalled();
expect(onSelectCapabilitySettings).not.toHaveBeenCalled();
});
it("separates catalog skills, plugins, and connectors into source groups", () => {
const onSelectSkill = vi.fn();
render(
<AgentSlashCommandPalette
label="Slash commands"
commandsGroupLabel="Commands"
capabilitiesGroupLabel="Capabilities"
skillsGroupLabel="Skills"
pluginsGroupLabel="Plugins"
connectorsGroupLabel="Connectors"
connectorConnectedLabel="Connected"
connectorNotConnectedLabel="Not connected"
connectorUnsupportedLabel="Unsupported"
mcpGroupLabel="MCP"
highlightedIndex={0}
entries={[
{
type: "skill",
key: "skill:catalog-review",
label: "catalog-review",
skill: {
name: "catalog-review",
trigger: "$catalog-review",
sourceKind: "plugin",
kind: "skill"
}
},
{
type: "skill",
key: "skill:plugin-review",
label: "plugin-review",
skill: {
name: "plugin-review",
trigger: "$plugin-review",
sourceKind: "plugin",
pluginName: "review-tools"
}
},
{
type: "skill",
key: "skill:google-drive",
label: "google-drive",
skill: {
name: "Google Drive",
connectorKey: "google-drive",
iconUrl: "data:image/png;base64,ZHJpdmU=",
trigger: "$google-drive",
sourceKind: "connector",
kind: "connector",
status: "available"
}
},
{
type: "skill",
key: "skill:notion",
label: "Notion",
skill: {
name: "Notion",
connectorKey: "notion",
trigger: "/notion",
sourceKind: "connector",
kind: "connector",
status: "setupRequired"
}
}
]}
onHighlightChange={vi.fn()}
onSelect={vi.fn()}
onSelectCapability={vi.fn()}
onSelectSkill={onSelectSkill}
/>
);
expect(screen.getByText("Skills")).toBeInTheDocument();
expect(screen.getByText("Plugins")).toBeInTheDocument();
expect(screen.getByText("Connectors")).toHaveClass(
"mt-3",
"pt-3",
"before:inset-x-3",
"before:border-t",
"before:border-[var(--border-1)]"
);
expect(screen.getByText("Connected")).toHaveClass(
"text-[var(--state-success)]"
);
const googleDriveOption = screen.getByRole("option", {
name: /google-drive/i
});
const googleDriveIcon = googleDriveOption.querySelector("img");
expect(googleDriveIcon).toHaveAttribute(
"src",
"data:image/png;base64,ZHJpdmU="
);
expect(googleDriveOption.querySelector("svg")).toBeNull();
fireEvent.error(googleDriveIcon!);
expect(googleDriveOption.querySelector("img")).toBeNull();
expect(googleDriveOption.querySelector("svg")).toBeInTheDocument();
screen.getByRole("button", { name: "Not connected" }).click();
expect(onSelectSkill).toHaveBeenCalledWith(
expect.objectContaining({ connectorKey: "notion" })
);
});
});