Files
tutti/packages/agent/gui/agent-gui/agentGuiNode/composer/ComposerPrimaryCapabilityControl.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

263 lines
7.9 KiB
TypeScript

import "@testing-library/jest-dom/vitest";
import { act, fireEvent, render, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import type { AgentComposerProps } from "./AgentComposer.types";
import { ComposerPrimaryCapabilityControl } from "./ComposerPrimaryCapabilityControl";
const labels = {
addContentConnectors: "Connectors",
addContentConnectorConnected: "Connected",
addContentConnectorSelected: "Selected",
addContentConnectorConnect: "Connect",
addContentConnectorAuthorize: "Authorize",
addContentConnectorEmpty: "No connectors available",
addContentConnectorLoading: "Loading connectors…",
addContentConnectorMore: "View more connectors",
tuttiModeDescription: "Coordinate work",
tuttiModeLabel: "Tutti Mode"
} as AgentComposerProps["labels"];
function renderControl(
overrides: Partial<
Parameters<typeof ComposerPrimaryCapabilityControl>[0]
> = {}
) {
return render(
<ComposerPrimaryCapabilityControl
availableSkills={[]}
connectorsVisible={false}
disabled={false}
isTuttiModeActive={false}
isTuttiModeUpdating={false}
labels={labels}
loading={false}
onCapabilitySettingsRequest={vi.fn()}
onConnectorSelected={vi.fn()}
onTuttiModeChange={vi.fn()}
selectedConnectorKeys={[]}
tuttiModeSupported={false}
{...overrides}
/>
);
}
describe("ComposerPrimaryCapabilityControl", () => {
it("hides every Tutti entry point when its host gate is off", () => {
const { container } = renderControl();
expect(container).toBeEmptyDOMElement();
});
it("shows the Tutti switch and routes activation when its host gate is on", () => {
const onTuttiModeChange = vi.fn();
renderControl({ onTuttiModeChange, tuttiModeSupported: true });
expect(
screen.getByTestId("agent-gui-composer-tutti-mode-toggle")
).toBeInTheDocument();
expect(
screen.queryByTestId("connector-market-composer-trigger")
).not.toBeInTheDocument();
fireEvent.click(
screen.getByTestId("agent-gui-composer-tutti-mode-toggle-switch")
);
expect(onTuttiModeChange).toHaveBeenCalledWith(true);
});
it("shows the Tutti switch alongside connectors when both gates are on", () => {
const onRetryComposerOptions = vi.fn();
renderControl({
connectorsVisible: true,
loading: true,
onRetryComposerOptions,
tuttiModeSupported: true
});
expect(
screen.getByTestId("connector-market-composer-trigger")
).toBeInTheDocument();
expect(
screen.getByTestId("agent-gui-composer-tutti-mode-toggle")
).toBeInTheDocument();
fireEvent.pointerDown(
screen.getByTestId("connector-market-composer-trigger"),
{ button: 0, ctrlKey: false, pointerType: "mouse" }
);
expect(onRetryComposerOptions).toHaveBeenCalledWith({
force: true,
section: "connectors"
});
expect(
screen.getByTestId("connector-market-composer-loading")
).toHaveTextContent("Loading connectors…");
});
it("routes the runtime switch to the host instead of draft selection", () => {
const onCapabilitySettingsRequest = vi.fn();
const onConnectorSelected = vi.fn();
renderControl({
availableSkills: [
{
connectorKey: "github",
kind: "connector",
name: "GitHub",
sourceKind: "connector",
status: "available",
trigger: "/github"
}
],
connectorsVisible: true,
onCapabilitySettingsRequest,
onConnectorSelected
});
fireEvent.pointerDown(
screen.getByTestId("connector-market-composer-trigger"),
{ button: 0, ctrlKey: false, pointerType: "mouse" }
);
fireEvent.pointerDown(
screen.getByTestId("connector-market-composer-status-github"),
{ button: 0, ctrlKey: false, pointerType: "mouse" }
);
expect(onCapabilitySettingsRequest).toHaveBeenCalledWith({
kind: "connector",
connectorKey: "github",
action: "set_runtime_enabled",
enabled: false
});
expect(onConnectorSelected).not.toHaveBeenCalled();
});
it("routes setup-required connectors directly to installation", async () => {
let completeInstall!: () => void;
const onCapabilitySettingsRequest = vi.fn(
() =>
new Promise<void>((resolve) => {
completeInstall = resolve;
})
);
const onRetryComposerOptions = vi.fn();
render(
<ComposerPrimaryCapabilityControl
availableSkills={[
{
connectorKey: "canva",
kind: "connector",
name: "Canva",
sourceKind: "connector",
status: "setupRequired",
trigger: "/canva"
}
]}
connectorsVisible
disabled={false}
isTuttiModeActive={false}
isTuttiModeUpdating={false}
labels={labels}
loading={false}
onCapabilitySettingsRequest={onCapabilitySettingsRequest}
onConnectorSelected={vi.fn()}
onRetryComposerOptions={onRetryComposerOptions}
selectedConnectorKeys={[]}
tuttiModeSupported={false}
/>
);
fireEvent.pointerDown(
screen.getByTestId("connector-market-composer-trigger"),
{ button: 0, ctrlKey: false, pointerType: "mouse" }
);
const item = screen.getByTestId("connector-market-composer-item-canva");
fireEvent.pointerDown(item, {
button: 0,
ctrlKey: false,
pointerType: "mouse"
});
expect(onCapabilitySettingsRequest).toHaveBeenCalledWith({
kind: "connector",
connectorKey: "canva",
action: "install"
});
expect(item).toHaveAttribute("aria-busy", "true");
await act(async () => completeInstall());
expect(onRetryComposerOptions).toHaveBeenCalledWith({
force: true,
section: "connectors"
});
});
it("keeps a shared connector catalog inspectable without mutation or management actions", () => {
const onCapabilitySettingsRequest = vi.fn();
const onConnectorSelected = vi.fn();
renderControl({
availableSkills: [
{
connectorKey: "github",
description: "Authorization required on the owner device.",
kind: "connector",
name: "GitHub",
sourceKind: "connector",
status: "authRequired",
trigger: "/github"
}
],
connectorsReadOnly: true,
connectorsVisible: true,
onCapabilitySettingsRequest,
onConnectorSelected,
showConnectorViewMore: false
});
fireEvent.pointerDown(
screen.getByTestId("connector-market-composer-trigger"),
{ button: 0, ctrlKey: false, pointerType: "mouse" }
);
const item = screen.getByTestId("connector-market-composer-item-github");
expect(item).toHaveAttribute("aria-disabled", "true");
expect(item).toHaveTextContent("GitHub");
expect(item).not.toHaveTextContent(
"Authorization required on the owner device."
);
expect(
screen.queryByTestId("connector-market-composer-more")
).not.toBeInTheDocument();
fireEvent.pointerDown(item, {
button: 0,
ctrlKey: false,
pointerType: "mouse"
});
expect(onCapabilitySettingsRequest).not.toHaveBeenCalled();
expect(onConnectorSelected).not.toHaveBeenCalled();
});
it("previews a read-only draft selection on the composer trigger", () => {
renderControl({
availableSkills: [
{
connectorKey: "google-forms",
kind: "connector",
name: "Google Forms",
sourceKind: "connector",
status: "setupRequired",
trigger: "/google-forms"
}
],
connectorsReadOnly: true,
connectorsVisible: true,
selectedConnectorKeys: ["google-forms"]
});
expect(
screen.getByTestId("connector-market-composer-preview-google-forms")
).toBeInTheDocument();
expect(
screen.queryByRole("button", { name: "Connectors" })
).not.toHaveTextContent("Connectors");
});
});