Files
clinicpro/assets/admin/pages/SecretaryDashboard.test.tsx
T
hamed 5c4976d65f feat: Implement secretary permissions enforcement across multiple resources
- Added SecretaryAccessChecker to manage resource access for secretaries.
- Integrated permission checks for payments, inventory, and tags in relevant controllers.
- Updated PaymentController and PaymentMethodController to enforce secretary permissions.
- Enhanced TenantTagController to check permissions for tag management actions.
- Introduced tests for secretary resource enforcement, ensuring proper access control.
- Updated DoctorSecretary entity to include inventory and tags permissions.
- Created a comprehensive audit document for secretary permissions coverage and enforcement.
- Fixed potential crashes in SecretaryDashboard when rendering without doctor data.
2026-07-23 16:36:35 +03:30

85 lines
3.2 KiB
TypeScript

import { describe, it, expect, beforeEach, vi } from 'vitest';
import { screen } from '@testing-library/react';
import { renderWithProviders } from '../test/utils';
vi.mock('../lib/api', () => ({
api: { get: vi.fn(), post: vi.fn(), patch: vi.fn(), put: vi.fn(), delete: vi.fn() },
ApiError: class extends Error {},
}));
import { api } from '../lib/api';
import { useAuthStore } from '../stores/authStore';
import DashboardPage from './DashboardPage';
const get = api.get as ReturnType<typeof vi.fn>;
const perms = {
version: 1,
resources: { appointments: { view: true, create: true, cancel: false, update_status: true } },
};
/** منشیِ scope=clinic: پاسخ کلید `doctor` ندارد — نباید کرش کند. */
const clinicScope = {
success: true,
data: {
scope: 'clinic',
clinic: { uuid: 'clinic-1', name: 'کلینیک نمونه' },
permissions: perms,
stats: { today_appointments: 3, tomorrow_appointments: 5 },
today_appointments: [],
},
};
const doctorScope = {
success: true,
data: {
scope: 'doctor',
doctor: { uuid: 'doc-1', name: 'دکتر رضایی', degree: 'متخصص قلب' },
permissions: perms,
stats: { today_appointments: 1, tomorrow_appointments: 2 },
today_appointments: [],
},
};
describe('SecretaryDashboard', () => {
beforeEach(() => {
get.mockReset();
useAuthStore.setState({ primaryRole: 'secretary', dbUuid: 'clinic-1', context: null } as never);
});
it('منشیِ کلینیک را بدون کرش رندر می‌کند (پاسخ بدون فیلد doctor)', async () => {
get.mockImplementation((url: string) =>
url.includes('/dashboard/secretary') ? Promise.resolve(clinicScope) : Promise.resolve({ success: true, data: [] }),
);
renderWithProviders(<DashboardPage />, { route: '/admin/dashboard' });
expect(await screen.findByText('داشبورد منشی')).toBeInTheDocument();
expect(screen.getAllByText(/کلینیک نمونه/).length).toBeGreaterThan(0);
expect(screen.getAllByText('نوبت‌های امروز').length).toBeGreaterThan(0);
});
it('منشیِ مطب پزشک را با نام پزشک رندر می‌کند', async () => {
get.mockImplementation((url: string) =>
url.includes('/dashboard/secretary') ? Promise.resolve(doctorScope) : Promise.resolve({ success: true, data: [] }),
);
renderWithProviders(<DashboardPage />, { route: '/admin/dashboard' });
expect(await screen.findByText('داشبورد منشی')).toBeInTheDocument();
expect(screen.getAllByText(/دکتر رضایی/).length).toBeGreaterThan(0);
});
it('پاسخ خالی/خطا را بدون کرش با پیام مناسب نشان می‌دهد', async () => {
get.mockImplementation((url: string) =>
url.includes('/dashboard/secretary')
? Promise.resolve({ success: false, data: null, errors: [{ code: 'X', message: 'x' }] })
: Promise.resolve({ success: true, data: [] }),
);
renderWithProviders(<DashboardPage />, { route: '/admin/dashboard' });
expect(await screen.findByText('در حال حاضر اطلاعات داشبورد در دسترس نیست.')).toBeInTheDocument();
});
});