- Added OTP login functionality in driver.mjs to handle user authentication with a fixed code in dev environment. - Enhanced RoleRoute component in App.tsx to support clinic-scoped doctor roles and permissions. - Updated ClinicDoctorsManager component to include pagination and search functionality for better user experience. - Refactored tests for ClinicDoctorsManager to cover new features and ensure proper API mocking. - Adjusted permissions in settingsMenu.ts and PracticeDomainSettingsPage.tsx to align with updated backend requirements. - Created RoleRoute.test.tsx to validate role-based access logic for different user scenarios.
130 lines
5.6 KiB
TypeScript
130 lines
5.6 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||
import { screen, waitFor } from '@testing-library/react';
|
||
import { renderWithProviders } from '../test/utils';
|
||
import { api } from '../lib/api';
|
||
import ClinicDoctorsManager from './ClinicDoctorsManager';
|
||
|
||
vi.mock('../lib/api', () => ({ api: { get: vi.fn(), post: vi.fn(), patch: vi.fn(), delete: vi.fn() } }));
|
||
|
||
const DOCTOR = {
|
||
id: '1',
|
||
uuid: 'doc-1',
|
||
name: 'پزشک دعوتشده',
|
||
gender: null,
|
||
degree: null,
|
||
img: [],
|
||
specialties: [],
|
||
active: false, // نوبتدهی آنلاینِ خودِ پزشک خاموش است
|
||
};
|
||
|
||
/** پاسخها بر اساس مسیر تفکیک میشوند، چون سه کوئری موازی میروند. */
|
||
function mockApi({ doctors = [DOCTOR], total = 1, permissions = [] as any[], failDoctors = false } = {}) {
|
||
(api.get as any).mockImplementation((url: string) => {
|
||
if (url.includes('/doctor-permissions')) return Promise.resolve({ data: permissions });
|
||
if (url.includes('/invitations')) return Promise.resolve({ data: [] });
|
||
if (url.includes('/doctor-list/')) {
|
||
return failDoctors
|
||
? Promise.reject(new Error('boom'))
|
||
: Promise.resolve({ data: doctors, meta: { totalRecords: total, totalPages: 1, currentPage: 1 } });
|
||
}
|
||
return Promise.resolve({ data: [] });
|
||
});
|
||
}
|
||
|
||
describe('ClinicDoctorsManager', () => {
|
||
beforeEach(() => vi.clearAllMocks());
|
||
|
||
it('صفحه و سقف را به سرور میفرستد — وگرنه backend سر ۱۰ پزشک بیصدا میبرد', async () => {
|
||
mockApi();
|
||
renderWithProviders(<ClinicDoctorsManager clinicUuid="cl-1" />);
|
||
|
||
await waitFor(() => expect(api.get).toHaveBeenCalled());
|
||
const listCall = (api.get as any).mock.calls.find((c: any[]) => c[0].includes('/doctor-list/'));
|
||
expect(listCall[0]).toContain('page=1');
|
||
expect(listCall[0]).toContain('limit=10');
|
||
});
|
||
|
||
it('شمارندهٔ تب از meta میآید، نه از طول صفحهٔ جاری', async () => {
|
||
mockApi({ doctors: [DOCTOR], total: 25 });
|
||
renderWithProviders(<ClinicDoctorsManager clinicUuid="cl-1" />);
|
||
|
||
expect(await screen.findByText(/پزشکان \(۲۵\)/)).toBeInTheDocument();
|
||
});
|
||
|
||
it('«نوبتدهی آنلاین» و «دسترسی در کلینیک» دو ستون جدا هستند', async () => {
|
||
mockApi();
|
||
renderWithProviders(<ClinicDoctorsManager clinicUuid="cl-1" />);
|
||
|
||
expect(await screen.findByText('دسترسی در کلینیک')).toBeInTheDocument();
|
||
expect(screen.getByText('نوبتدهی آنلاین')).toBeInTheDocument();
|
||
});
|
||
|
||
it('شمار مجوزها زیر همان بجِ دسترسی میآید، نه در ستون جدا', async () => {
|
||
mockApi({
|
||
permissions: [{
|
||
doctor_uuid: 'doc-1',
|
||
active: true,
|
||
permissions: { resources: { appointments: { view: true, create: false } } },
|
||
}],
|
||
});
|
||
renderWithProviders(<ClinicDoctorsManager clinicUuid="cl-1" />);
|
||
|
||
expect(await screen.findByText('۱ از ۲ مجوز')).toBeInTheDocument();
|
||
expect(screen.queryByText('مجوزها')).not.toBeInTheDocument();
|
||
});
|
||
|
||
it('پزشکِ بدون ردیف مجوز، «پیشفرض» و دسترسی فعال میگیرد', async () => {
|
||
mockApi({ permissions: [] });
|
||
renderWithProviders(<ClinicDoctorsManager clinicUuid="cl-1" />);
|
||
|
||
expect(await screen.findByText('پیشفرض')).toBeInTheDocument();
|
||
});
|
||
|
||
it('ردیف مجوزِ خاموش، «غیرفعال» نشان میدهد و شمار مجوزها را میآورد', async () => {
|
||
mockApi({
|
||
permissions: [{
|
||
doctor_uuid: 'doc-1',
|
||
active: false,
|
||
permissions: { resources: { appointments: { view: true, create: false } } },
|
||
}],
|
||
});
|
||
renderWithProviders(<ClinicDoctorsManager clinicUuid="cl-1" />);
|
||
|
||
expect(await screen.findByText('۱ از ۲ مجوز')).toBeInTheDocument();
|
||
// دو «غیرفعال»: یکی دسترسیِ کلینیک، یکی نوبتدهی آنلاین. پیش از این یک بج جای
|
||
// هر دو مینشست و همین ابهام، پزشکِ سالم را «غیرفعال» نشان میداد.
|
||
expect(screen.getAllByText('غیرفعال')).toHaveLength(2);
|
||
});
|
||
|
||
it('دسترسیِ فعال با نوبتدهیِ خاموش قاطی نمیشود', async () => {
|
||
mockApi({
|
||
permissions: [{
|
||
doctor_uuid: 'doc-1',
|
||
active: true,
|
||
permissions: { resources: { appointments: { view: true } } },
|
||
}],
|
||
});
|
||
renderWithProviders(<ClinicDoctorsManager clinicUuid="cl-1" />);
|
||
|
||
// دسترسی فعال است…
|
||
expect(await screen.findByText('فعال')).toBeInTheDocument();
|
||
// …ولی نوبتدهی آنلاینِ خودِ پزشک همچنان خاموش.
|
||
expect(screen.getByText('غیرفعال')).toBeInTheDocument();
|
||
});
|
||
|
||
it('خطای فهرست، پیام خطا میدهد نه حالت خالی', async () => {
|
||
mockApi({ failDoctors: true });
|
||
renderWithProviders(<ClinicDoctorsManager clinicUuid="cl-1" />);
|
||
|
||
expect(await screen.findByText('فهرست پزشکان بارگذاری نشد')).toBeInTheDocument();
|
||
expect(screen.queryByText('هیچ پزشکی به این کلینیک متصل نیست')).not.toBeInTheDocument();
|
||
});
|
||
|
||
it('فهرست خالی، پیام خالی میدهد', async () => {
|
||
mockApi({ doctors: [], total: 0 });
|
||
renderWithProviders(<ClinicDoctorsManager clinicUuid="cl-1" />);
|
||
|
||
expect(await screen.findByText('هیچ پزشکی به این کلینیک متصل نیست')).toBeInTheDocument();
|
||
});
|
||
});
|