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,64 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import ResourceSelect from './index';
|
||||
|
||||
const resource = (over = {}) => ({
|
||||
uuid: 'r1',
|
||||
name: 'کندلا2021',
|
||||
type: { code: 'laser_device', name: 'دستگاه لیزر' },
|
||||
services: [{ uuid: 's1', name: 'لیزر دست', duration_minutes: 20, price_rials: 2000000 }],
|
||||
...over,
|
||||
});
|
||||
|
||||
describe('ResourceSelect', () => {
|
||||
it('کارت «نوبت با پزشک» همیشه اول میآید', () => {
|
||||
render(<ResourceSelect resources={[resource()]} onSelect={vi.fn()} />);
|
||||
|
||||
const buttons = screen.getAllByRole('button');
|
||||
expect(buttons).toHaveLength(2);
|
||||
expect(buttons[0]).toHaveTextContent('نوبت با پزشک');
|
||||
expect(buttons[1]).toHaveTextContent('کندلا2021');
|
||||
});
|
||||
|
||||
it('نوع منبع بهعنوان برچسب دیده میشود', () => {
|
||||
render(<ResourceSelect resources={[resource()]} onSelect={vi.fn()} />);
|
||||
expect(screen.getByText('دستگاه لیزر')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('انتخاب «نوبت با پزشک» مقدار null میفرستد', async () => {
|
||||
const onSelect = vi.fn();
|
||||
render(<ResourceSelect resources={[resource()]} onSelect={onSelect} />);
|
||||
|
||||
await userEvent.click(screen.getByText('نوبت با پزشک'));
|
||||
expect(onSelect).toHaveBeenCalledWith(null);
|
||||
});
|
||||
|
||||
it('انتخاب منبع، خودِ آبجکت منبع را میفرستد', async () => {
|
||||
const onSelect = vi.fn();
|
||||
const r = resource();
|
||||
render(<ResourceSelect resources={[r]} onSelect={onSelect} />);
|
||||
|
||||
await userEvent.click(screen.getByText('کندلا2021'));
|
||||
expect(onSelect).toHaveBeenCalledWith(r);
|
||||
});
|
||||
|
||||
it('تا سه سرویس با نام میآید و بقیه با +n', () => {
|
||||
const services = ['الف', 'ب', 'ج', 'د', 'ه'].map((n, i) => ({ uuid: `s${i}`, name: n }));
|
||||
render(<ResourceSelect resources={[resource({ services })]} onSelect={vi.fn()} />);
|
||||
|
||||
expect(screen.getByText('الف، ب، ج +2')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('منبعِ بدون سرویس، زیرنویس خالی نمیسازد', () => {
|
||||
render(<ResourceSelect resources={[resource({ services: [] })]} onSelect={vi.fn()} />);
|
||||
|
||||
// فقط زیرنویسِ کارتِ پزشک میماند.
|
||||
expect(screen.getAllByRole('button')[1].textContent).toBe('کندلا2021دستگاه لیزر');
|
||||
});
|
||||
|
||||
it('منبعِ بدون type برچسب نمیگیرد و نمیشکند', () => {
|
||||
render(<ResourceSelect resources={[resource({ type: null })]} onSelect={vi.fn()} />);
|
||||
expect(screen.getByText('کندلا2021')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user