import { describe, it, expect, vi, beforeEach } from 'vitest'; import { screen, fireEvent } from '@testing-library/react'; import { renderWithProviders } from '../../test/utils'; vi.mock('../../lib/api', () => ({ api: { get: vi.fn(() => Promise.resolve({ success: true, data: [] })), post: vi.fn(), patch: vi.fn(), put: vi.fn(), delete: vi.fn() }, ApiError: class extends Error {}, })); import TurnsTimeline from './TurnsTimeline'; import type { TimelineSlot } from './types'; import type { Appointment } from '../../types'; const appt = (over: Partial = {}): Appointment => ({ uuid: 'ap1', patient_name: 'ساغر صابری', patient_mobile: '09356619438', doctor_uuid: 'doc1', doctor_name: 'دکتر محمدی', slot_start: 1000, slot_end: 2000, appointment_date: '2024-12-31', appointment_time: '08:00', end_time: '08:35', status: 'completed', version: 1, created_at: '', service_item: { uuid: 's1', name: 'ویزیت عمومی' }, } as unknown as Appointment); const occupiedSlot: TimelineSlot = { start: 1000, end: 2000, start_time: '08:00', end_time: '08:35', is_available: false, appointment: appt(), cancelled_appointment: null, }; const emptySlot: TimelineSlot = { start: Math.floor(Date.now() / 1000) + 3600, end: Math.floor(Date.now() / 1000) + 5400, start_time: '09:10', end_time: '10:30', is_available: true, appointment: null, cancelled_appointment: null, }; describe('TurnsTimeline', () => { beforeEach(() => vi.clearAllMocks()); it('renders an occupied slot card with patient name + service', () => { renderWithProviders(); expect(screen.getByText('ساغر صابری')).toBeInTheDocument(); expect(screen.getByText(/ویزیت عمومی/)).toBeInTheDocument(); }); it('renders an empty slot as «افزودن نوبت» and fires onBook on click', () => { const onBook = vi.fn(); renderWithProviders(); const add = screen.getByText('افزودن نوبت سریع'); fireEvent.click(add); expect(onBook).toHaveBeenCalledWith(emptySlot); }); it('empty_reason=day_off → «این روز شیفت کاری ندارد»', () => { renderWithProviders(); expect(screen.getByText('این روز شیفت کاری ندارد')).toBeInTheDocument(); }); it('empty_reason=holiday → «این روز تعطیل است»', () => { renderWithProviders(); expect(screen.getByText('این روز تعطیل است')).toBeInTheDocument(); }); it('خطای API هرگز به «شیفت کاری ندارد» ترجمه نمی‌شود', () => { renderWithProviders(); expect(screen.getByText('خطا در دریافت برنامهٔ این روز')).toBeInTheDocument(); expect(screen.getByText('دکتر یافت نشد')).toBeInTheDocument(); expect(screen.queryByText('این روز شیفت کاری ندارد')).toBeNull(); }); it('دلیل ناشناخته/غایب → پیام خنثی، نه day_off', () => { renderWithProviders(); expect(screen.getByText('برنامهٔ این روز در دسترس نیست')).toBeInTheDocument(); expect(screen.queryByText('این روز شیفت کاری ندارد')).toBeNull(); }); });