Files
horus-3d/tests/unit/agentBrainPanel.test.ts
Luke The Dev 4fa4f13558 First Release of Claw3D (#11)
Co-authored-by: iamlukethedev <iamlukethedev@users.noreply.github.com>
2026-03-19 23:14:04 -05:00

219 lines
7.0 KiB
TypeScript

import { createElement } from "react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react";
import type { AgentState } from "@/features/agents/state/store";
import { AgentBrainPanel } from "@/features/agents/components/AgentInspectPanels";
import type { GatewayClient } from "@/lib/gateway/GatewayClient";
const createAgent = (agentId: string, name: string, sessionKey: string): AgentState => ({
agentId,
name,
sessionKey,
status: "idle",
sessionCreated: true,
awaitingUserInput: false,
hasUnseenActivity: false,
outputLines: [],
lastResult: null,
lastDiff: null,
runId: null,
runStartedAt: null,
streamText: null,
thinkingTrace: null,
latestOverride: null,
latestOverrideKind: null,
lastAssistantMessageAt: null,
lastActivityAt: null,
latestPreview: null,
lastUserMessage: null,
draft: "",
sessionSettingsSynced: true,
historyLoadedAt: null,
historyFetchLimit: null,
historyFetchedCount: null,
historyMaybeTruncated: false,
toolCallingEnabled: true,
showThinkingTraces: true,
model: null,
thinkingLevel: null,
avatarSeed: `seed-${agentId}`,
avatarUrl: null,
});
const createMockClient = () => {
const filesByAgent: Record<string, Record<string, string>> = {
"agent-1": {
"AGENTS.md": "alpha agents",
"SOUL.md": "# SOUL.md - Who You Are\n\n## Core Truths\n\nBe useful.",
"IDENTITY.md": "# IDENTITY.md - Who Am I?\n\n- Name: Alpha\n- Creature: droid\n- Vibe: calm\n- Emoji: 🤖\n",
"USER.md": "# USER.md - About Your Human\n\n- Name: George\n- What to call them: GP\n\n## Context\n\nBuilding Claw3D.",
"TOOLS.md": "tool notes",
"HEARTBEAT.md": "heartbeat notes",
"MEMORY.md": "durable memory",
},
"agent-2": {
"AGENTS.md": "beta agents",
},
};
const calls: Array<{ method: string; params: unknown }> = [];
const client = {
call: vi.fn(async (method: string, params: unknown) => {
calls.push({ method, params });
if (method === "agents.files.get") {
const record = params && typeof params === "object" ? (params as Record<string, unknown>) : {};
const agentId = typeof record.agentId === "string" ? record.agentId : "";
const name = typeof record.name === "string" ? record.name : "";
const content = filesByAgent[agentId]?.[name];
if (typeof content !== "string") {
return { file: { name, missing: true } };
}
return { file: { name, missing: false, content } };
}
if (method === "agents.files.set") {
const record = params && typeof params === "object" ? (params as Record<string, unknown>) : {};
const agentId = typeof record.agentId === "string" ? record.agentId : "";
const name = typeof record.name === "string" ? record.name : "";
const content = typeof record.content === "string" ? record.content : "";
if (!filesByAgent[agentId]) {
filesByAgent[agentId] = {};
}
filesByAgent[agentId][name] = content;
return { ok: true };
}
return {};
}),
} as unknown as GatewayClient;
return { client, calls, filesByAgent };
};
describe("AgentBrainPanel", () => {
afterEach(() => {
cleanup();
});
it("renders_behavior_sections_and_loads_agent_files", async () => {
const { client } = createMockClient();
const agents = [
createAgent("agent-1", "Alpha", "session-1"),
createAgent("agent-2", "Beta", "session-2"),
];
render(
createElement(AgentBrainPanel, {
client,
agents,
selectedAgentId: "agent-1",
})
);
await waitFor(() => {
expect(screen.getByRole("heading", { name: "Persona" })).toBeInTheDocument();
});
expect(screen.getByRole("heading", { name: "Directives" })).toBeInTheDocument();
expect(screen.getByRole("heading", { name: "Context" })).toBeInTheDocument();
expect(screen.getByRole("heading", { name: "Identity" })).toBeInTheDocument();
expect(screen.getByLabelText("Directives")).toHaveValue("alpha agents");
expect(screen.getByLabelText("Persona")).toHaveValue(
"# SOUL.md - Who You Are\n\n## Core Truths\n\nBe useful."
);
expect(screen.getByLabelText("Name")).toHaveValue("Alpha");
});
it("shows_actionable_message_when_session_key_missing", async () => {
const { client } = createMockClient();
const agents = [createAgent("", "Alpha", "session-1")];
render(
createElement(AgentBrainPanel, {
client,
agents,
selectedAgentId: "",
})
);
await waitFor(() => {
expect(screen.getByText("Agent ID is missing for this agent.")).toBeInTheDocument();
});
});
it("saves_updated_behavior_files", async () => {
const { client, calls, filesByAgent } = createMockClient();
const agents = [createAgent("agent-1", "Alpha", "session-1")];
render(
createElement(AgentBrainPanel, {
client,
agents,
selectedAgentId: "agent-1",
})
);
await waitFor(() => {
expect(screen.getByLabelText("Directives")).toBeInTheDocument();
});
fireEvent.change(screen.getByLabelText("Directives"), {
target: { value: "alpha directives updated" },
});
const saveButton = screen.getByRole("button", { name: "Save" });
expect(saveButton).not.toBeDisabled();
fireEvent.click(saveButton);
await waitFor(() => {
expect(calls.some((entry) => entry.method === "agents.files.set")).toBe(true);
});
expect(filesByAgent["agent-1"]["AGENTS.md"]).toBe("alpha directives updated");
});
it("discards_unsaved_changes_without_writing_files", async () => {
const { client, calls } = createMockClient();
const agents = [createAgent("agent-1", "Alpha", "session-1")];
render(
createElement(AgentBrainPanel, {
client,
agents,
selectedAgentId: "agent-1",
})
);
await waitFor(() => {
expect(screen.getByLabelText("Name")).toBeInTheDocument();
});
fireEvent.change(screen.getByLabelText("Name"), {
target: { value: "Alpha Prime" },
});
expect(screen.getByLabelText("Name")).toHaveValue("Alpha Prime");
fireEvent.click(screen.getByRole("button", { name: "Discard" }));
expect(screen.getByLabelText("Name")).toHaveValue("Alpha");
expect(calls.some((entry) => entry.method === "agents.files.set")).toBe(false);
});
it("does_not_render_name_editor_in_personality_panel", async () => {
const { client } = createMockClient();
const agents = [createAgent("agent-1", "Alpha", "session-1")];
render(
createElement(AgentBrainPanel, {
client,
agents,
selectedAgentId: "agent-1",
})
);
await waitFor(() => {
expect(screen.getByRole("heading", { name: "Persona" })).toBeInTheDocument();
});
expect(screen.queryByLabelText("Agent name")).not.toBeInTheDocument();
expect(screen.queryByRole("button", { name: "Update Name" })).not.toBeInTheDocument();
});
});