import { describe, it, expect, beforeEach, vi } from 'vitest'; import { screen, fireEvent, waitFor } from '@testing-library/react'; import { Routes, Route } from 'react-router-dom'; import { renderWithProviders } from '../test/utils'; vi.mock('../lib/api', () => ({ api: { get: vi.fn(), post: vi.fn(), patch: vi.fn(), put: vi.fn(), delete: vi.fn() }, ApiError: class extends Error {}, })); import { api } from '../lib/api'; import AppointmentEditPage from './AppointmentEditPage'; const get = api.get as ReturnType; const patch = api.patch as ReturnType; const slotStart = Math.floor(new Date('2026-08-01T15:00').getTime() / 1000); const slotEnd = Math.floor(new Date('2026-08-01T16:00').getTime() / 1000); beforeEach(() => { get.mockReset(); patch.mockReset(); get.mockImplementation((url: string) => { if (url === '/api/v1/appointment/ap1') return Promise.resolve({ success: true, data: { data: { uuid: 'ap1', slot_start: slotStart, slot_end: slotEnd, status: 'confirmed', version: 4, note: 'یادداشت', deposit_required: true, deposit_amount_rials: 5000000, service_section: { uuid: 'sec1', name: 'زیبایی' }, service_item: { uuid: 'it1', name: 'لیزر' }, staff: { uuid: 'st1', full_name: 'سحر ایمانی' }, } } }); if (url === '/api/v1/service-sections') return Promise.resolve({ success: true, data: [{ uuid: 'sec1', name: 'زیبایی' }] }); if (url.startsWith('/api/v1/service-items/')) return Promise.resolve({ success: true, data: [{ uuid: 'it1', name: 'لیزر' }] }); if (url === '/api/v1/staff') return Promise.resolve({ success: true, data: [{ uuid: 'st1', full_name: 'سحر ایمانی' }] }); return Promise.resolve({ success: true, data: [] }); }); patch.mockResolvedValue({ success: true, data: {} }); }); function renderEdit() { return renderWithProviders( } />, { route: '/admin/appointments/ap1/edit' }, ); } describe('AppointmentEditPage (ویرایش نوبت)', () => { it('hydrates the form from the appointment', async () => { renderEdit(); expect(await screen.findByText('مشخصات سرویس:')).toBeInTheDocument(); expect((screen.getByLabelText('ساعت شروع') as HTMLInputElement).value).toBe('15:00'); expect(screen.getByText('قطعی شده')).toBeInTheDocument(); // react-select single value = confirmed expect(screen.getByDisplayValue('یادداشت')).toBeInTheDocument(); }); it('patches the general update endpoint with the edited values', async () => { renderEdit(); await screen.findByText('مشخصات سرویس:'); fireEvent.change(screen.getByLabelText('ساعت پایان'), { target: { value: '16:30' } }); fireEvent.click(screen.getByRole('button', { name: 'ثبت اطلاعات' })); await waitFor(() => expect(patch).toHaveBeenCalledWith('/api/v1/appointment/ap1', expect.objectContaining({ slot_start: slotStart, slot_end: Math.floor(new Date('2026-08-01T16:30').getTime() / 1000), service_section_uuid: 'sec1', staff_uuid: 'st1', deposit_required: true, version: 4, }))); }); });