feat: Implement resource-based appointment booking flow
- 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.
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
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();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user