diff --git a/autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/nodes/CustomNode/components/__tests__/NodeHeader.test.tsx b/autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/nodes/CustomNode/components/__tests__/NodeHeader.test.tsx new file mode 100644 index 0000000000..dca3e87598 --- /dev/null +++ b/autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/nodes/CustomNode/components/__tests__/NodeHeader.test.tsx @@ -0,0 +1,121 @@ +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { render, screen, fireEvent } from "@/tests/integrations/test-utils"; +import { NodeHeader } from "../NodeHeader"; +import { CustomNodeData } from "../../CustomNode"; +import { useNodeStore } from "@/app/(platform)/build/stores/nodeStore"; + +vi.mock("../NodeCost", () => ({ + NodeCost: () =>
, +})); + +vi.mock("../NodeContextMenu", () => ({ + NodeContextMenu: () =>
, +})); + +vi.mock("../NodeBadges", () => ({ + NodeBadges: () =>
, +})); + +function makeData(overrides: Partial = {}): CustomNodeData { + return { + title: "AgentExecutorBlock", + description: "", + hardcodedValues: {}, + inputSchema: {}, + outputSchema: {}, + uiType: "agent", + block_id: "block-1", + costs: [], + categories: [], + ...overrides, + } as CustomNodeData; +} + +describe("NodeHeader", () => { + const mockUpdateNodeData = vi.fn(); + + beforeEach(() => { + vi.clearAllMocks(); + useNodeStore.setState({ updateNodeData: mockUpdateNodeData } as any); + }); + + it("renders beautified generic block title", () => { + render(); + expect(screen.getByText("Agent Executor")).toBeTruthy(); + }); + + it("renders agent name with version from hardcodedValues", () => { + const data = makeData({ + hardcodedValues: { agent_name: "Researcher", graph_version: 2 }, + }); + render(); + expect(screen.getByText("Researcher v2")).toBeTruthy(); + }); + + it("renders customized_name over agent name", () => { + const data = makeData({ + metadata: { customized_name: "My Custom Node" } as any, + hardcodedValues: { agent_name: "Researcher", graph_version: 1 }, + }); + render(); + expect(screen.getByText("My Custom Node")).toBeTruthy(); + }); + + it("shows node ID prefix", () => { + render(); + expect(screen.getByText("#abc")).toBeTruthy(); + }); + + it("enters edit mode on double-click and saves on blur", () => { + render(); + const titleEl = screen.getByText("Agent Executor"); + fireEvent.doubleClick(titleEl); + + const input = screen.getByDisplayValue("AgentExecutorBlock"); + fireEvent.change(input, { target: { value: "New Name" } }); + fireEvent.blur(input); + + expect(mockUpdateNodeData).toHaveBeenCalledWith("node-1", { + metadata: { customized_name: "New Name" }, + }); + }); + + it("does not save when title is unchanged on blur", () => { + const data = makeData({ + hardcodedValues: { agent_name: "Researcher", graph_version: 2 }, + }); + render(); + const titleEl = screen.getByText("Researcher v2"); + fireEvent.doubleClick(titleEl); + + const input = screen.getByDisplayValue("Researcher v2"); + fireEvent.blur(input); + + expect(mockUpdateNodeData).not.toHaveBeenCalled(); + }); + + it("saves on Enter key", () => { + render(); + fireEvent.doubleClick(screen.getByText("Agent Executor")); + + const input = screen.getByDisplayValue("AgentExecutorBlock"); + fireEvent.change(input, { target: { value: "Renamed" } }); + fireEvent.keyDown(input, { key: "Enter" }); + + expect(mockUpdateNodeData).toHaveBeenCalledWith("node-1", { + metadata: { customized_name: "Renamed" }, + }); + }); + + it("cancels edit on Escape key", () => { + render(); + fireEvent.doubleClick(screen.getByText("Agent Executor")); + + const input = screen.getByDisplayValue("AgentExecutorBlock"); + fireEvent.change(input, { target: { value: "Changed" } }); + fireEvent.keyDown(input, { key: "Escape" }); + + expect(mockUpdateNodeData).not.toHaveBeenCalled(); + expect(screen.getByText("Agent Executor")).toBeTruthy(); + }); +});