Two engine merger tests created mkdtempSync workspaces directly in tmpdir() under the tracked `fusion-test-` prefix; under full-suite concurrent load the post-run check-test-isolation flagged them as leaks. Route both (`merger-no-op-fix-finalize.test.ts`, `merger-verification-fix-already-on-main.test.ts`) through FUSION_TEST_WORKER_ROOT like sibling merger tests so they nest inside the already-tracked worker root. Bump engine vitest subprocess guard from 60s to 120s and testTimeout to 30s — plain git commands (branch -d, worktree remove) queued behind system contention during `pnpm -r --workspace-concurrency=2` runs were timing out. The guard only fires on hangs, so healthy tests pay nothing. Also bundles in-progress dashboard mobile-breakpoint regex/CSS test updates and docs index additions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
235 lines
6.4 KiB
TypeScript
235 lines
6.4 KiB
TypeScript
import { fireEvent, render, screen } from "@testing-library/react";
|
|
import { describe, expect, it, vi } from "vitest";
|
|
import type { Agent } from "@fusion/core";
|
|
import { AgentMentionPopup } from "../AgentMentionPopup";
|
|
import { loadAllAppCss } from "../../test/cssFixture";
|
|
|
|
vi.mock("lucide-react", async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import("lucide-react")>();
|
|
return {
|
|
...actual,
|
|
Bot: ({ "data-testid": testId, ...props }: any) => (
|
|
<svg data-testid={testId || "icon-bot"} {...props} />
|
|
),
|
|
};
|
|
});
|
|
|
|
const agents: Agent[] = [
|
|
{
|
|
id: "agent-001",
|
|
name: "Alpha",
|
|
role: "executor",
|
|
state: "idle",
|
|
createdAt: "2026-04-01T00:00:00.000Z",
|
|
updatedAt: "2026-04-01T00:00:00.000Z",
|
|
metadata: {},
|
|
},
|
|
{
|
|
id: "agent-002",
|
|
name: "Beta Reviewer",
|
|
role: "reviewer",
|
|
state: "idle",
|
|
createdAt: "2026-04-01T00:00:00.000Z",
|
|
updatedAt: "2026-04-01T00:00:00.000Z",
|
|
metadata: {},
|
|
},
|
|
{
|
|
id: "agent-003",
|
|
name: "Gamma",
|
|
role: "triage",
|
|
state: "idle",
|
|
createdAt: "2026-04-01T00:00:00.000Z",
|
|
updatedAt: "2026-04-01T00:00:00.000Z",
|
|
metadata: {},
|
|
},
|
|
];
|
|
|
|
describe("AgentMentionPopup", () => {
|
|
it("renders agent list when visible", () => {
|
|
render(
|
|
<AgentMentionPopup
|
|
agents={agents}
|
|
filter=""
|
|
highlightedIndex={0}
|
|
visible={true}
|
|
onSelect={vi.fn()}
|
|
/>,
|
|
);
|
|
|
|
expect(screen.getByTestId("agent-mention-popup")).toBeInTheDocument();
|
|
expect(screen.getByTestId("agent-mention-item-agent-001")).toBeInTheDocument();
|
|
expect(screen.getByTestId("agent-mention-item-agent-002")).toBeInTheDocument();
|
|
});
|
|
|
|
it.each([
|
|
["review", "filters agents by name case-insensitively"],
|
|
["beta_re", "matches underscore handles for agents with spaces"],
|
|
])("%s %s", (filter) => {
|
|
render(
|
|
<AgentMentionPopup
|
|
agents={agents}
|
|
filter={filter}
|
|
highlightedIndex={0}
|
|
visible={true}
|
|
onSelect={vi.fn()}
|
|
/>,
|
|
);
|
|
|
|
expect(screen.queryByTestId("agent-mention-item-agent-001")).not.toBeInTheDocument();
|
|
expect(screen.getByTestId("agent-mention-item-agent-002")).toBeInTheDocument();
|
|
});
|
|
|
|
it("highlights the item at highlightedIndex", () => {
|
|
render(
|
|
<AgentMentionPopup
|
|
agents={agents}
|
|
filter=""
|
|
highlightedIndex={1}
|
|
visible={true}
|
|
onSelect={vi.fn()}
|
|
/>,
|
|
);
|
|
|
|
expect(screen.getByTestId("agent-mention-item-agent-001")).not.toHaveClass(
|
|
"agent-mention-item--highlighted",
|
|
);
|
|
expect(screen.getByTestId("agent-mention-item-agent-002")).toHaveClass(
|
|
"agent-mention-item--highlighted",
|
|
);
|
|
});
|
|
|
|
it("calls onSelect when item is clicked", () => {
|
|
const onSelect = vi.fn();
|
|
|
|
render(
|
|
<AgentMentionPopup
|
|
agents={agents}
|
|
filter=""
|
|
highlightedIndex={0}
|
|
visible={true}
|
|
onSelect={onSelect}
|
|
/>,
|
|
);
|
|
|
|
fireEvent.click(screen.getByTestId("agent-mention-item-agent-002"));
|
|
expect(onSelect).toHaveBeenCalledWith(agents[1]);
|
|
});
|
|
|
|
it("shows empty state when filter has no matches", () => {
|
|
render(
|
|
<AgentMentionPopup
|
|
agents={agents}
|
|
filter="zzz"
|
|
highlightedIndex={0}
|
|
visible={true}
|
|
onSelect={vi.fn()}
|
|
/>,
|
|
);
|
|
|
|
expect(screen.getByText("No agents found")).toBeInTheDocument();
|
|
});
|
|
|
|
it("keeps the below modifier class when rendered below", () => {
|
|
render(
|
|
<AgentMentionPopup
|
|
agents={agents}
|
|
filter=""
|
|
highlightedIndex={0}
|
|
visible={true}
|
|
onSelect={vi.fn()}
|
|
position="below"
|
|
/>,
|
|
);
|
|
|
|
expect(screen.getByTestId("agent-mention-popup")).toHaveClass("agent-mention-popup--below");
|
|
});
|
|
|
|
it("keeps the above modifier class when rendered above", () => {
|
|
render(
|
|
<AgentMentionPopup
|
|
agents={agents}
|
|
filter=""
|
|
highlightedIndex={0}
|
|
visible={true}
|
|
onSelect={vi.fn()}
|
|
position="above"
|
|
/>,
|
|
);
|
|
|
|
expect(screen.getByTestId("agent-mention-popup")).toHaveClass("agent-mention-popup--above");
|
|
});
|
|
|
|
it("anchors the below modifier above the input inside the mobile media query", async () => {
|
|
const css = await loadAllAppCss();
|
|
|
|
expect(css).toMatch(
|
|
/@media[^{]*\(max-width:\s*768px\)[^{]*\{\s*\.agent-mention-popup\s*\{[^}]*\}\s*\.agent-mention-popup--below,\s*\.agent-mention-popup--above\s*\{[^}]*bottom:\s*calc\(100%\s*\+\s*var\(--space-xs\)\);[^}]*top:\s*auto;[^}]*\}/,
|
|
);
|
|
});
|
|
|
|
it("shows room sections with members first and member dot label", () => {
|
|
render(
|
|
<AgentMentionPopup
|
|
agents={agents}
|
|
filter="a"
|
|
highlightedIndex={0}
|
|
visible={true}
|
|
onSelect={vi.fn()}
|
|
roomMemberIds={new Set(["agent-003", "agent-001"])}
|
|
roomName="engineering"
|
|
/>,
|
|
);
|
|
|
|
expect(screen.getByTestId("agent-mention-members-header")).toHaveTextContent("Members of #engineering");
|
|
expect(screen.getByTestId("agent-mention-others-header")).toBeInTheDocument();
|
|
expect(screen.getAllByLabelText("Room member")).toHaveLength(2);
|
|
});
|
|
|
|
it("room mode hides other section when filter is empty and still allows selecting non-member when searching", () => {
|
|
const onSelect = vi.fn();
|
|
const roomMemberIds = new Set(["agent-001"]);
|
|
const { rerender } = render(
|
|
<AgentMentionPopup
|
|
agents={agents}
|
|
filter=""
|
|
highlightedIndex={0}
|
|
visible={true}
|
|
onSelect={onSelect}
|
|
roomMemberIds={roomMemberIds}
|
|
/>,
|
|
);
|
|
|
|
expect(screen.queryByTestId("agent-mention-others-header")).not.toBeInTheDocument();
|
|
expect(screen.getByTestId("agent-mention-other-hint")).toBeInTheDocument();
|
|
expect(screen.queryByTestId("agent-mention-item-agent-002")).not.toBeInTheDocument();
|
|
|
|
rerender(
|
|
<AgentMentionPopup
|
|
agents={agents}
|
|
filter="be"
|
|
highlightedIndex={1}
|
|
visible={true}
|
|
onSelect={onSelect}
|
|
roomMemberIds={roomMemberIds}
|
|
/>,
|
|
);
|
|
|
|
fireEvent.click(screen.getByTestId("agent-mention-item-agent-002"));
|
|
expect(onSelect).toHaveBeenCalledWith(agents[1]);
|
|
});
|
|
|
|
it("renders nothing when visible is false", () => {
|
|
render(
|
|
<AgentMentionPopup
|
|
agents={agents}
|
|
filter=""
|
|
highlightedIndex={0}
|
|
visible={false}
|
|
onSelect={vi.fn()}
|
|
/>,
|
|
);
|
|
|
|
expect(screen.queryByTestId("agent-mention-popup")).not.toBeInTheDocument();
|
|
});
|
|
});
|