Files
nobat724_front/services/services.test.js
T
hamed 54bebbd41a 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.
2026-08-09 10:45:52 +03:30

129 lines
5.3 KiB
JavaScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
// --- clinicApi (native fetch) ---
import { getClinicDoctors } from '@/services/clinicApi';
describe('getClinicDoctors', () => {
beforeEach(() => vi.stubGlobal('fetch', vi.fn()));
it('پاسخ double-nested → { data, page }', async () => {
fetch.mockResolvedValue({
ok: true,
json: () =>
Promise.resolve({
data: { data: [{ uuid: 'd1' }, { uuid: 'd2' }], meta: { totalPages: 3, currentPage: 1 } },
}),
});
const out = await getClinicDoctors('my-clinic', { page: 1 });
expect(out.data).toHaveLength(2);
expect(out.page).toEqual({ total_pages: 3, current: 1 });
const calledUrl = fetch.mock.calls[0][0];
expect(calledUrl).toContain('/api/v1/clinic/doctor-list/my-clinic');
});
it('بدون meta → صفحه‌بندی پیش‌فرض', async () => {
fetch.mockResolvedValue({ ok: true, json: () => Promise.resolve({ data: { data: [] } }) });
const out = await getClinicDoctors('x');
expect(out.page).toEqual({ total_pages: 1, current: 1 });
});
it('پاسخ ناموفق (ok=false) → shape خالی پیش‌فرض', async () => {
fetch.mockResolvedValue({ ok: false, status: 500, text: () => Promise.resolve('err') });
const out = await getClinicDoctors('x');
expect(out).toEqual({ data: [], page: { total_pages: 1, current: 1 } });
});
it('خطای شبکه → shape خالی پیش‌فرض', async () => {
fetch.mockRejectedValue(new Error('net'));
const out = await getClinicDoctors('x');
expect(out.data).toEqual([]);
});
});
// --- response.js wrappers (mock axios layer) ---
vi.mock('@/services/api', () => ({
default: {
get: vi.fn(() => Promise.resolve({})),
post: vi.fn(() => Promise.resolve({})),
patch: vi.fn(() => Promise.resolve({})),
delete: vi.fn(() => Promise.resolve({})),
},
}));
import api from '@/services/api';
import { request } from '@/services/response';
describe('request wrappers — قرارداد به لایه‌ی API', () => {
beforeEach(() => {
api.get.mockClear();
api.post.mockClear();
});
it('getUserProfile → GET مسیر درست با requireAuth', () => {
request.getUserProfile('u1');
expect(api.get).toHaveBeenCalledWith('/api/v1/user-profile/u1', { requireAuth: true });
});
it('getUserInfo → GET oauth/userinfo با requireAuth', () => {
request.getUserInfo();
expect(api.get).toHaveBeenCalledWith('oauth/userinfo', { requireAuth: true });
});
it('postAppointment → POST با body و requireAuth', () => {
request.postAppointment({ slot: 5 });
expect(api.post).toHaveBeenCalledWith('api/v1/appointment', { slot: 5 }, { requireAuth: true });
});
// --- نوبت‌دهی منبع‌محور ---
it('getBookingResources → بدون کلینیک، مسیر ساده', () => {
request.getBookingResources('doc-1');
expect(api.get.mock.calls[0][0]).toBe('api/v1/appointment-booking-resources/doc-1');
});
it('getBookingResources → با کلینیک، clinic_uuid با ? می‌آید', () => {
request.getBookingResources('doc-1', 'cl-1');
expect(api.get.mock.calls[0][0]).toBe(
'api/v1/appointment-booking-resources/doc-1?clinic_uuid=cl-1'
);
});
it('getResourceSlots → هر سرویس یک service_item_uuids[] جدا می‌گیرد', () => {
request.getResourceSlots('res-1', '2026-08-10', ['s1', 's2']);
const url = api.get.mock.calls[0][0];
expect(url).toContain('resource_uuid=res-1');
expect(url).toContain('date=2026-08-10');
expect(url).toContain('&service_item_uuids[]=s1');
expect(url).toContain('&service_item_uuids[]=s2');
});
it('getResourceSlots → uuid با کاراکتر ویژه encode می‌شود', () => {
request.getResourceSlots('res-1', '2026-08-10', ['a/b']);
expect(api.get.mock.calls[0][0]).toContain('service_item_uuids[]=a%2Fb');
});
it('getResourceSlots → فهرست خالی هیچ پارامتر سرویسی نمی‌سازد', () => {
request.getResourceSlots('res-1', '2026-08-10', []);
expect(api.get.mock.calls[0][0]).not.toContain('service_item_uuids');
});
it('getResourceMonthAvailability → سال و ماه و سرویس‌ها در query', () => {
request.getResourceMonthAvailability('res-1', 2026, 9, ['s1']);
const url = api.get.mock.calls[0][0];
expect(url).toContain('api/v1/appointment-resource-month-availability/res-1');
expect(url).toContain('year=2026');
expect(url).toContain('month=9');
expect(url).toContain('&service_item_uuids[]=s1');
});
it('هر سه اندپوینت عمومی‌اند — هدر Authorization حذف می‌شود', () => {
request.getBookingResources('doc-1');
request.getResourceSlots('res-1', '2026-08-10', ['s1']);
request.getResourceMonthAvailability('res-1', 2026, 9, ['s1']);
for (const call of api.get.mock.calls) {
expect(call[1]?.headers?.Authorization).toBe('');
}
});
});