Files
jellytau/src/lib/components/common/SearchBar.test.ts
T
2026-01-26 22:21:54 +01:00

241 lines
6.5 KiB
TypeScript

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");
});
});
});