import { describe, it, expect, vi } from "vitest"; import { render, screen, fireEvent } from "@testing-library/svelte"; import SearchBar from "./SearchBar.svelte"; describe("SearchBar", () => { describe("Rendering Tests", () => { it("should render input field with placeholder", () => { render(SearchBar, { props: { value: "", placeholder: "Search test...", onInput: vi.fn(), }, }); const input = screen.getByPlaceholderText("Search test..."); expect(input).toBeTruthy(); }); it("should render search icon", () => { const { container } = render(SearchBar, { props: { value: "", placeholder: "Search...", onInput: vi.fn(), }, }); const svg = container.querySelector("svg"); expect(svg).toBeTruthy(); const classString = svg?.getAttribute("class") || ""; expect(classString).toContain("w-5"); expect(classString).toContain("h-5"); }); it("should display current value in input", () => { render(SearchBar, { props: { value: "test query", placeholder: "Search...", onInput: vi.fn(), }, }); const input = screen.getByDisplayValue("test query") as HTMLInputElement; expect(input.value).toBe("test query"); }); it("should apply custom className", () => { const { container } = render(SearchBar, { props: { value: "", placeholder: "Search...", onInput: vi.fn(), className: "custom-class", }, }); const wrapper = container.firstChild as HTMLElement; expect(wrapper.className).toContain("custom-class"); }); it("should have proper accessibility attributes", () => { render(SearchBar, { props: { value: "", placeholder: "Search genres...", onInput: vi.fn(), }, }); const input = screen.getByPlaceholderText("Search genres...") as HTMLInputElement; expect(input.type).toBe("text"); }); }); describe("Interaction Tests", () => { it("should call onInput callback when user types", () => { const onInput = vi.fn(); render(SearchBar, { props: { value: "", placeholder: "Search...", onInput, }, }); const input = screen.getByPlaceholderText("Search...") as HTMLInputElement; fireEvent.input(input, { target: { value: "test" } }); expect(onInput).toHaveBeenCalled(); }); it("should pass correct value to onInput callback", () => { const onInput = vi.fn(); render(SearchBar, { props: { value: "", placeholder: "Search...", onInput, }, }); const input = screen.getByPlaceholderText("Search...") as HTMLInputElement; fireEvent.input(input, { target: { value: "album search" } }); // Check that callback was called with the typed value expect(onInput).toHaveBeenCalledWith("album search"); }); it("should handle multiple input changes", () => { const onInput = vi.fn(); render(SearchBar, { props: { value: "", placeholder: "Search...", onInput, }, }); const input = screen.getByPlaceholderText("Search...") as HTMLInputElement; fireEvent.input(input, { target: { value: "test" } }); fireEvent.input(input, { target: { value: "testing" } }); expect(onInput).toHaveBeenCalled(); }); }); describe("Edge Cases", () => { it("should handle empty search query", () => { render(SearchBar, { props: { value: "", placeholder: "Search...", onInput: vi.fn(), }, }); const input = screen.getByPlaceholderText("Search...") as HTMLInputElement; expect(input.value).toBe(""); }); it("should handle special characters in value", () => { render(SearchBar, { props: { value: '@$%^&*()', placeholder: "Search...", onInput: vi.fn(), }, }); const input = screen.getByDisplayValue("@$%^&*()") as HTMLInputElement; expect(input.value).toBe("@$%^&*()"); }); it("should handle very long input values", () => { const longValue = "a".repeat(500); render(SearchBar, { props: { value: longValue, placeholder: "Search...", onInput: vi.fn(), }, }); const input = screen.getByDisplayValue(longValue) as HTMLInputElement; expect(input.value).toBe(longValue); }); it("should work with numeric input", () => { const onInput = vi.fn(); render(SearchBar, { props: { value: "", placeholder: "Search...", onInput, }, }); const input = screen.getByPlaceholderText("Search...") as HTMLInputElement; fireEvent.input(input, { target: { value: "12345" } }); expect(onInput).toHaveBeenCalledWith("12345"); }); }); describe("Requirement Tests", () => { it("should support searching with spaces", () => { const onInput = vi.fn(); render(SearchBar, { props: { value: "", placeholder: "Search...", onInput, }, }); const input = screen.getByPlaceholderText("Search...") as HTMLInputElement; fireEvent.input(input, { target: { value: "search multiple words" } }); expect(onInput).toHaveBeenCalledWith("search multiple words"); }); it("should work as controlled component with value prop", () => { render(SearchBar, { props: { value: "initial value", placeholder: "Search...", onInput: vi.fn(), }, }); const input = screen.getByDisplayValue("initial value") as HTMLInputElement; expect(input.value).toBe("initial value"); }); it("should have proper styling for dark theme", () => { const { container } = render(SearchBar, { props: { value: "", placeholder: "Search...", onInput: vi.fn(), }, }); const input = container.querySelector("input"); expect(input).toBeTruthy(); const classString = input?.getAttribute("class") || ""; expect(classString.length).toBeGreaterThan(0); expect(classString).toContain("bg-"); expect(classString).toContain("text-white"); expect(classString).toContain("placeholder-gray"); }); }); });