import { renderHook, act } from "@testing-library/react"; import { useUserSearch } from "@/components/Attendees/useUserSearch"; import { searchUsers } from "@/features/User/userAPI"; jest.mock("@/features/User/userAPI", () => ({ searchUsers: jest.fn(), })); describe("useUserSearch", () => { const mockSearchUsers = searchUsers as jest.Mock; beforeEach(() => { jest.useFakeTimers(); jest.clearAllMocks(); }); afterEach(() => { jest.useRealTimers(); }); it("should initialize with default values", () => { const { result } = renderHook(() => useUserSearch({ objectTypes: ["user"], errorMessage: "Error" }) ); expect(result.current.query).toBe(""); expect(result.current.loading).toBe(false); expect(result.current.options).toEqual([]); expect(result.current.hasSearched).toBe(false); expect(result.current.isOpen).toBe(false); expect(result.current.inputError).toBeNull(); expect(result.current.snackbarOpen).toBe(false); expect(result.current.snackbarMessage).toBe(""); }); it("should debounce and fetch users when query changes", async () => { const mockUsers = [{ displayName: "John Doe", email: "john@example.com" }]; mockSearchUsers.mockResolvedValueOnce(mockUsers); const { result } = renderHook(() => useUserSearch({ objectTypes: ["user"], errorMessage: "Error" }) ); act(() => { result.current.setQuery("John"); }); expect(result.current.loading).toBe(false); // Before debounce // Wait for the mock promise to resolve within act await act(async () => { jest.advanceTimersByTime(300); await Promise.resolve(); // allow microtasks to flush }); expect(mockSearchUsers).toHaveBeenCalledWith("John", ["user"]); expect(result.current.loading).toBe(false); expect(result.current.options).toEqual(mockUsers); expect(result.current.hasSearched).toBe(true); }); it("should clear options and handle empty query", () => { const { result } = renderHook(() => useUserSearch({ objectTypes: ["user"], errorMessage: "Error" }) ); act(() => { result.current.setQuery(" "); // empty query with spaces }); act(() => { jest.advanceTimersByTime(300); }); expect(mockSearchUsers).not.toHaveBeenCalled(); expect(result.current.options).toEqual([]); expect(result.current.loading).toBe(false); expect(result.current.hasSearched).toBe(false); }); it("should handle search errors and show the custom error message", async () => { mockSearchUsers.mockRejectedValueOnce(new Error("API Error")); const { result } = renderHook(() => useUserSearch({ objectTypes: ["user"], errorMessage: "Custom Error" }) ); act(() => { result.current.setQuery("FailedSearch"); }); await act(async () => { jest.advanceTimersByTime(300); await Promise.resolve(); // allow microtasks to flush }); expect(result.current.hasSearched).toBe(false); expect(result.current.loading).toBe(false); expect(result.current.snackbarOpen).toBe(true); expect(result.current.snackbarMessage).toBe("Custom Error"); }); });