/** * QuickCaptureWidget Component Tests * Following TDD principles */ import { describe, it, expect, vi, beforeEach } from "vitest"; import { render, screen, waitFor } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { QuickCaptureWidget } from "../QuickCaptureWidget"; global.fetch = vi.fn(); describe("QuickCaptureWidget", () => { beforeEach(() => { vi.clearAllMocks(); }); it("should render input field", () => { render(); expect(screen.getByRole("textbox")).toBeInTheDocument(); }); it("should render submit button", () => { render(); expect(screen.getByRole("button", { name: /add|capture|submit/i })).toBeInTheDocument(); }); it("should allow text input", async () => { const user = userEvent.setup(); render(); const input = screen.getByRole("textbox"); await user.type(input, "Quick note for later"); expect(input).toHaveValue("Quick note for later"); }); it("should submit note when button clicked", async () => { const user = userEvent.setup(); (global.fetch as any).mockResolvedValueOnce({ ok: true, json: async () => ({ success: true }), }); render(); const input = screen.getByRole("textbox"); const button = screen.getByRole("button", { name: /add|capture|submit/i }); await user.type(input, "New quick note"); await user.click(button); await waitFor(() => { expect(global.fetch).toHaveBeenCalledWith( expect.stringContaining("/api"), expect.objectContaining({ method: "POST", }) ); }); }); it("should clear input after successful submission", async () => { const user = userEvent.setup(); (global.fetch as any).mockResolvedValueOnce({ ok: true, json: async () => ({ success: true }), }); render(); const input = screen.getByRole("textbox"); const button = screen.getByRole("button", { name: /add|capture|submit/i }); await user.type(input, "Test note"); await user.click(button); await waitFor(() => { expect(input).toHaveValue(""); }); }); it("should handle submission errors", async () => { const user = userEvent.setup(); (global.fetch as any).mockRejectedValueOnce(new Error("API Error")); render(); const input = screen.getByRole("textbox"); const button = screen.getByRole("button", { name: /add|capture|submit/i }); await user.type(input, "Test note"); await user.click(button); await waitFor(() => { expect(screen.getByText(/error|failed/i)).toBeInTheDocument(); }); }); it("should not submit empty notes", async () => { const user = userEvent.setup(); render(); const button = screen.getByRole("button", { name: /add|capture|submit/i }); await user.click(button); expect(global.fetch).not.toHaveBeenCalled(); }); it("should support keyboard shortcut (Enter)", async () => { const user = userEvent.setup(); (global.fetch as any).mockResolvedValueOnce({ ok: true, json: async () => ({ success: true }), }); render(); const input = screen.getByRole("textbox"); await user.type(input, "Quick note{Enter}"); await waitFor(() => { expect(global.fetch).toHaveBeenCalled(); }); }); it("should show success feedback after submission", async () => { const user = userEvent.setup(); (global.fetch as any).mockResolvedValueOnce({ ok: true, json: async () => ({ success: true }), }); render(); const input = screen.getByRole("textbox"); const button = screen.getByRole("button", { name: /add|capture|submit/i }); await user.type(input, "Test note"); await user.click(button); await waitFor(() => { expect(screen.getByText(/success|saved|captured/i)).toBeInTheDocument(); }); }); });