import { render, screen, fireEvent } from "@testing-library/react"; import PersonnelCard, { PersonnelSimple, } from "@/apps/new-ui/pages/Personnel/+components/PersonnelCard"; import { useDeletePersonel, useGetPersonelExtraInformation, } from "@/apps/new-ui/services/PersonnelServices"; import { showWarningAlert } from "@/apps/new-ui/components/CustomAlert"; import { notifyOnce } from "@/lib/toastManager-2"; import { useNavigate } from "react-router-dom"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; const queryClient = new QueryClient(); window.scrollTo = jest.fn(); jest.mock("../src/apps/new-ui/Utils/env.ts", () => ({ ENV: { API_URL: "https://api.test", }, })); jest.mock("@/utils/axios-interceptor", () => ({ appointmentClient: { get: jest.fn(), post: jest.fn(), put: jest.fn(), delete: jest.fn(), }, })); // ------------------ Mock فایل‌ها و کتابخانه‌ها ------------------ jest.mock("@/apps/new-ui/assets/profilePhoto.svg", () => "mock-avatar"); jest.mock("@/apps/new-ui/services/PersonnelServices", () => ({ useDeletePersonel: jest.fn(), useGetPersonelExtraInformation: jest.fn(), useGetPersonel: jest.fn(() => ({ data: { services: [], duration_days: 20, appointments_count: 5, remaind_fee: 800000, }, refetch: jest.fn(), })), })); jest.mock("@/apps/new-ui/services/PersonnelServices", () => ({ useDeletePersonel: jest.fn(() => ({ mutate: jest.fn() })), useGetPersonelExtraInformation: jest.fn(() => ({ data: { duration_days: 20, appointments_count: 5, remaind_fee: 800000 }, })), useGetPersonel: jest.fn(() => ({ data: { services: [], duration_days: 20, appointments_count: 5, remaind_fee: 800000, }, refetch: jest.fn(), })), useAddServiceToPersonel: jest.fn(() => ({ mutate: jest.fn() })), useDeletePersonelService: jest.fn(() => ({ mutate: jest.fn() })), })); jest.mock( "@/apps/new-ui/pages/Personnel/+components/ManageServicesModal", () => () =>
ManageServicesModal
, ); jest.mock("@/apps/new-ui/components/CustomAlert", () => ({ showWarningAlert: jest.fn(), })); jest.mock("@/lib/toastManager-2", () => ({ notifyOnce: jest.fn(), })); jest.mock("react-router-dom", () => ({ ...jest.requireActual("react-router-dom"), useNavigate: jest.fn(), useLocation: jest.fn(() => ({ pathname: "/" })), })); // mock محیط VITE (import.meta.env) (global as any).import = { meta: { env: { VITE_APP_API_URL: "http://localhost:3000", }, }, }; // ------------------ داده پیش‌فرض ------------------ const mockPersonel: PersonnelSimple = { personel_id: 10, first_name: "امیر", last_name: "عباسی", score: 4.5, total_appointments: 5, services: [{ service_name: "اصلاح", type_of_service: "hair", price: 120000 }], }; // ------------------ mocks ------------------ const mockNavigate = jest.fn(); const mockDeleteMutate = jest.fn(); describe("PersonnelCard Component", () => { beforeEach(() => { jest.clearAllMocks(); (useNavigate as jest.Mock).mockReturnValue(mockNavigate); (useDeletePersonel as jest.Mock).mockReturnValue({ mutate: mockDeleteMutate, }); (useGetPersonelExtraInformation as jest.Mock).mockReturnValue({ data: { duration_days: 20, appointments_count: 5, remaind_fee: 800000, }, }); }); const renderCard = () => render( , ); // ------------------------------------------------------------- test("کارت پرسنل به‌درستی رندر می‌شود", () => { renderCard(); expect(screen.getByText("امیر عباسی")).toBeInTheDocument(); screen.getAllByText("4.5").forEach((el) => { expect(el).toBeInTheDocument(); }); expect(screen.getByText("مدیریت خدمات")).toBeInTheDocument(); }); // ------------------------------------------------------------- test("باز و بسته شدن آکاردئون کار می‌کند", () => { renderCard(); const trigger = screen.getByText("امیر عباسی").closest("[role='button']")!; // پیدا کردن کانتینر آکاردئون (نه کارت) const accordion = document.querySelector( "div.w-full.mx-auto.transition-all.overflow-hidden", ) as HTMLElement; expect(accordion).toHaveClass("h-0"); fireEvent.click(trigger); expect(accordion).not.toHaveClass("h-0"); fireEvent.click(trigger); expect(accordion).toHaveClass("h-0"); }); // ------------------------------------------------------------- test("باز شدن مودال مدیریت خدمات", () => { renderCard(); fireEvent.click(screen.getByText("مدیریت خدمات")); expect(screen.getByText("ManageServicesModal")).toBeInTheDocument(); }); // ------------------------------------------------------------- test("باز شدن منوی سه‌نقطه (portal) و اجرای گزینه‌های آن", () => { const mockOnClick = jest.fn(); render(); const menuBtn = screen.getByRole("button", { name: "" }); fireEvent.click(menuBtn); // گزینه‌های منو ظاهر شوند expect(screen.getByText("تنظیمات")).toBeInTheDocument(); expect(screen.getByText("ویرایش")).toBeInTheDocument(); expect(screen.getByText("حذف")).toBeInTheDocument(); expect(screen.getByText("تماس")).toBeInTheDocument(); // تست تنظیمات fireEvent.click(screen.getByText("تنظیمات")); expect(mockOnClick).toHaveBeenCalledWith(10); }); // ------------------------------------------------------------- test("دکمه ویرایش باید به /personnel/add?id=ID ناوبری کند", () => { renderCard(); fireEvent.click(screen.getByRole("button", { name: "" })); // سه‌نقطه fireEvent.click(screen.getByText("ویرایش")); expect(mockNavigate).toHaveBeenCalledWith("/personnel/add?id=10"); }); // ------------------------------------------------------------- test("دکمه حذف alert را نمایش می‌دهد و سپس mutation اجرا می‌شود", () => { renderCard(); fireEvent.click(screen.getByRole("button", { name: "" })); fireEvent.click(screen.getByText("حذف")); expect(showWarningAlert).toHaveBeenCalled(); // اجرای callback حذف const approveCallback = (showWarningAlert as jest.Mock).mock.calls[0][1]; approveCallback(); expect(mockDeleteMutate).toHaveBeenCalledWith(10); }); // ------------------------------------------------------------- test("در صورت نبود شماره تماس، notifyOnce اجرا می‌شود", () => { const personelWithoutPhone = { ...mockPersonel, phone_number: undefined }; render( , ); fireEvent.click(screen.getByRole("button", { name: "" })); fireEvent.click(screen.getByText("تماس")); expect(notifyOnce).toHaveBeenCalled(); }); // ------------------------------------------------------------- test("باز شدن مودال مدیریت خدمات", () => { renderCard(); fireEvent.click(screen.getByText("مدیریت خدمات")); expect(screen.getByText(/ManageServicesModal/i)).toBeInTheDocument(); }); });