Files
tutti/packages/agent/gui/workbench/AgentGuiWorkbenchSessionMenu.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

148 lines
4.7 KiB
TypeScript

import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { AgentGuiWorkbenchSessionMenu } from "./AgentGuiWorkbenchSessionMenu";
import { AgentGuiWorkbenchHeader } from "./header";
const copy = {
copyAsMarkdown: "Copy as Markdown",
copyAsReference: "Copy as reference",
moreSessionActions: "More session actions",
renameSession: "Rename session"
};
describe("AgentGuiWorkbenchSessionMenu", () => {
it("dispatches copy once after the menu gesture and exposes only the supported copy variants", async () => {
const onAction = vi.fn();
const onHeaderPointerDown = vi.fn();
render(
<div onPointerDown={onHeaderPointerDown}>
<AgentGuiWorkbenchSessionMenu copy={copy} onAction={onAction} />
</div>
);
fireEvent.pointerDown(
screen.getByRole("button", { name: copy.moreSessionActions }),
{ button: 0, ctrlKey: false }
);
const markdown = await screen.findByRole("menuitem", {
name: copy.copyAsMarkdown
});
expect(
screen.getByRole("menuitem", { name: copy.copyAsReference })
).toBeTruthy();
for (const removed of [
"Copy deep link",
"Copy session ID",
"Copy working directory"
]) {
expect(screen.queryByRole("menuitem", { name: removed })).toBeNull();
}
fireEvent.pointerDown(markdown, { button: 0 });
expect(onHeaderPointerDown).not.toHaveBeenCalled();
fireEvent.pointerUp(markdown, { button: 0 });
fireEvent.click(markdown);
await waitFor(() => expect(onAction).toHaveBeenCalledTimes(1));
expect(onAction).toHaveBeenCalledWith("copy-markdown");
});
it("renders only the actions supported by a read-only host surface", async () => {
const onAction = vi.fn();
render(
<AgentGuiWorkbenchSessionMenu
actions={["copy-markdown", "copy-reference"]}
copy={copy}
onAction={onAction}
/>
);
fireEvent.pointerDown(
screen.getByRole("button", { name: copy.moreSessionActions }),
{ button: 0, ctrlKey: false }
);
expect(
await screen.findByRole("menuitem", { name: copy.copyAsMarkdown })
).toBeTruthy();
expect(
screen.getByRole("menuitem", { name: copy.copyAsReference })
).toBeTruthy();
expect(
screen.queryByRole("menuitem", { name: copy.renameSession })
).toBeNull();
expect(screen.queryByRole("separator")).toBeNull();
});
it("renders host-defined actions before the built-in session actions", async () => {
const onOpenSession = vi.fn();
render(
<AgentGuiWorkbenchSessionMenu
actions={["copy-markdown", "copy-reference"]}
additionalActions={[
{
id: "open-session",
label: "Open session",
onSelect: onOpenSession
}
]}
copy={copy}
onAction={vi.fn()}
/>
);
fireEvent.pointerDown(
screen.getByRole("button", { name: copy.moreSessionActions }),
{ button: 0, ctrlKey: false }
);
const menuItems = await screen.findAllByRole("menuitem");
expect(menuItems[0]).toHaveTextContent("Open session");
expect(screen.getByRole("separator")).toBeTruthy();
const openSession = screen.getByRole("menuitem", { name: "Open session" });
fireEvent.pointerDown(openSession, { button: 0 });
fireEvent.pointerUp(openSession, { button: 0 });
fireEvent.click(openSession);
await waitFor(() => expect(onOpenSession).toHaveBeenCalledOnce());
});
it("lets the complete header constrain its session menu actions", async () => {
render(
<AgentGuiWorkbenchHeader
copy={{
collapseConversationRail: "Collapse",
expandConversationRail: "Expand",
fallbackAgentLabel: "Agent",
newConversation: "New conversation",
sessionMenu: copy
}}
conversationIconUrl="agent.png"
conversationTitle="Shared session title"
hasConversation
isConversationRailAutoCollapsed
isConversationRailCollapsed
nodeId="activity-center-session-1"
sessionMenuActions={["copy-markdown", "copy-reference"]}
showConversationRailToggle={false}
showWindowControls={false}
onSessionAction={vi.fn()}
onToggleConversationRail={vi.fn()}
/>
);
expect(screen.getByText("Shared session title")).toBeTruthy();
fireEvent.pointerDown(
screen.getByRole("button", { name: copy.moreSessionActions }),
{ button: 0, ctrlKey: false }
);
expect(
await screen.findByRole("menuitem", { name: copy.copyAsMarkdown })
).toBeTruthy();
expect(
screen.queryByRole("menuitem", { name: copy.renameSession })
).toBeNull();
});
});