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
175 lines
4.8 KiB
TypeScript
175 lines
4.8 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
agentToolPanelDefaultWidthById,
|
|
clampAgentToolPanelWidth,
|
|
createAgentToolSidebarState,
|
|
filterAgentToolAddablePanels,
|
|
filterAgentToolPanels,
|
|
reduceAgentToolSidebarState,
|
|
resolveAgentToolPanelExpansionTransfer,
|
|
shouldAutoCollapseAgentToolSidebar,
|
|
type AgentToolPanelDefinition
|
|
} from "./model.ts";
|
|
|
|
const panels: readonly AgentToolPanelDefinition[] = [
|
|
{ id: "files", label: "Files" },
|
|
{ id: "terminal", label: "Terminal" },
|
|
{ id: "browser", label: "Browser" }
|
|
];
|
|
|
|
describe("agent tool sidebar model", () => {
|
|
it("uses the shared 720px default for task and message panels", () => {
|
|
expect(agentToolPanelDefaultWidthById.tasks).toBe(720);
|
|
expect(agentToolPanelDefaultWidthById.messages).toBe(720);
|
|
});
|
|
|
|
it("preserves the established Side width bounds in the shared sidebar", () => {
|
|
expect(agentToolPanelDefaultWidthById.side).toBe(440);
|
|
expect(
|
|
clampAgentToolPanelWidth({
|
|
mainContentMinWidth: 280,
|
|
panel: "side",
|
|
viewportWidth: 1_400,
|
|
width: 100
|
|
})
|
|
).toBe(360);
|
|
expect(
|
|
clampAgentToolPanelWidth({
|
|
mainContentMinWidth: 280,
|
|
panel: "side",
|
|
viewportWidth: 1_400,
|
|
width: 900
|
|
})
|
|
).toBe(600);
|
|
});
|
|
|
|
it("keeps only unique supported panels in host order", () => {
|
|
expect(
|
|
filterAgentToolPanels([
|
|
...panels,
|
|
{ id: "files", label: "Duplicate" },
|
|
{ id: "unsupported", label: "Unsupported" }
|
|
])
|
|
).toEqual(panels);
|
|
});
|
|
|
|
it("preserves host-owned panel creation policy", () => {
|
|
const contextual = { canAdd: false, id: "side", label: "Side" } as const;
|
|
expect(filterAgentToolPanels([contextual])).toEqual([contextual]);
|
|
expect(filterAgentToolAddablePanels([...panels, contextual])).toEqual(
|
|
panels
|
|
);
|
|
});
|
|
|
|
it("reuses the latest panel tab and returns to the previous tab when closing", () => {
|
|
let state = createAgentToolSidebarState();
|
|
state = reduceAgentToolSidebarState(state, {
|
|
panel: "files",
|
|
tabId: "files:first",
|
|
type: "add-panel"
|
|
});
|
|
state = reduceAgentToolSidebarState(state, {
|
|
panel: "terminal",
|
|
tabId: "terminal:first",
|
|
type: "add-panel"
|
|
});
|
|
state = reduceAgentToolSidebarState(state, {
|
|
panel: "files",
|
|
tabId: "files:ignored",
|
|
type: "open-panel"
|
|
});
|
|
|
|
expect(state.activeTabId).toBe("files:first");
|
|
expect(state.mountedTabs).toHaveLength(2);
|
|
|
|
state = reduceAgentToolSidebarState(state, {
|
|
tabId: "files:first",
|
|
type: "close-tab"
|
|
});
|
|
expect(state.activePanel).toBe("terminal");
|
|
expect(state.activeTabId).toBe("terminal:first");
|
|
|
|
state = reduceAgentToolSidebarState(state, {
|
|
tabId: "terminal:first",
|
|
type: "close-tab"
|
|
});
|
|
expect(state.activePanel).toBeNull();
|
|
expect(state.activeTabId).toBeNull();
|
|
expect(state.mountedTabs).toEqual([]);
|
|
});
|
|
|
|
it("clamps panel width to the panel and remaining-content bounds", () => {
|
|
expect(
|
|
clampAgentToolPanelWidth({
|
|
mainContentMinWidth: 280,
|
|
panel: "files",
|
|
viewportWidth: 900,
|
|
width: 900
|
|
})
|
|
).toBe(620);
|
|
});
|
|
|
|
it("collapses a sidebar only after it crosses the main-content boundary", () => {
|
|
expect(
|
|
shouldAutoCollapseAgentToolSidebar({
|
|
containerWidth: 1470,
|
|
mainContentMinWidth: 750,
|
|
sidebarWidth: 720
|
|
})
|
|
).toBe(false);
|
|
expect(
|
|
shouldAutoCollapseAgentToolSidebar({
|
|
containerWidth: 1469,
|
|
mainContentMinWidth: 750,
|
|
sidebarWidth: 720
|
|
})
|
|
).toBe(true);
|
|
});
|
|
|
|
it("ensures a background panel without changing the active tab", () => {
|
|
let state = createAgentToolSidebarState({
|
|
activePanel: "files",
|
|
activeTabId: "files:first",
|
|
mountedTabs: [{ id: "files:first", panel: "files" }]
|
|
});
|
|
state = reduceAgentToolSidebarState(state, {
|
|
panel: "browser",
|
|
resourceId: "agent-1",
|
|
tabId: "browser:agent-1",
|
|
type: "ensure-panel"
|
|
});
|
|
|
|
expect(state.activePanel).toBe("files");
|
|
expect(state.activeTabId).toBe("files:first");
|
|
expect(state.mountedTabs).toContainEqual({
|
|
id: "browser:agent-1",
|
|
panel: "browser",
|
|
resourceId: "agent-1"
|
|
});
|
|
|
|
const repeated = reduceAgentToolSidebarState(state, {
|
|
panel: "browser",
|
|
resourceId: "agent-1",
|
|
tabId: "browser:duplicate",
|
|
type: "ensure-panel"
|
|
});
|
|
expect(repeated).toBe(state);
|
|
});
|
|
|
|
it("transfers expansion while remembering both panel widths", () => {
|
|
expect(
|
|
resolveAgentToolPanelExpansionTransfer({
|
|
expandedPanel: "files",
|
|
nextPanel: "browser",
|
|
nextPanelWidth: 640,
|
|
widthBeforeExpansion: 560
|
|
})
|
|
).toEqual({
|
|
expandedPanel: "browser",
|
|
nextPanelWidthBeforeExpansion: 640,
|
|
previousPanel: "files",
|
|
previousPanelWidth: 560
|
|
});
|
|
});
|
|
});
|