veza/apps/web/src/features/tracks/components/UploadQuota.test.tsx

200 lines
5.7 KiB
TypeScript

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(<UploadQuota userId="me" />);
expect(screen.getByText('Chargement du quota...')).toBeInTheDocument();
});
it('should display quota information when loaded', async () => {
vi.mocked(getUserQuota).mockResolvedValue(mockQuota);
render(<UploadQuota userId="me" />);
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(<UploadQuota userId={123} />);
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(<UploadQuota userId={123} />);
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(<UploadQuota userId="me" />);
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(<UploadQuota userId="me" />);
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(<UploadQuota userId="me" />);
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(<UploadQuota userId="me" onQuotaUpdated={onQuotaUpdated} />);
await waitFor(() => {
expect(onQuotaUpdated).toHaveBeenCalledWith(mockQuota);
});
});
it('should reload quota when userId changes', async () => {
vi.mocked(getUserQuota).mockResolvedValue(mockQuota);
const { rerender } = render(<UploadQuota userId={123} />);
await waitFor(() => {
expect(getUserQuota).toHaveBeenCalledWith(123);
});
rerender(<UploadQuota userId={456} />);
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(<UploadQuota userId="me" />);
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(<UploadQuota userId="me" />);
await waitFor(() => {
expect(screen.getByText(/0 \/ 1000/)).toBeInTheDocument();
expect(screen.getByText(/0 Bytes/)).toBeInTheDocument();
});
});
});