import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
vi.mock('@/services/response', () => ({
request: {
getServiceSlotsForReschedule: vi.fn(),
serviceReschedule: vi.fn(),
},
}));
import { request } from '@/services/response';
import RescheduleModal from './RescheduleModal';
const appointment = {
uuid: 'a-1',
doctor: { uuid: 'd-1' },
service_items: [{ uuid: 's-1' }, { uuid: 's-2' }],
};
const slots = {
data: {
total_duration_minutes: 30,
start_times: [
{ start: 1_900_000_000, end: 1_900_001_800, start_time: '09:00', end_time: '09:30' },
{ start: 1_900_003_600, end: 1_900_005_400, start_time: '10:00', end_time: '10:30' },
],
},
};
async function openAndPickFirstDay(user) {
render();
await user.click(screen.getByRole('button', { name: 'جابهجایی نوبت' }));
const days = screen.getAllByRole('button').filter((b) => /\d|[۰-۹]/.test(b.textContent));
await user.click(days[0]);
}
describe('مودال جابهجایی نوبت سایت', () => {
beforeEach(() => {
request.getServiceSlotsForReschedule.mockResolvedValue(slots);
request.serviceReschedule.mockResolvedValue({ data: {} });
});
/**
* ⭐ بدون `exclude_appointment_uuid`، بیمار ساعت خودش را «پر» میبیند و نمیتواند
* حتی به همان روز جابهجا شود.
*/
it('وقتها را با کنارگذاشتن نوبت فعلی میگیرد', async () => {
const user = userEvent.setup();
await openAndPickFirstDay(user);
await waitFor(() => expect(request.getServiceSlotsForReschedule).toHaveBeenCalled());
const [doctorUuid, , appointmentUuid, serviceUuids] =
request.getServiceSlotsForReschedule.mock.calls[0];
expect(doctorUuid).toBe('d-1');
expect(appointmentUuid).toBe('a-1');
expect(serviceUuids).toEqual(['s-1', 's-2']);
});
/** مدت را سرور حساب میکند؛ فرانت فقط زمان شروع میفرستد. */
it('فقط زمان شروع را میفرستد، نه مدت', async () => {
const onDone = vi.fn();
const user = userEvent.setup();
render();
await user.click(screen.getByRole('button', { name: 'جابهجایی نوبت' }));
const days = screen.getAllByRole('button').filter((b) => /\d|[۰-۹]/.test(b.textContent));
await user.click(days[0]);
const slot = await screen.findByRole('button', { name: '09:00' });
await user.click(slot);
await user.click(screen.getByRole('button', { name: 'جابهجا کن' }));
await waitFor(() =>
expect(request.serviceReschedule).toHaveBeenCalledWith('a-1', { start: 1_900_000_000 }),
);
await waitFor(() => expect(onDone).toHaveBeenCalled());
});
it('روزِ بدون وقت آزاد را صریح میگوید', async () => {
request.getServiceSlotsForReschedule.mockResolvedValue({ data: { start_times: [] } });
const user = userEvent.setup();
await openAndPickFirstDay(user);
expect(await screen.findByText(/در این روز وقت آزادی نیست/)).toBeInTheDocument();
});
/** ۴۰۹ یعنی همین لحظه کس دیگری گرفت — پیام سرور باید دیده شود. */
it('پیام خطای سرور را نشان میدهد', async () => {
request.serviceReschedule.mockRejectedValue(new Error('این بازه زمانی قبلاً رزرو شده است'));
const user = userEvent.setup();
await openAndPickFirstDay(user);
await user.click(await screen.findByRole('button', { name: '09:00' }));
await user.click(screen.getByRole('button', { name: 'جابهجا کن' }));
expect(await screen.findByText('این بازه زمانی قبلاً رزرو شده است')).toBeInTheDocument();
});
});