Files
clinicpro/assets/admin/components/layout/PurchaseSubscriptionSidebar.test.tsx
T
hamedandClaude Opus 4.8 221dce29c3 fix(secretary): route «نوبت‌دهی» settings to the scope-correct variant
A clinic-scoped secretary opening «مدیریت نوبت دهی» hit 404s
(/api/v1/doctor/{clinicUuid}, available-locations, weekly-schedule): the
permission-only secretary filter ignored each item's `roles`, so BOTH
appointment-settings variants (doctor → /admin/appointment-settings,
clinic → /admin/settings/appointment-settings) showed. Clicking the doctor
variant landed on the personal page, which has no doctor uuid for a clinic
secretary and fell back to the clinic uuid — not a doctor → 404.

Make the secretary settings filter scope-aware in both navs
(PurchaseSubscriptionSidebar + menuForRole): a role-variant item is kept only
when its `roles` matches the secretary's context scope (clinic→'clinic',
else 'doctor'). The clinic page already threads clinic_uuid through
ScheduleSection, so once routed correctly the flow works end-to-end.

Test: appointment variant resolves to the clinic route under clinic scope.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 18:11:41 +03:30

63 lines
3.5 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { screen } from '@testing-library/react';
import { renderWithProviders } from '../../test/utils';
import { useAuthStore } from '../../stores/authStore';
import PurchaseSubscriptionSidebar from './PurchaseSubscriptionSidebar';
describe('PurchaseSubscriptionSidebar — settings menu', () => {
it('lists secretary and staff management (moved out of the main nav)', () => {
renderWithProviders(<PurchaseSubscriptionSidebar active="staff" />, { route: '/admin/staff' });
const secretary = screen.getByRole('link', { name: 'مدیریت منشی' });
const staff = screen.getByRole('link', { name: 'پرسنل' });
expect(secretary).toHaveAttribute('href', '/admin/my-secretaries');
expect(staff).toHaveAttribute('href', '/admin/staff');
});
it('highlights the active item (aria-current) for staff', () => {
renderWithProviders(<PurchaseSubscriptionSidebar active="staff" />, { route: '/admin/staff' });
expect(screen.getByRole('link', { name: 'پرسنل' })).toHaveAttribute('aria-current', 'page');
expect(screen.getByRole('link', { name: 'مدیریت منشی' })).not.toHaveAttribute('aria-current');
});
it('برای منشی فقط آیتم‌های مجاز را نشان می‌دهد (staff مجاز، بقیه پنهان)', () => {
useAuthStore.setState({
primaryRole: 'secretary',
context: { scope: 'clinic', permissions: { resources: { staff: { view: true } } } },
} as any);
renderWithProviders(<PurchaseSubscriptionSidebar active="staff" />, { route: '/admin/staff' });
// مجاز
expect(screen.getByRole('link', { name: 'پرسنل' })).toHaveAttribute('href', '/admin/staff');
expect(screen.getByRole('link', { name: 'حساب کاربری' })).toBeInTheDocument();
// owner-only / بدون مجوز → پنهان
expect(screen.queryByRole('link', { name: 'مدیریت منشی' })).not.toBeInTheDocument();
expect(screen.queryByRole('link', { name: 'خرید اشتراک' })).not.toBeInTheDocument();
expect(screen.queryByRole('link', { name: 'مدیریت تخفیف‌ها' })).not.toBeInTheDocument();
useAuthStore.setState({ primaryRole: null, context: null } as any);
});
it('«مدیریت نوبت دهی» را با scope منشی به واریانتِ درست لینک می‌کند', () => {
// منشیِ کلینیک → صفحهٔ کلینیک (نه صفحهٔ پزشکِ مستقل که uuid کلینیک را
// به‌جای doctor می‌فرستد و ۴۰۴ می‌گرفت).
useAuthStore.setState({
primaryRole: 'secretary',
context: { scope: 'clinic', permissions: { resources: { appointment_settings: { view: true } } } },
} as any);
renderWithProviders(<PurchaseSubscriptionSidebar active="appointment" />, { route: '/admin/settings/appointment-settings' });
const link = screen.getByRole('link', { name: 'مدیریت نوبت دهی' });
expect(link).toHaveAttribute('href', '/admin/settings/appointment-settings');
useAuthStore.setState({ primaryRole: null, context: null } as any);
});
// regression: the settings menu must stay visible on mobile (was `hidden lg:block`,
// which dropped the whole menu below the lg breakpoint → no settings nav on phones).
it('is not hidden on mobile', () => {
renderWithProviders(<PurchaseSubscriptionSidebar active="staff" />, { route: '/admin/staff' });
const nav = screen.getByRole('complementary', { name: 'منوی تنظیمات' });
expect(nav.className).not.toMatch(/\bhidden\b/);
});
});