import { render, screen, fireEvent, act } from "@testing-library/react"; import { useGetUserInfo } from "@/apps/new-ui/services/User"; import Services from "@/apps/new-ui/components/AppointmentComponents/Services"; // ---- MOCKS ---- // mock Swiper to avoid DOM errors jest.mock("swiper/react", () => ({ Swiper: ({ children }: any) =>
{children}
, SwiperSlide: ({ children }: any) =>
{children}
, })); jest.mock("swiper/modules", () => ({ Navigation: {}, Autoplay: {}, })); // mock VoiceSearchInput jest.mock("@/apps/new-ui/components/VoiceSearchInput", () => { return function MockVoiceInput(props: any) { return ( props.onChange(e.target.value)} /> ); }; }); // mock AddService modal jest.mock("@/apps/new-ui/pages/AddService/AddService", () => () => (
AddService Component
)); // mock useGetUserInfo jest.mock("@/apps/new-ui/services/User", () => ({ useGetUserInfo: jest.fn(), })); // Helper localStorage mock const localStore: Record = {}; beforeEach(() => { localStorage.clear(); Object.keys(localStore).forEach((k) => delete localStore[k]); jest.spyOn(window.localStorage.__proto__, "getItem").mockImplementation( (...args: any[]) => { const key = args[0]; return localStore[key] || null; } ); jest.spyOn(window.localStorage.__proto__, "setItem").mockImplementation( (...args: any[]) => { const [key, value] = args; localStore[key] = value; } ); jest.spyOn(window.localStorage.__proto__, "removeItem").mockImplementation( (...args: any[]) => { const key = args[0]; delete localStore[key]; } ); }); // test data const mockServices = [ { emoji: "💆‍♀️", name: "ماساژ", price: 200 }, { emoji: "💅", name: "مانیکور", price: 150 }, { emoji: "💇‍♀️", name: "اصلاح", price: 100 }, ]; describe("Services Component", () => { beforeEach(() => { (useGetUserInfo as jest.Mock).mockReturnValue({ data: { current_user: { services: mockServices, }, }, }); }); test("renders services from API", () => { render(); expect(screen.getByTestId("swiper")).toBeInTheDocument(); expect(screen.getAllByTestId("slide").length).toBe(3); expect(screen.getByText("ماساژ")).toBeInTheDocument(); expect(screen.getByText("مانیکور")).toBeInTheDocument(); }); test("filters services when search input changes", () => { render(); const input = screen.getByTestId("voice-input"); fireEvent.change(input, { target: { value: "اص" } }); expect(screen.getByText("اصلاح")).toBeInTheDocument(); expect(screen.queryByText("مانیکور")).toBeNull(); expect(screen.queryByText("ماساژ")).toBeNull(); }); beforeEach(() => { localStorage.clear(); jest.spyOn(localStorage.__proto__, "setItem"); }); afterEach(() => { jest.restoreAllMocks(); }); test("selecting a service updates localStorage and dispatches event", async () => { const eventSpy = jest.fn(); window.addEventListener("serviceSelected", eventSpy); render(); await act(async () => { await new Promise((r) => setTimeout(r, 0)); }); eventSpy.mockClear(); const manicureItem = screen.getByText("مانیکور"); await act(async () => { fireEvent.click(manicureItem); }); expect(eventSpy).toHaveBeenCalled(); expect(localStorage.setItem).toHaveBeenCalledWith("serviceTitle", "مانیکور"); }); test("opens AddService modal when add button clicked", () => { const dispatchSpy = jest.fn(); render(); const addButton = screen.getByAltText("add service"); expect(addButton).toBeInTheDocument(); act(() => { fireEvent.click(addButton); }); expect(dispatchSpy).toHaveBeenCalledWith("OPEN"); expect(screen.getByTestId("add-service")).toBeInTheDocument(); }); });