Files
fusion/packages/dashboard/app/components/__tests__/ChatView.rooms.test.tsx
Fusion 301038effd feat(FN-3806): implement rooms create modal and chat sidebar with plugin ro
Adds a rooms feature to the chat sidebar including a new CreateRoomModal for creating chat rooms, with mobile selection handling and search empty-state copy fixes. Also introduces listTasksModifiedSince plugin contract and report plugin scaffold, replacing the removed dashboard roadmap backend.

Fusion-Task-Id: FN-3806
2026-05-09 10:31:05 -07:00

108 lines
4.1 KiB
TypeScript

import { render, screen, waitFor, within } from "@testing-library/react";
import { describe, it, expect, vi, beforeEach } from "vitest";
import { userEvent } from "@testing-library/user-event";
import { ChatView } from "../ChatView";
import * as useChatModule from "../../hooks/useChat";
import * as headerModule from "../Header";
vi.mock("lucide-react", async (importOriginal) => {
const actual = await importOriginal<typeof import("lucide-react")>();
return {
...actual,
Plus: ({ "data-testid": testId, ...props }: any) => <svg data-testid={testId || "icon-plus"} {...props} />,
Bot: ({ "data-testid": testId, ...props }: any) => <svg data-testid={testId || "icon-bot"} {...props} />,
};
});
vi.mock("../../hooks/useChat", () => ({
useChat: vi.fn(),
}));
vi.mock("../Header", () => ({
useViewportMode: vi.fn(),
}));
vi.mock("../../api", () => ({
fetchModels: vi.fn().mockResolvedValue({ models: [], favoriteProviders: [], favoriteModels: [] }),
fetchAgents: vi.fn().mockResolvedValue([
{ id: "agent-1", name: "Alpha", role: "executor", state: "idle", metadata: {}, createdAt: "", updatedAt: "" },
]),
fetchDiscoveredSkills: vi.fn().mockResolvedValue([]),
updateGlobalSettings: vi.fn(),
searchFiles: vi.fn().mockResolvedValue({ files: [] }),
}));
const mockUseChat = vi.mocked(useChatModule.useChat);
const mockUseViewportMode = vi.mocked(headerModule.useViewportMode);
beforeEach(() => {
vi.clearAllMocks();
mockUseViewportMode.mockReturnValue("desktop");
mockUseChat.mockReturnValue({
sessions: [],
activeSession: null,
sessionsLoading: false,
messages: [],
messagesLoading: false,
isStreaming: false,
streamingText: "",
streamingThinking: "",
streamingToolCalls: [],
selectSession: vi.fn(),
createSession: vi.fn(),
archiveSession: vi.fn(),
deleteSession: vi.fn(),
sendMessage: vi.fn(),
stopStreaming: vi.fn(),
pendingMessage: "",
clearPendingMessage: vi.fn(),
loadMoreMessages: vi.fn(),
hasMoreMessages: false,
searchQuery: "",
setSearchQuery: vi.fn(),
filteredSessions: [],
refreshSessions: vi.fn(),
agentsMap: new Map(),
} as any);
});
describe("ChatView rooms", () => {
it("renders create room flow and local draft list", async () => {
render(<ChatView addToast={vi.fn()} projectId="proj-1" />);
await userEvent.click(screen.getByTestId("chat-sidebar-scope-rooms"));
expect(screen.getByTestId("chat-create-room-btn")).toBeInTheDocument();
await userEvent.click(screen.getByTestId("chat-create-room-btn"));
await userEvent.type(screen.getByLabelText("Room name"), "engineering");
await userEvent.click(await screen.findByRole("button", { name: /Alpha/i }));
const dialog = screen.getByRole("dialog", { name: "Create room" });
await userEvent.click(within(dialog).getByRole("button", { name: "Create room" }));
const roomItem = await screen.findByTestId("chat-room-item-engineering");
expect(within(roomItem).getByText("#engineering")).toBeInTheDocument();
expect(within(roomItem).getByText("1 member")).toBeInTheDocument();
expect(screen.getByTestId("chat-rooms-placeholder-pane")).toHaveTextContent("Coming soon — room messaging is being wired up (FN-3807)");
});
it("hides sidebar on mobile when selecting a room", async () => {
mockUseViewportMode.mockReturnValue("mobile");
render(<ChatView addToast={vi.fn()} projectId="proj-1" />);
await userEvent.click(screen.getByTestId("chat-sidebar-scope-rooms"));
await userEvent.click(screen.getByTestId("chat-create-room-btn"));
await userEvent.type(screen.getByLabelText("Room name"), "engineering");
await userEvent.click(await screen.findByRole("button", { name: /Alpha/i }));
const dialog = screen.getByRole("dialog", { name: "Create room" });
await userEvent.click(within(dialog).getByRole("button", { name: "Create room" }));
await userEvent.click(await screen.findByTestId("chat-room-item-engineering"));
await waitFor(() => {
expect(screen.getByTestId("chat-back-btn")).toBeInTheDocument();
});
expect(screen.getByTestId("chat-rooms-placeholder-pane")).toHaveTextContent("#engineering");
});
});