import { describe, it, expect, vi } from "vitest"; import { fireEvent, render, screen } from "@testing-library/react"; import "../../styles.css"; import { AgentPermissionPolicyEditor } from "../AgentPermissionPolicyEditor"; import { AGENT_PERMISSION_POLICY_ACTION_CATEGORIES, type AgentPermissionPolicy, } from "@fusion/core"; describe("AgentPermissionPolicyEditor", () => { it("preset dropdown switches all rules", () => { const onChange = vi.fn(); render( , ); fireEvent.change(screen.getByLabelText("Preset"), { target: { value: "locked-down" } }); const payload = onChange.mock.calls.at(-1)?.[0] as AgentPermissionPolicy; expect(payload.presetId).toBe("locked-down"); expect(payload.rules.git_write).toBe("block"); }); it("changing one category flips to custom", () => { const onChange = vi.fn(); render( , ); const selects = screen.getAllByRole("combobox"); fireEvent.change(selects[1], { target: { value: "require-approval" } }); const payload = onChange.mock.calls.at(-1)?.[0] as AgentPermissionPolicy; expect(payload.presetId).toBe("custom"); }); it("agent override inherit preset emits undefined", () => { const onChange = vi.fn(); render( , ); fireEvent.change(screen.getByLabelText("Preset"), { target: { value: "inherit" } }); expect(onChange).toHaveBeenLastCalledWith(undefined); }); it("shows inherit annotation from project default", () => { render( {}} />, ); expect(screen.getByText("from project default: Require approval")).toBeInTheDocument(); }); it("shows network and task mutation examples", () => { render( {}} />, ); expect(screen.getByText("fn_research_run (web/research)")).toBeInTheDocument(); expect(screen.getByText("fn_task_create")).toBeInTheDocument(); }); it("renders exempt tools guidance", () => { render( {}} />, ); expect(screen.getByText("Tools exempt from approval policy")).toBeInTheDocument(); expect(screen.getByText(/bypass approval policy/i)).toBeInTheDocument(); expect(screen.getByText("fn_send_message")).toBeInTheDocument(); }); it("does not duplicate fn tool examples across category rows", () => { const { container } = render( {}} />, ); const rowTools = Array.from(container.querySelectorAll(".agent-policy-examples code")) .map((node) => node.textContent ?? "") .filter((name) => name.startsWith("fn_")); expect(new Set(rowTools).size).toBe(rowTools.length); }); it("renders exactly the action-gate categories as configurable rows", () => { const { container } = render( {}} />, ); const rowCategories = Array.from(container.querySelectorAll(".agent-policy-row")) .map((row) => row.getAttribute("data-category")) .filter((value): value is string => typeof value === "string"); expect(new Set(rowCategories)).toEqual(new Set(AGENT_PERMISSION_POLICY_ACTION_CATEGORIES)); expect(rowCategories).toHaveLength(AGENT_PERMISSION_POLICY_ACTION_CATEGORIES.length); }); it("keeps exempt tools panel read-only", () => { const { container } = render( {}} />, ); const details = container.querySelector(".agent-policy-exempt"); expect(details).toBeTruthy(); expect(details?.querySelector("input, select, button")).toBeNull(); }); it("applies space-xl indentation to policy bullet lists", () => { const { container } = render( {}} />, ); const examplesList = container.querySelector(".agent-policy-examples"); const exemptList = container.querySelector(".agent-policy-exempt-list"); expect(examplesList).toBeTruthy(); expect(exemptList).toBeTruthy(); const spaceXl = getComputedStyle(document.documentElement).getPropertyValue("--space-xl").trim(); expect(spaceXl).not.toBe(""); if (!examplesList || !exemptList) { return; } const examplesPaddingLeft = getComputedStyle(examplesList).paddingLeft; const exemptPaddingLeft = getComputedStyle(exemptList).paddingLeft; const expectedPaddingLeft = examplesPaddingLeft === "var(--space-xl)" ? "var(--space-xl)" : spaceXl; expect(examplesPaddingLeft).toBe(expectedPaddingLeft); expect(exemptPaddingLeft).toBe(expectedPaddingLeft); }); });