- Updated DoctorPage component to accept bookingResources prop for appointment list. - Added serviceQuery function to serialize service item UUIDs for API requests. - Introduced new API endpoints for fetching booking resources and resource slots. - Enhanced tests for new resource-based booking functionality, including resource selection and service availability. - Created ResourceSelect component for selecting appointment types, including doctor and resource options. - Updated appointment submission logic to include resource_uuid in payload when applicable. - Ensured UI reflects changes in booking flow without disrupting existing doctor-centric experience.
143 lines
5.9 KiB
JavaScript
143 lines
5.9 KiB
JavaScript
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
import { render, screen } from '@testing-library/react';
|
|
|
|
// جریان نوبت به کوکی، تم، تقویم و لایهی API وابسته است؛ اینجا فقط تصمیمِ
|
|
// «کدام مرحله رندر میشود» سنجیده میشود، پس بقیه mock میشوند.
|
|
vi.mock('@/components/layout', () => ({ default: ({ children }) => <div>{children}</div> }));
|
|
vi.mock('./Content', () => ({ default: ({ children }) => <div>{children}</div> }));
|
|
vi.mock('./date', () => ({ default: () => <div>مرحله-روز</div> }));
|
|
vi.mock('@/components/appointment/paying', () => ({ default: () => null }));
|
|
vi.mock('@/components/appointment/detail', () => ({ default: () => null }));
|
|
vi.mock('@/components/appointment/failedPay', () => ({ default: () => null }));
|
|
vi.mock('@/components/appointment/successPay', () => ({ default: () => null }));
|
|
vi.mock('@/components/register/LogInPage', () => ({ default: () => null }));
|
|
vi.mock('@/components/register/verificationPage', () => ({ default: () => null }));
|
|
vi.mock('@/components/register/LayoutRegister', () => ({ default: ({ children }) => <div>{children}</div> }));
|
|
|
|
import Container from './Container';
|
|
|
|
const RESOURCE = {
|
|
uuid: 'r1',
|
|
name: 'کندلا2021',
|
|
type: { name: 'دستگاه لیزر' },
|
|
services: [{ uuid: 's1', name: 'لیزر دست', duration_minutes: 20 }],
|
|
};
|
|
|
|
const LOCATION = { clinic_uuid: null, title: 'مطب شخصی', booking_mode: 'slot', services: [] };
|
|
|
|
const props = (over = {}) => ({
|
|
step: 0,
|
|
data: {},
|
|
doctor: { uuid: 'd1' },
|
|
setData: vi.fn(),
|
|
setStep: vi.fn(),
|
|
prevData: {},
|
|
matchedCity: {},
|
|
isForAnother: false,
|
|
setIsForAnother: vi.fn(),
|
|
disabledDates: [],
|
|
setNum: vi.fn(),
|
|
setUuid: vi.fn(),
|
|
setIsSendMsg: vi.fn(),
|
|
setSelectedSlot: vi.fn(),
|
|
setSelectedDate: vi.fn(),
|
|
setAppointmentId: vi.fn(),
|
|
setAppointmentExpiresAt: vi.fn(),
|
|
bookingMode: 'slot',
|
|
bookingServices: [],
|
|
selectedServiceUuids: [],
|
|
setSelectedServiceUuids: vi.fn(),
|
|
bookingLocations: [LOCATION],
|
|
selectedLocation: LOCATION,
|
|
locationConfirmed: true,
|
|
changeLocation: vi.fn(),
|
|
reopenLocationChoice: vi.fn(),
|
|
onDateChange: vi.fn(),
|
|
selectedClosedOnDate: false,
|
|
resources: [],
|
|
selectedResource: null,
|
|
resourceStepNeeded: false,
|
|
changeResource: vi.fn(),
|
|
reopenResourceChoice: vi.fn(),
|
|
...over,
|
|
});
|
|
|
|
describe('مرحلهٔ انتخاب نوع نوبت در جریان رزرو', () => {
|
|
beforeEach(() => vi.clearAllMocks());
|
|
|
|
it('پزشکِ بدون منبع → هیچ تغییری؛ مستقیم مرحلهٔ روز', () => {
|
|
render(<Container {...props()} />);
|
|
|
|
expect(screen.getByText('مرحله-روز')).toBeInTheDocument();
|
|
expect(screen.queryByText('انتخاب نوع نوبت')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('منبع هست و هنوز انتخاب نشده → مرحلهٔ نوع نوبت', () => {
|
|
render(<Container {...props({ resources: [RESOURCE], resourceStepNeeded: true })} />);
|
|
|
|
expect(screen.getByText('۱. انتخاب نوع نوبت')).toBeInTheDocument();
|
|
expect(screen.getByText('کندلا2021')).toBeInTheDocument();
|
|
expect(screen.queryByText('مرحله-روز')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('محلِ تأییدنشده مقدم بر مرحلهٔ منبع است', () => {
|
|
render(
|
|
<Container
|
|
{...props({
|
|
bookingLocations: [LOCATION, { ...LOCATION, clinic_uuid: 'c2', title: 'کلینیک' }],
|
|
locationConfirmed: false,
|
|
resources: [RESOURCE],
|
|
resourceStepNeeded: true,
|
|
})}
|
|
/>
|
|
);
|
|
|
|
expect(screen.getByText('۱. انتخاب محل نوبتدهی')).toBeInTheDocument();
|
|
expect(screen.queryByText('۱. انتخاب نوع نوبت')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('پزشکِ بدون برنامهٔ هفتگی ولی دارای منبع → مرحلهٔ منبع، نه پیام «فعال نیست»', () => {
|
|
render(
|
|
<Container
|
|
{...props({
|
|
bookingLocations: [],
|
|
selectedLocation: null,
|
|
resources: [{ ...RESOURCE, clinic_uuid: 'c5' }],
|
|
resourceStepNeeded: true,
|
|
})}
|
|
/>
|
|
);
|
|
|
|
expect(screen.getByText('۱. انتخاب نوع نوبت')).toBeInTheDocument();
|
|
expect(screen.getByText('کندلا2021')).toBeInTheDocument();
|
|
expect(
|
|
screen.queryByText('نوبتدهی آنلاین برای این پزشک فعال نیست.')
|
|
).not.toBeInTheDocument();
|
|
// ویزیت مستقیم وجود ندارد، پس کارتش هم نباید باشد.
|
|
expect(screen.queryByText('نوبت با پزشک')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('نه محل و نه منبع → همان پیام «فعال نیست»', () => {
|
|
render(<Container {...props({ bookingLocations: [], selectedLocation: null })} />);
|
|
|
|
expect(screen.getByText('نوبتدهی آنلاین برای این پزشک فعال نیست.')).toBeInTheDocument();
|
|
});
|
|
|
|
it('بعد از انتخاب منبع، مرحلهٔ سرویس با سرویسهای همان منبع میآید', () => {
|
|
render(
|
|
<Container
|
|
{...props({
|
|
resources: [RESOURCE],
|
|
selectedResource: RESOURCE,
|
|
resourceStepNeeded: false,
|
|
bookingMode: 'service',
|
|
bookingServices: RESOURCE.services,
|
|
})}
|
|
/>
|
|
);
|
|
|
|
expect(screen.getByText('۱. انتخاب سرویس')).toBeInTheDocument();
|
|
expect(screen.getByText('لیزر دست')).toBeInTheDocument();
|
|
});
|
|
});
|