186 lines
6 KiB
TypeScript
186 lines
6 KiB
TypeScript
|
|
import { describe, it, expect, vi } from 'vitest';
|
||
|
|
import { render, screen } from '@testing-library/react';
|
||
|
|
import userEvent from '@testing-library/user-event';
|
||
|
|
import { PlayerError } from './PlayerError';
|
||
|
|
|
||
|
|
describe('PlayerError', () => {
|
||
|
|
it('should not render when error is null', () => {
|
||
|
|
const { container } = render(<PlayerError error={null} />);
|
||
|
|
|
||
|
|
expect(container.firstChild).toBeNull();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should render when error is provided', () => {
|
||
|
|
const error = new Error('Test error');
|
||
|
|
render(<PlayerError error={error} />);
|
||
|
|
|
||
|
|
expect(screen.getByRole('alert')).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should display error message', () => {
|
||
|
|
const error = new Error('Test error');
|
||
|
|
render(<PlayerError error={error} />);
|
||
|
|
|
||
|
|
expect(screen.getByText('Une erreur est survenue lors de la lecture.')).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should display error title', () => {
|
||
|
|
const error = new Error('Test error');
|
||
|
|
render(<PlayerError error={error} />);
|
||
|
|
|
||
|
|
expect(screen.getByText('Erreur de lecture')).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should display network error message', () => {
|
||
|
|
const error = new Error('Network error');
|
||
|
|
error.name = 'NetworkError';
|
||
|
|
render(<PlayerError error={error} />);
|
||
|
|
|
||
|
|
expect(
|
||
|
|
screen.getByText('Erreur de connexion. Vérifiez votre connexion internet.')
|
||
|
|
).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should display decode error message', () => {
|
||
|
|
const error = new Error('Decode error');
|
||
|
|
error.name = 'DecodeError';
|
||
|
|
render(<PlayerError error={error} />);
|
||
|
|
|
||
|
|
expect(
|
||
|
|
screen.getByText('Erreur de décodage audio. Le fichier est peut-être corrompu.')
|
||
|
|
).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should display source error message', () => {
|
||
|
|
const error = new Error('Source not found');
|
||
|
|
error.name = 'NotFoundError';
|
||
|
|
render(<PlayerError error={error} />);
|
||
|
|
|
||
|
|
expect(
|
||
|
|
screen.getByText('Erreur de source audio. Le fichier est introuvable ou inaccessible.')
|
||
|
|
).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should display abort error message', () => {
|
||
|
|
const error = new Error('Abort error');
|
||
|
|
error.name = 'AbortError';
|
||
|
|
render(<PlayerError error={error} />);
|
||
|
|
|
||
|
|
expect(screen.getByText('Chargement annulé.')).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should use custom errorType', () => {
|
||
|
|
const error = new Error('Test error');
|
||
|
|
render(<PlayerError error={error} errorType="network" />);
|
||
|
|
|
||
|
|
expect(
|
||
|
|
screen.getByText('Erreur de connexion. Vérifiez votre connexion internet.')
|
||
|
|
).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should display retry button when onRetry is provided', () => {
|
||
|
|
const error = new Error('Test error');
|
||
|
|
const onRetry = vi.fn();
|
||
|
|
render(<PlayerError error={error} onRetry={onRetry} />);
|
||
|
|
|
||
|
|
expect(screen.getByText('Réessayer')).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should not display retry button when onRetry is not provided', () => {
|
||
|
|
const error = new Error('Test error');
|
||
|
|
render(<PlayerError error={error} />);
|
||
|
|
|
||
|
|
expect(screen.queryByText('Réessayer')).not.toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should not display retry button when showRetry is false', () => {
|
||
|
|
const error = new Error('Test error');
|
||
|
|
const onRetry = vi.fn();
|
||
|
|
render(<PlayerError error={error} onRetry={onRetry} showRetry={false} />);
|
||
|
|
|
||
|
|
expect(screen.queryByText('Réessayer')).not.toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should call onRetry when retry button is clicked', async () => {
|
||
|
|
const user = userEvent.setup();
|
||
|
|
const error = new Error('Test error');
|
||
|
|
const onRetry = vi.fn();
|
||
|
|
render(<PlayerError error={error} onRetry={onRetry} />);
|
||
|
|
|
||
|
|
const retryButton = screen.getByText('Réessayer');
|
||
|
|
await user.click(retryButton);
|
||
|
|
|
||
|
|
expect(onRetry).toHaveBeenCalledTimes(1);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should use custom retry label', () => {
|
||
|
|
const error = new Error('Test error');
|
||
|
|
const onRetry = vi.fn();
|
||
|
|
render(<PlayerError error={error} onRetry={onRetry} retryLabel="Retry" />);
|
||
|
|
|
||
|
|
expect(screen.getByText('Retry')).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should apply custom className', () => {
|
||
|
|
const error = new Error('Test error');
|
||
|
|
const { container } = render(<PlayerError error={error} className="custom-class" />);
|
||
|
|
|
||
|
|
expect(container.firstChild).toHaveClass('custom-class');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should have accessible attributes', () => {
|
||
|
|
const error = new Error('Test error');
|
||
|
|
render(<PlayerError error={error} />);
|
||
|
|
|
||
|
|
const alert = screen.getByRole('alert');
|
||
|
|
expect(alert).toHaveAttribute('aria-live', 'assertive');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should have accessible retry button', () => {
|
||
|
|
const error = new Error('Test error');
|
||
|
|
const onRetry = vi.fn();
|
||
|
|
const { container } = render(<PlayerError error={error} onRetry={onRetry} />);
|
||
|
|
|
||
|
|
const retryButton = screen.getByText('Réessayer');
|
||
|
|
// Check that aria-label is present on the button element
|
||
|
|
const buttonElement = container.querySelector('button[aria-label]');
|
||
|
|
expect(buttonElement).toBeInTheDocument();
|
||
|
|
expect(buttonElement?.getAttribute('aria-label')).toContain('Réessayer');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should detect network error from message', () => {
|
||
|
|
const error = new Error('Network request failed');
|
||
|
|
render(<PlayerError error={error} />);
|
||
|
|
|
||
|
|
expect(
|
||
|
|
screen.getByText('Erreur de connexion. Vérifiez votre connexion internet.')
|
||
|
|
).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should detect decode error from message', () => {
|
||
|
|
const error = new Error('Failed to decode audio data');
|
||
|
|
render(<PlayerError error={error} />);
|
||
|
|
|
||
|
|
expect(
|
||
|
|
screen.getByText('Erreur de décodage audio. Le fichier est peut-être corrompu.')
|
||
|
|
).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should detect source error from message', () => {
|
||
|
|
const error = new Error('Source not found');
|
||
|
|
render(<PlayerError error={error} />);
|
||
|
|
|
||
|
|
expect(
|
||
|
|
screen.getByText('Erreur de source audio. Le fichier est introuvable ou inaccessible.')
|
||
|
|
).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should detect abort error from message', () => {
|
||
|
|
const error = new Error('Request aborted');
|
||
|
|
render(<PlayerError error={error} />);
|
||
|
|
|
||
|
|
expect(screen.getByText('Chargement annulé.')).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|