import "@testing-library/jest-dom"; import { fireEvent, render, screen } from "@testing-library/react"; import ComboBox from "./ComboBox"; const options = [ { value: "apple", label: "Apple" }, { value: "banana", label: "Banana" }, { value: "cherry", label: "Cherry" }, ]; describe("ComboBox", () => { test("renders the input with the given placeholder", () => { render(); expect(screen.getByPlaceholderText("Pick a fruit")).toBeInTheDocument(); }); test("shows all options when the input is focused", () => { render(); fireEvent.focus(screen.getByRole("combobox")); expect(screen.getByText("Apple")).toBeInTheDocument(); expect(screen.getByText("Banana")).toBeInTheDocument(); expect(screen.getByText("Cherry")).toBeInTheDocument(); }); test("filters options as the user types", () => { render(); fireEvent.change(screen.getByRole("combobox"), { target: { value: "an" }, }); expect(screen.getByText("Banana")).toBeInTheDocument(); expect(screen.queryByText("Apple")).not.toBeInTheDocument(); expect(screen.queryByText("Cherry")).not.toBeInTheDocument(); }); test("shows 'No results found' when no options match", () => { render(); fireEvent.change(screen.getByRole("combobox"), { target: { value: "xyz" }, }); expect(screen.getByText("No results found")).toBeInTheDocument(); }); test("calls onSelect with the chosen option when an option is clicked", () => { const handleSelect = vi.fn(); render(); fireEvent.focus(screen.getByRole("combobox")); fireEvent.mouseDown(screen.getByText("Banana")); expect(handleSelect).toHaveBeenCalledWith({ value: "banana", label: "Banana", }); }); test("sets the input value to the selected option's label after selection", () => { render(); const input = screen.getByRole("combobox"); fireEvent.focus(input); fireEvent.mouseDown(screen.getByText("Cherry")); expect(input).toHaveValue("Cherry"); }); test("closes the listbox after selection", () => { render(); fireEvent.focus(screen.getByRole("combobox")); fireEvent.mouseDown(screen.getByText("Apple")); expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); }); test("closes the listbox on Escape key", () => { render(); fireEvent.focus(screen.getByRole("combobox")); expect(screen.getByRole("listbox")).toBeInTheDocument(); fireEvent.keyDown(screen.getByRole("combobox"), { key: "Escape" }); expect(screen.queryByRole("listbox")).not.toBeInTheDocument(); }); test("navigates options with arrow keys", () => { render(); const input = screen.getByRole("combobox"); fireEvent.focus(input); fireEvent.keyDown(input, { key: "ArrowDown" }); expect(screen.getByText("Apple").closest("div")).toHaveClass( "combo-box-option-active", ); fireEvent.keyDown(input, { key: "ArrowDown" }); expect(screen.getByText("Banana").closest("div")).toHaveClass( "combo-box-option-active", ); }); test("selects the active option on Enter", () => { const handleSelect = vi.fn(); render(); const input = screen.getByRole("combobox"); fireEvent.focus(input); fireEvent.keyDown(input, { key: "ArrowDown" }); fireEvent.keyDown(input, { key: "Enter" }); expect(handleSelect).toHaveBeenCalledWith({ value: "apple", label: "Apple", }); }); test("calls onChange as the user types", () => { const handleChange = vi.fn(); render(); fireEvent.change(screen.getByRole("combobox"), { target: { value: "Ban" }, }); expect(handleChange).toHaveBeenCalledWith("Ban"); }); test("renders a disabled input when disabled prop is true", () => { render(); expect(screen.getByRole("combobox")).toBeDisabled(); }); test("has correct ARIA attributes on the input", () => { render(); const input = screen.getByRole("combobox"); expect(input).toHaveAttribute("aria-autocomplete", "list"); }); test("aria-expanded is true when the listbox is open", () => { render(); const input = screen.getByRole("combobox"); fireEvent.focus(input); expect(input).toHaveAttribute("aria-expanded", "true"); }); test("aria-expanded is false when the listbox is closed", () => { render(); const input = screen.getByRole("combobox"); expect(input).toHaveAttribute("aria-expanded", "false"); }); test("opens the listbox on ArrowDown when closed", () => { render(); const input = screen.getByRole("combobox"); fireEvent.keyDown(input, { key: "ArrowDown" }); expect(screen.getByRole("listbox")).toBeInTheDocument(); }); });