theo-agent-dashboard

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

Composer.test.tsx (5235B)


      1 import { describe, it, expect, vi, beforeEach } from "vitest";
      2 import { render, screen, fireEvent } from "@testing-library/react";
      3 import { Composer } from "./Composer";
      4 
      5 beforeEach(() => {
      6   vi.restoreAllMocks();
      7 });
      8 
      9 describe("Composer", () => {
     10   it("renders textarea with placeholder", () => {
     11     render(<Composer onSend={vi.fn()} />);
     12     expect(screen.getByPlaceholderText("Type a message...")).toBeInTheDocument();
     13   });
     14 
     15   it("renders Send button", () => {
     16     render(<Composer onSend={vi.fn()} />);
     17     expect(screen.getByText("Send")).toBeInTheDocument();
     18   });
     19 
     20   it("renders attachment label", () => {
     21     render(<Composer onSend={vi.fn()} />);
     22     expect(screen.getByText("📎")).toBeInTheDocument();
     23   });
     24 
     25   it("renders help text", () => {
     26     render(<Composer onSend={vi.fn()} />);
     27     expect(screen.getByText(/Ctrl\+Enter to send/)).toBeInTheDocument();
     28   });
     29 
     30   it("calls onSend with text when Send is clicked", () => {
     31     const onSend = vi.fn();
     32     render(<Composer onSend={onSend} />);
     33     const textarea = screen.getByPlaceholderText("Type a message...");
     34     fireEvent.change(textarea, { target: { value: "Hello world" } });
     35     fireEvent.click(screen.getByText("Send"));
     36     expect(onSend).toHaveBeenCalledWith("Hello world", undefined);
     37   });
     38 
     39   it("clears text after sending", () => {
     40     render(<Composer onSend={vi.fn()} />);
     41     const textarea = screen.getByPlaceholderText("Type a message...");
     42     fireEvent.change(textarea, { target: { value: "Hello" } });
     43     fireEvent.click(screen.getByText("Send"));
     44     expect(textarea).toHaveValue("");
     45   });
     46 
     47   it("disables Send button when empty", () => {
     48     render(<Composer onSend={vi.fn()} />);
     49     expect(screen.getByText("Send")).toBeDisabled();
     50   });
     51 
     52   it("enables Send button when text is entered", () => {
     53     render(<Composer onSend={vi.fn()} />);
     54     fireEvent.change(screen.getByPlaceholderText("Type a message..."), { target: { value: "hi" } });
     55     expect(screen.getByText("Send")).not.toBeDisabled();
     56   });
     57 
     58   it("disables textarea when disabled prop is true", () => {
     59     render(<Composer onSend={vi.fn()} disabled />);
     60     expect(screen.getByPlaceholderText("Type a message...")).toBeDisabled();
     61     expect(screen.getByText("Send")).toBeDisabled();
     62   });
     63 
     64   it("calls onSend with Ctrl+Enter", () => {
     65     const onSend = vi.fn();
     66     render(<Composer onSend={onSend} />);
     67     const textarea = screen.getByPlaceholderText("Type a message...");
     68     fireEvent.change(textarea, { target: { value: "test" } });
     69     fireEvent.keyDown(textarea, { key: "Enter", ctrlKey: true });
     70     expect(onSend).toHaveBeenCalledWith("test", undefined);
     71   });
     72 
     73   it("calls onSend with Meta+Enter", () => {
     74     const onSend = vi.fn();
     75     render(<Composer onSend={onSend} />);
     76     const textarea = screen.getByPlaceholderText("Type a message...");
     77     fireEvent.change(textarea, { target: { value: "meta" } });
     78     fireEvent.keyDown(textarea, { key: "Enter", metaKey: true });
     79     expect(onSend).toHaveBeenCalledWith("meta", undefined);
     80   });
     81 
     82   it("does not send on Enter without modifier", () => {
     83     const onSend = vi.fn();
     84     render(<Composer onSend={onSend} />);
     85     const textarea = screen.getByPlaceholderText("Type a message...");
     86     fireEvent.change(textarea, { target: { value: "test" } });
     87     fireEvent.keyDown(textarea, { key: "Enter" });
     88     expect(onSend).not.toHaveBeenCalled();
     89   });
     90 
     91   it("does not send on Ctrl+Shift+Enter", () => {
     92     const onSend = vi.fn();
     93     render(<Composer onSend={onSend} />);
     94     const textarea = screen.getByPlaceholderText("Type a message...");
     95     fireEvent.change(textarea, { target: { value: "test" } });
     96     fireEvent.keyDown(textarea, { key: "Enter", ctrlKey: true, shiftKey: true });
     97     expect(onSend).not.toHaveBeenCalled();
     98   });
     99 
    100   it("does not send whitespace-only text", () => {
    101     const onSend = vi.fn();
    102     render(<Composer onSend={onSend} />);
    103     const textarea = screen.getByPlaceholderText("Type a message...");
    104     fireEvent.change(textarea, { target: { value: "   " } });
    105     fireEvent.click(screen.getByText("Send"));
    106     expect(onSend).not.toHaveBeenCalled();
    107   });
    108 
    109   it("trims whitespace before sending", () => {
    110     const onSend = vi.fn();
    111     render(<Composer onSend={onSend} />);
    112     const textarea = screen.getByPlaceholderText("Type a message...");
    113     fireEvent.change(textarea, { target: { value: "  hello  " } });
    114     fireEvent.click(screen.getByText("Send"));
    115     expect(onSend).toHaveBeenCalledWith("hello", undefined);
    116   });
    117 
    118   it("does not send when disabled even with text", () => {
    119     const onSend = vi.fn();
    120     render(<Composer onSend={onSend} disabled />);
    121     const textarea = screen.getByPlaceholderText("Type a message...");
    122     fireEvent.change(textarea, { target: { value: "test" } });
    123     fireEvent.click(screen.getByText("Send"));
    124     expect(onSend).not.toHaveBeenCalled();
    125   });
    126 
    127   it("shows drop zone", () => {
    128     render(<Composer onSend={vi.fn()} />);
    129     expect(screen.getByTestId("composer-drop-zone")).toBeInTheDocument();
    130   });
    131 
    132   it("textarea auto-adjusts height on text change", () => {
    133     render(<Composer onSend={vi.fn()} />);
    134     const textarea = screen.getByPlaceholderText("Type a message...");
    135     expect(textarea).toBeInTheDocument();
    136   });
    137 });