import { describe, it, expect, beforeEach, vi } from 'vitest'; import { act, renderHook, waitFor } from '@testing-library/react'; import { renderHookWithClient } 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 { useSubscription } from '@/hooks/useSubscription'; import { usePaymentConfig } from '@/hooks/usePaymentConfig'; import { usePwaInstall } from '@/hooks/usePwaInstall'; const get = api.get as ReturnType; beforeEach(() => { localStorage.clear(); get.mockReset(); useAuthStore.setState({ primaryRole: null }); }); describe('useSubscription', () => { it('برای نقش doctor فعال است و hasFeature/maxSecretaries را برمی‌گرداند', async () => { useAuthStore.setState({ primaryRole: 'doctor' }); get.mockResolvedValue({ data: { subscription: { plan: { features: { sms: true, claims: false }, max_secretaries: 3 }, days_remaining: 5, }, }, }); const { result } = renderHookWithClient(() => useSubscription()); await waitFor(() => expect(result.current.hasPlan).toBe(true)); expect(result.current.hasFeature('sms')).toBe(true); expect(result.current.hasFeature('claims')).toBe(false); expect(result.current.hasFeature('unknown')).toBe(false); expect(result.current.maxSecretaries).toBe(3); expect(result.current.isExpiringSoon).toBe(true); }); it('نبود اشتراک: امکانات را از effective_plan (پلن free) می‌گیرد', async () => { useAuthStore.setState({ primaryRole: 'doctor' }); get.mockResolvedValue({ data: { subscription: null, effective_plan: { features: { patient_records: true, services: true, sms_panel: true }, max_secretaries: 1 }, }, }); const { result } = renderHookWithClient(() => useSubscription()); await waitFor(() => expect(result.current.hasFeature('patient_records')).toBe(true)); expect(result.current.hasFeature('services')).toBe(true); expect(result.current.hasFeature('sms_panel')).toBe(true); expect(result.current.hasPlan).toBe(false); expect(result.current.maxSecretaries).toBe(1); }); it('برای نقش admin غیرفعال است (query اجرا نمی‌شود)', async () => { useAuthStore.setState({ primaryRole: 'admin' }); const { result } = renderHookWithClient(() => useSubscription()); expect(result.current.hasPlan).toBe(false); expect(get).not.toHaveBeenCalled(); }); }); describe('usePaymentConfig', () => { it('test_mode را به isTestMode مپ می‌کند', async () => { get.mockResolvedValue({ data: { test_mode: true } }); const { result } = renderHookWithClient(() => usePaymentConfig()); await waitFor(() => expect(result.current.isTestMode).toBe(true)); }); it('پیش‌فرض isTestMode=false', () => { get.mockResolvedValue({ data: { test_mode: false } }); const { result } = renderHookWithClient(() => usePaymentConfig()); expect(result.current.isTestMode).toBe(false); }); }); describe('usePwaInstall', () => { it('رویداد beforeinstallprompt را می‌گیرد', () => { const { result } = renderHook(() => usePwaInstall()); expect(result.current.promptEvent).toBeNull(); act(() => { window.dispatchEvent(new Event('beforeinstallprompt')); }); expect(result.current.promptEvent).not.toBeNull(); }); it('dismiss در localStorage ذخیره و isDismissed را true می‌کند', () => { const { result } = renderHook(() => usePwaInstall()); expect(result.current.isDismissed).toBe(false); act(() => result.current.dismiss()); expect(localStorage.getItem('pwa-dismissed')).toBe('1'); expect(result.current.isDismissed).toBe(true); }); it('اگر قبلاً dismiss شده باشد، اولیه isDismissed=true', () => { localStorage.setItem('pwa-dismissed', '1'); const { result } = renderHook(() => usePwaInstall()); expect(result.current.isDismissed).toBe(true); }); });