200 lines
5.7 KiB
TypeScript
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();
|
|
});
|
|
});
|
|
});
|