218 lines
6.2 KiB
TypeScript
218 lines
6.2 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
import { render, screen, waitFor } from '@testing-library/react';
|
|
import userEvent from '@testing-library/user-event';
|
|
import { TrackDownloadButton } from './TrackDownloadButton';
|
|
import {
|
|
downloadTrack,
|
|
TrackDownloadError,
|
|
} from '../services/trackDownloadService';
|
|
import { useToast } from '@/hooks/useToast';
|
|
|
|
// Mock dependencies
|
|
vi.mock('../services/trackDownloadService');
|
|
vi.mock('@/hooks/useToast');
|
|
|
|
describe('TrackDownloadButton', () => {
|
|
const mockToast = {
|
|
success: vi.fn(),
|
|
error: vi.fn(),
|
|
warning: vi.fn(),
|
|
info: vi.fn(),
|
|
toast: vi.fn(),
|
|
};
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
vi.mocked(useToast).mockReturnValue(mockToast);
|
|
});
|
|
|
|
it('should render download button', () => {
|
|
render(<TrackDownloadButton trackId={123} />);
|
|
|
|
expect(screen.getByText('Télécharger')).toBeInTheDocument();
|
|
expect(screen.getByRole('button')).toBeInTheDocument();
|
|
});
|
|
|
|
it('should download track when button is clicked', async () => {
|
|
vi.mocked(downloadTrack).mockResolvedValue(undefined);
|
|
|
|
render(<TrackDownloadButton trackId={123} />);
|
|
|
|
const button = screen.getByRole('button');
|
|
await userEvent.click(button);
|
|
|
|
await waitFor(() => {
|
|
expect(downloadTrack).toHaveBeenCalledWith(123, {
|
|
shareToken: undefined,
|
|
filename: undefined,
|
|
onProgress: undefined,
|
|
});
|
|
});
|
|
|
|
expect(mockToast.success).toHaveBeenCalledWith('Téléchargement terminé');
|
|
});
|
|
|
|
it('should download track with share token', async () => {
|
|
vi.mocked(downloadTrack).mockResolvedValue(undefined);
|
|
|
|
render(<TrackDownloadButton trackId={123} shareToken="test-token" />);
|
|
|
|
const button = screen.getByRole('button');
|
|
await userEvent.click(button);
|
|
|
|
await waitFor(() => {
|
|
expect(downloadTrack).toHaveBeenCalledWith(123, {
|
|
shareToken: 'test-token',
|
|
filename: undefined,
|
|
onProgress: undefined,
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should show loading state during download', async () => {
|
|
let resolveDownload: () => void;
|
|
const downloadPromise = new Promise<void>((resolve) => {
|
|
resolveDownload = resolve;
|
|
});
|
|
vi.mocked(downloadTrack).mockReturnValue(downloadPromise);
|
|
|
|
render(<TrackDownloadButton trackId={123} />);
|
|
|
|
const button = screen.getByRole('button');
|
|
await userEvent.click(button);
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByText(/Téléchargement.../i)).toBeInTheDocument();
|
|
});
|
|
|
|
expect(button).toBeDisabled();
|
|
|
|
// Résoudre le téléchargement
|
|
resolveDownload!();
|
|
await waitFor(() => {
|
|
expect(screen.getByText('Télécharger')).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
it('should show progress bar when showProgress is true', async () => {
|
|
let progressCallback: (progress: number) => void;
|
|
const downloadPromise = new Promise<void>((resolve) => {
|
|
vi.mocked(downloadTrack).mockImplementation((id, options) => {
|
|
if (options?.onProgress) {
|
|
progressCallback = options.onProgress;
|
|
}
|
|
setTimeout(() => resolve(), 100);
|
|
return Promise.resolve();
|
|
});
|
|
});
|
|
|
|
render(<TrackDownloadButton trackId={123} showProgress={true} />);
|
|
|
|
const button = screen.getByRole('button');
|
|
await userEvent.click(button);
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByRole('progressbar')).toBeInTheDocument();
|
|
});
|
|
|
|
// Simuler la progression
|
|
if (progressCallback!) {
|
|
progressCallback(50);
|
|
await waitFor(() => {
|
|
expect(screen.getByText(/50%/i)).toBeInTheDocument();
|
|
});
|
|
}
|
|
});
|
|
|
|
it('should display error message on download failure', async () => {
|
|
const error = new TrackDownloadError('Download failed', 'NETWORK', true);
|
|
vi.mocked(downloadTrack).mockRejectedValue(error);
|
|
|
|
render(<TrackDownloadButton trackId={123} />);
|
|
|
|
const button = screen.getByRole('button');
|
|
await userEvent.click(button);
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByText('Download failed')).toBeInTheDocument();
|
|
});
|
|
|
|
expect(mockToast.error).toHaveBeenCalledWith('Download failed');
|
|
});
|
|
|
|
it('should call onDownloadStart callback', async () => {
|
|
const onDownloadStart = vi.fn();
|
|
vi.mocked(downloadTrack).mockResolvedValue(undefined);
|
|
|
|
render(
|
|
<TrackDownloadButton trackId={123} onDownloadStart={onDownloadStart} />,
|
|
);
|
|
|
|
const button = screen.getByRole('button');
|
|
await userEvent.click(button);
|
|
|
|
await waitFor(() => {
|
|
expect(onDownloadStart).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
it('should call onDownloadComplete callback', async () => {
|
|
const onDownloadComplete = vi.fn();
|
|
vi.mocked(downloadTrack).mockResolvedValue(undefined);
|
|
|
|
render(
|
|
<TrackDownloadButton
|
|
trackId={123}
|
|
onDownloadComplete={onDownloadComplete}
|
|
/>,
|
|
);
|
|
|
|
const button = screen.getByRole('button');
|
|
await userEvent.click(button);
|
|
|
|
await waitFor(() => {
|
|
expect(onDownloadComplete).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
it('should call onDownloadError callback on failure', async () => {
|
|
const onDownloadError = vi.fn();
|
|
const error = new TrackDownloadError('Download failed', 'NETWORK', true);
|
|
vi.mocked(downloadTrack).mockRejectedValue(error);
|
|
|
|
render(
|
|
<TrackDownloadButton trackId={123} onDownloadError={onDownloadError} />,
|
|
);
|
|
|
|
const button = screen.getByRole('button');
|
|
await userEvent.click(button);
|
|
|
|
await waitFor(() => {
|
|
expect(onDownloadError).toHaveBeenCalledWith('Download failed');
|
|
});
|
|
});
|
|
|
|
it('should use custom filename if provided', async () => {
|
|
vi.mocked(downloadTrack).mockResolvedValue(undefined);
|
|
|
|
render(<TrackDownloadButton trackId={123} filename="custom-track.mp3" />);
|
|
|
|
const button = screen.getByRole('button');
|
|
await userEvent.click(button);
|
|
|
|
await waitFor(() => {
|
|
expect(downloadTrack).toHaveBeenCalledWith(123, {
|
|
shareToken: undefined,
|
|
filename: 'custom-track.mp3',
|
|
onProgress: undefined,
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should apply custom variant and size', () => {
|
|
render(<TrackDownloadButton trackId={123} variant="outline" size="sm" />);
|
|
|
|
const button = screen.getByRole('button');
|
|
expect(button).toBeInTheDocument();
|
|
});
|
|
});
|