/** * @file ChatOverlay.test.tsx * @description Tests for the ChatOverlay component */ import { render, screen, fireEvent } from "@testing-library/react"; import { describe, it, expect, vi, beforeEach } from "vitest"; import { ChatOverlay } from "./ChatOverlay"; // Mock the Chat component vi.mock("./Chat", () => ({ Chat: vi.fn(() =>
Chat Component
), })); // Mock the useChatOverlay hook const mockOpen = vi.fn(); const mockClose = vi.fn(); const mockMinimize = vi.fn(); const mockExpand = vi.fn(); const mockToggle = vi.fn(); const mockToggleMinimize = vi.fn(); vi.mock("../../hooks/useChatOverlay", () => ({ useChatOverlay: vi.fn(() => ({ isOpen: false, isMinimized: false, open: mockOpen, close: mockClose, minimize: mockMinimize, expand: mockExpand, toggle: mockToggle, toggleMinimize: mockToggleMinimize, })), })); describe("ChatOverlay", () => { beforeEach(async () => { vi.clearAllMocks(); // Reset mock to default state const { useChatOverlay } = await import("../../hooks/useChatOverlay"); vi.mocked(useChatOverlay).mockReturnValue({ isOpen: false, isMinimized: false, open: mockOpen, close: mockClose, minimize: mockMinimize, expand: mockExpand, toggle: mockToggle, toggleMinimize: mockToggleMinimize, }); }); describe("when closed", () => { it("should render a floating button to open the chat", () => { render(); const openButton = screen.getByRole("button", { name: /open chat/i }); expect(openButton).toBeDefined(); }); it("should not render the chat component when closed", () => { render(); const chatComponent = screen.queryByTestId("chat-component"); expect(chatComponent).toBeNull(); }); it("should call open when the floating button is clicked", () => { render(); const openButton = screen.getByRole("button", { name: /open chat/i }); fireEvent.click(openButton); expect(mockOpen).toHaveBeenCalledOnce(); }); }); describe("when open", () => { beforeEach(async () => { const { useChatOverlay } = await import("../../hooks/useChatOverlay"); vi.mocked(useChatOverlay).mockReturnValue({ isOpen: true, isMinimized: false, open: mockOpen, close: mockClose, minimize: mockMinimize, expand: mockExpand, toggle: mockToggle, toggleMinimize: mockToggleMinimize, }); }); it("should render the chat component", () => { render(); const chatComponent = screen.getByTestId("chat-component"); expect(chatComponent).toBeDefined(); }); it("should render a close button", () => { render(); const closeButton = screen.getByRole("button", { name: /close chat/i }); expect(closeButton).toBeDefined(); }); it("should render a minimize button", () => { render(); const minimizeButton = screen.getByRole("button", { name: /minimize chat/i }); expect(minimizeButton).toBeDefined(); }); it("should call close when the close button is clicked", () => { render(); const closeButton = screen.getByRole("button", { name: /close chat/i }); fireEvent.click(closeButton); expect(mockClose).toHaveBeenCalledOnce(); }); it("should call minimize when the minimize button is clicked", () => { render(); const minimizeButton = screen.getByRole("button", { name: /minimize chat/i }); fireEvent.click(minimizeButton); expect(mockMinimize).toHaveBeenCalledOnce(); }); }); describe("when minimized", () => { beforeEach(async () => { const { useChatOverlay } = await import("../../hooks/useChatOverlay"); vi.mocked(useChatOverlay).mockReturnValue({ isOpen: true, isMinimized: true, open: mockOpen, close: mockClose, minimize: mockMinimize, expand: mockExpand, toggle: mockToggle, toggleMinimize: mockToggleMinimize, }); }); it("should not render the chat component when minimized", () => { render(); const chatComponent = screen.queryByTestId("chat-component"); expect(chatComponent).toBeNull(); }); it("should render a minimized header", () => { render(); const header = screen.getByText(/jarvis/i); expect(header).toBeDefined(); }); it("should call expand when clicking the minimized header", () => { render(); const header = screen.getByText(/jarvis/i); fireEvent.click(header); expect(mockExpand).toHaveBeenCalledOnce(); }); }); describe("keyboard shortcuts", () => { it("should toggle chat when Cmd+Shift+J is pressed", () => { render(); fireEvent.keyDown(document, { key: "j", code: "KeyJ", metaKey: true, shiftKey: true, }); expect(mockToggle).toHaveBeenCalledOnce(); }); it("should toggle chat when Ctrl+Shift+J is pressed", () => { render(); fireEvent.keyDown(document, { key: "j", code: "KeyJ", ctrlKey: true, shiftKey: true, }); expect(mockToggle).toHaveBeenCalledOnce(); }); it("should minimize chat when Escape is pressed and chat is open", async () => { const { useChatOverlay } = await import("../../hooks/useChatOverlay"); vi.mocked(useChatOverlay).mockReturnValue({ isOpen: true, isMinimized: false, open: mockOpen, close: mockClose, minimize: mockMinimize, expand: mockExpand, toggle: mockToggle, toggleMinimize: mockToggleMinimize, }); render(); fireEvent.keyDown(document, { key: "Escape", code: "Escape", }); expect(mockMinimize).toHaveBeenCalledOnce(); }); it("should open chat when Cmd+K is pressed and chat is closed", async () => { render(); // Wait for component to mount await screen.findByRole("button", { name: /open chat/i }); fireEvent.keyDown(document, { key: "k", code: "KeyK", metaKey: true, }); expect(mockOpen).toHaveBeenCalled(); }); it("should open chat when Ctrl+K is pressed and chat is closed", async () => { render(); // Wait for component to mount await screen.findByRole("button", { name: /open chat/i }); fireEvent.keyDown(document, { key: "k", code: "KeyK", ctrlKey: true, }); expect(mockOpen).toHaveBeenCalled(); }); }); describe("new conversation button", () => { it("should render the new conversation button when chat is open", async () => { const { useChatOverlay } = await import("../../hooks/useChatOverlay"); vi.mocked(useChatOverlay).mockReturnValue({ isOpen: true, isMinimized: false, open: mockOpen, close: mockClose, minimize: mockMinimize, expand: mockExpand, toggle: mockToggle, toggleMinimize: mockToggleMinimize, }); render(); const newConvBtn = screen.getByRole("button", { name: /new conversation/i }); expect(newConvBtn).toBeDefined(); }); it("should have a tooltip on the new conversation button", async () => { const { useChatOverlay } = await import("../../hooks/useChatOverlay"); vi.mocked(useChatOverlay).mockReturnValue({ isOpen: true, isMinimized: false, open: mockOpen, close: mockClose, minimize: mockMinimize, expand: mockExpand, toggle: mockToggle, toggleMinimize: mockToggleMinimize, }); render(); const newConvBtn = screen.getByRole("button", { name: /new conversation/i }); expect(newConvBtn.getAttribute("title")).toContain("Cmd+N"); }); }); describe("responsive design", () => { it("should render as a sidebar on desktop", () => { render(); // Check for desktop-specific classes (will be verified in implementation) // This is a placeholder - actual implementation will have proper responsive classes expect(true).toBe(true); }); it("should render as a drawer on mobile", () => { render(); // Check for mobile-specific classes (will be verified in implementation) // This is a placeholder - actual implementation will have proper responsive classes expect(true).toBe(true); }); }); });