import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { render, screen, waitFor } from '@testing-library/react'; import { UploadQuota } from './UploadQuota'; import { getUserQuota, TrackUploadError } from '../services/trackService'; import { useAuthStore } from '@/features/auth/store/authStore'; // Mock trackService vi.mock('../services/trackService', () => ({ getUserQuota: vi.fn(), TrackUploadError: class TrackUploadError extends Error { constructor( message: string, public code: string, public retryable: boolean = false, ) { super(message); this.name = 'TrackUploadError'; } }, })); // Mock useAuthStore vi.mock('@/features/auth/store/authStore', () => ({ useAuthStore: vi.fn(), })); describe('UploadQuota', () => { const mockQuota = { tracks_count: 5, tracks_limit: 1000, storage_used: 50 * 1024 * 1024, // 50MB storage_limit: 100 * 1024 * 1024 * 1024, // 100GB }; beforeEach(() => { vi.clearAllMocks(); }); afterEach(() => { vi.restoreAllMocks(); }); it('should render loading state initially', async () => { vi.mocked(getUserQuota).mockImplementation(() => new Promise(() => {})); // Never resolves render(); expect(screen.getByText('Chargement du quota...')).toBeInTheDocument(); }); it('should display quota information when loaded', async () => { vi.mocked(getUserQuota).mockResolvedValue(mockQuota); render(); await waitFor(() => { expect(screen.getByText("Quota d'upload")).toBeInTheDocument(); expect(screen.getByText('Tracks')).toBeInTheDocument(); expect(screen.getByText(/5 \/ 1000/)).toBeInTheDocument(); expect(screen.getByText('Stockage')).toBeInTheDocument(); expect(screen.getByText(/50 MB/)).toBeInTheDocument(); expect(screen.getByText(/100 GB/)).toBeInTheDocument(); }); }); it('should display tracks quota with progress bar', async () => { vi.mocked(getUserQuota).mockResolvedValue(mockQuota); render(); await waitFor(() => { const progressBars = screen.getAllByRole('progressbar'); expect(progressBars.length).toBeGreaterThan(0); }); }); it('should display storage quota with progress bar', async () => { vi.mocked(getUserQuota).mockResolvedValue(mockQuota); render(); await waitFor(() => { const progressBars = screen.getAllByRole('progressbar'); expect(progressBars.length).toBeGreaterThanOrEqual(2); }); }); it('should show warning when quota is near limit', async () => { const nearLimitQuota = { tracks_count: 950, tracks_limit: 1000, storage_used: 95 * 1024 * 1024 * 1024, // 95GB storage_limit: 100 * 1024 * 1024 * 1024, // 100GB }; vi.mocked(getUserQuota).mockResolvedValue(nearLimitQuota); render(); await waitFor(() => { expect( screen.getByText(/Votre quota d'upload approche de sa limite/), ).toBeInTheDocument(); }); }); it('should show error state when quota is exceeded', async () => { const exceededQuota = { tracks_count: 1000, tracks_limit: 1000, storage_used: 100 * 1024 * 1024 * 1024, // 100GB storage_limit: 100 * 1024 * 1024 * 1024, // 100GB }; vi.mocked(getUserQuota).mockResolvedValue(exceededQuota); render(); await waitFor(() => { expect(screen.getByText('Limite de tracks atteinte')).toBeInTheDocument(); expect( screen.getByText('Limite de stockage atteinte'), ).toBeInTheDocument(); }); }); it('should display error message when API call fails', async () => { const error = new TrackUploadError('Failed to load quota', 'SERVER', false); vi.mocked(getUserQuota).mockRejectedValue(error); render(); await waitFor(() => { expect(screen.getByText('Failed to load quota')).toBeInTheDocument(); }); }); it('should call onQuotaUpdated when quota is loaded', async () => { const onQuotaUpdated = vi.fn(); vi.mocked(getUserQuota).mockResolvedValue(mockQuota); render(); await waitFor(() => { expect(onQuotaUpdated).toHaveBeenCalledWith(mockQuota); }); }); it('should reload quota when userId changes', async () => { vi.mocked(getUserQuota).mockResolvedValue(mockQuota); const { rerender } = render(); await waitFor(() => { expect(getUserQuota).toHaveBeenCalledWith(123); }); rerender(); await waitFor(() => { expect(getUserQuota).toHaveBeenCalledWith(456); }); }); it('should format file sizes correctly', async () => { const smallQuota = { tracks_count: 0, tracks_limit: 1000, storage_used: 1024, // 1KB storage_limit: 1024 * 1024, // 1MB }; vi.mocked(getUserQuota).mockResolvedValue(smallQuota); render(); await waitFor(() => { expect(screen.getByText(/1 KB/)).toBeInTheDocument(); expect(screen.getByText(/1 MB/)).toBeInTheDocument(); }); }); it('should handle empty quota (no tracks)', async () => { const emptyQuota = { tracks_count: 0, tracks_limit: 1000, storage_used: 0, storage_limit: 100 * 1024 * 1024 * 1024, }; vi.mocked(getUserQuota).mockResolvedValue(emptyQuota); render(); await waitFor(() => { expect(screen.getByText(/0 \/ 1000/)).toBeInTheDocument(); expect(screen.getByText(/0 Bytes/)).toBeInTheDocument(); }); }); });