import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import { useUpdateUser } from '@/apps/new-ui/services/User'; import { useGetAllSpecialties } from '@/apps/new-ui/services/Specialty'; import toast from 'react-hot-toast'; import EditInformation from '@/apps/new-ui/pages/Profile/+components/EditInformation'; // Mock کردن ماژول‌ها jest.mock('@/apps/new-ui/services/User'); jest.mock('@/apps/new-ui/services/Specialty'); jest.mock('react-hot-toast'); jest.mock("react-dom", () => ({ ...jest.requireActual("react-dom"), createPortal: (node: any) => node, })); jest.mock("@/utils/axios-interceptor", () => ({ appointmentClient: { get: jest.fn(), post: jest.fn(), put: jest.fn(), delete: jest.fn(), }, })); jest.mock("../src/apps/new-ui/Utils/env.ts", () => ({ ENV: { API_URL: "https://api.test", }, })); jest.mock('@/apps/new-ui/components/MobilePicker/MobileScrollDatePicker', () => ({ __esModule: true, default: ({ value, onChange }: any) => (
onChange(e.target.value)} data-testid="date-input" />
), })); jest.mock('@/apps/new-ui/components/Inputs/NumericInput', () => ({ __esModule: true, default: ({ value, onChange, placeholder, className, ...props }: any) => ( onChange(e.target.value)} placeholder={placeholder} className={className} data-testid="numeric-input" {...props} /> ), })); jest.mock('@/apps/new-ui/components/CustomeComponents/MapPicker', () => ({ __esModule: true, default: ({ latitude, longitude, onChange }: any) => (
Lat: {latitude}, Lng: {longitude}
), })); // مسیرهای اصلاح شده jest.mock('@/apps/new-ui/pages/Profile/+components/EditPhoto', () => ({ __esModule: true, default: ({ onClose }: any) => (
), })); jest.mock('@/apps/new-ui/pages/Profile/+components/SelectSpecialization', () => ({ __esModule: true, default: ({ selectedSpecialization, onSpecializationChange, specializations }: any) => (
), })); jest.mock('@/apps/new-ui/pages/Profile/+components/SelectProvinceCity', () => ({ __esModule: true, default: ({ selectedProvince, selectedCity, onProvinceChange, onCityChange }: any) => (
onProvinceChange(e.target.value)} placeholder="استان" /> onCityChange(e.target.value)} placeholder="شهر" />
), })); // Mock createPortal jest.mock('react-dom', () => ({ ...jest.requireActual('react-dom'), createPortal: (node: React.ReactNode) => node, })); describe('EditInformation', () => { const mockOnClick = jest.fn(); const mockUpdateUser = jest.fn(); const mockUserInfo = { name: 'علی رضایی', phone_number: '09123456789', profile_picture: 'profile.jpg', city: 'تهران', date_of_birth: '1990-01-01', province: 'تهران', specialty: 'قلب', address: 'خیابان ولیعصر، پلاک ۱۲۳', latitude: 35.6892, longitude: 51.3890, }; const mockSpecialties = { specialties: [ { id: 1, name: 'قلب' }, { id: 2, name: 'مغز و اعصاب' }, { id: 3, name: 'ارتوپدی' }, ], }; beforeEach(() => { jest.clearAllMocks(); (useUpdateUser as jest.Mock).mockReturnValue({ mutate: mockUpdateUser, isPending: false }); (useGetAllSpecialties as jest.Mock).mockReturnValue({ data: mockSpecialties }); (toast.error as jest.Mock).mockImplementation(() => {}); }); const renderComponent = (props = {}) => { return render( ); }; it('should render correctly with user info', () => { renderComponent(); expect(screen.getByText('ویرایش اطلاعات')).toBeInTheDocument(); expect(screen.getByDisplayValue('علی رضایی')).toBeInTheDocument(); expect(screen.getByDisplayValue('09123456789')).toBeInTheDocument(); }); it('should render with default values when no userInfo provided', () => { render(); const nameInput = screen.getByPlaceholderText('نام و نام خانوادگی'); expect(nameInput).toHaveValue(''); const phoneInput = screen.getByPlaceholderText('شماره موبایل'); expect(phoneInput).toHaveValue(''); }); it('should update name input value', async () => { renderComponent(); const nameInput = screen.getByDisplayValue('علی رضایی'); fireEvent.change(nameInput, { target: { value: 'احمد محمدی' } }); expect(nameInput).toHaveValue('احمد محمدی'); }); it('should update phone number', async () => { renderComponent(); const phoneInput = screen.getByDisplayValue('09123456789'); fireEvent.change(phoneInput, { target: { value: '09987654321' } }); expect(phoneInput).toHaveValue('09987654321'); }); it('should call updateUser with correct data on save', async () => { mockUpdateUser.mockImplementation((_data: any, { onSuccess }: any) => { onSuccess(); }); renderComponent(); const saveButton = screen.getByText('ذخیره'); fireEvent.click(saveButton); await waitFor(() => { expect(mockUpdateUser).toHaveBeenCalledWith( expect.objectContaining({ name: 'علی رضایی', phone_number: '09123456789', specialty: 'قلب', province: 'تهران', city: 'تهران', }), expect.any(Object) ); }); }); it('should show error toast on update failure', async () => { mockUpdateUser.mockImplementation((_data: any, { onError }: any) => { onError(new Error('Update failed')); }); renderComponent(); const saveButton = screen.getByText('ذخیره'); fireEvent.click(saveButton); await waitFor(() => { expect(toast.error).toHaveBeenCalledWith('خطا در به روز رسانی اطلاعات'); }); }); it('should call onclick after successful save', async () => { mockUpdateUser.mockImplementation((_data: any, { onSuccess }: any) => { onSuccess(); }); renderComponent(); const saveButton = screen.getByText('ذخیره'); fireEvent.click(saveButton); await waitFor(() => { expect(mockOnClick).toHaveBeenCalled(); }); }); it('should open and close edit photo modal', async () => { renderComponent(); const profilePhoto = screen.getByAltText('profile'); fireEvent.click(profilePhoto); expect(screen.getByTestId('edit-photo-modal')).toBeInTheDocument(); const closeButton = screen.getByTestId('close-photo-modal'); fireEvent.click(closeButton); await waitFor(() => { expect(screen.queryByTestId('edit-photo-modal')).not.toBeInTheDocument(); }); }); it('should show hover effect on profile photo', async () => { renderComponent(); const profileDiv = screen.getByAltText('profile').parentElement!; fireEvent.mouseEnter(profileDiv); expect(screen.getByAltText('editIcon')).toBeInTheDocument(); fireEvent.mouseLeave(profileDiv); await waitFor(() => { expect(screen.queryByAltText('editIcon')).not.toBeInTheDocument(); }); }); it('should disable save button while updating', async () => { (useUpdateUser as jest.Mock).mockReturnValue({ mutate: mockUpdateUser, isPending: true }); renderComponent(); const saveButton = screen.getByText('در حال ذخیره...'); expect(saveButton).toBeDisabled(); }); it('should call onCancel when cancel button is clicked', () => { renderComponent(); const cancelButton = screen.getByText('انصراف'); fireEvent.click(cancelButton); expect(mockOnClick).toHaveBeenCalled(); }); it('should enforce maxLength on name input', () => { renderComponent(); const nameInput = screen.getByDisplayValue('علی رضایی'); expect(nameInput).toHaveAttribute('maxLength', '30'); }); });