128 lines
3.6 KiB
TypeScript
128 lines
3.6 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 { ShareLinkDisplay } from './ShareLinkDisplay';
|
|
import { useToast } from '@/hooks/useToast';
|
|
import type { TrackShare } from '../services/trackShareService';
|
|
|
|
// Mock dependencies
|
|
vi.mock('@/hooks/useToast');
|
|
|
|
describe('ShareLinkDisplay', () => {
|
|
const mockToast = {
|
|
success: vi.fn(),
|
|
error: vi.fn(),
|
|
warning: vi.fn(),
|
|
info: vi.fn(),
|
|
toast: vi.fn(),
|
|
};
|
|
|
|
const mockShare: TrackShare = {
|
|
id: 1,
|
|
track_id: 123,
|
|
creator_id: 456,
|
|
share_token: 'test-token-123',
|
|
permissions: 'read,download',
|
|
access_count: 5,
|
|
created_at: '2024-01-01T00:00:00Z',
|
|
updated_at: '2024-01-01T00:00:00Z',
|
|
};
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
vi.mocked(useToast).mockReturnValue(mockToast);
|
|
|
|
// Mock navigator.clipboard
|
|
Object.assign(navigator, {
|
|
clipboard: {
|
|
writeText: vi.fn().mockResolvedValue(undefined),
|
|
},
|
|
});
|
|
});
|
|
|
|
it('should display share link', () => {
|
|
render(<ShareLinkDisplay share={mockShare} />);
|
|
|
|
expect(screen.getByText(/Lien de partage/i)).toBeInTheDocument();
|
|
expect(
|
|
screen.getByText(/tracks\/shared\/test-token-123/i),
|
|
).toBeInTheDocument();
|
|
});
|
|
|
|
it('should display permissions', () => {
|
|
render(<ShareLinkDisplay share={mockShare} />);
|
|
|
|
expect(screen.getByText(/Permissions/i)).toBeInTheDocument();
|
|
expect(screen.getByText(/Lecture/i)).toBeInTheDocument();
|
|
expect(screen.getByText(/Téléchargement/i)).toBeInTheDocument();
|
|
});
|
|
|
|
it('should display statistics', () => {
|
|
render(<ShareLinkDisplay share={mockShare} />);
|
|
|
|
expect(screen.getByText(/Statistiques/i)).toBeInTheDocument();
|
|
expect(screen.getByText(/Nombre d'accès: 5/i)).toBeInTheDocument();
|
|
});
|
|
|
|
it('should display expiration date if provided', () => {
|
|
const shareWithExpiration: TrackShare = {
|
|
...mockShare,
|
|
expires_at: '2024-12-31T23:59:59Z',
|
|
};
|
|
|
|
render(<ShareLinkDisplay share={shareWithExpiration} />);
|
|
|
|
expect(screen.getByText(/Expire le/i)).toBeInTheDocument();
|
|
});
|
|
|
|
it('should copy link to clipboard when copy button is clicked', async () => {
|
|
render(<ShareLinkDisplay share={mockShare} />);
|
|
|
|
const copyButton = screen.getByTitle(/Copier le lien/i);
|
|
await userEvent.click(copyButton);
|
|
|
|
await waitFor(() => {
|
|
expect(navigator.clipboard.writeText).toHaveBeenCalledWith(
|
|
expect.stringContaining('tracks/shared/test-token-123'),
|
|
);
|
|
expect(mockToast.success).toHaveBeenCalledWith(
|
|
expect.stringContaining('copié'),
|
|
);
|
|
});
|
|
});
|
|
|
|
it('should open link in new tab when open button is clicked', async () => {
|
|
const mockOpen = vi.fn();
|
|
window.open = mockOpen;
|
|
|
|
render(<ShareLinkDisplay share={mockShare} />);
|
|
|
|
const openButton = screen.getByTitle(/Ouvrir le lien/i);
|
|
await userEvent.click(openButton);
|
|
|
|
expect(mockOpen).toHaveBeenCalledWith(
|
|
expect.stringContaining('tracks/shared/test-token-123'),
|
|
'_blank',
|
|
);
|
|
});
|
|
|
|
it('should handle copy error gracefully', async () => {
|
|
const mockError = new Error('Clipboard error');
|
|
Object.assign(navigator, {
|
|
clipboard: {
|
|
writeText: vi.fn().mockRejectedValue(mockError),
|
|
},
|
|
});
|
|
|
|
render(<ShareLinkDisplay share={mockShare} />);
|
|
|
|
const copyButton = screen.getByTitle(/Copier le lien/i);
|
|
await userEvent.click(copyButton);
|
|
|
|
await waitFor(() => {
|
|
expect(mockToast.error).toHaveBeenCalledWith(
|
|
expect.stringContaining('Impossible de copier'),
|
|
);
|
|
});
|
|
});
|
|
});
|