veza/apps/web/src/features/tracks/components/ShareLinkDisplay.test.tsx
2025-12-03 22:56:50 +01:00

127 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,
user_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')
);
});
});
});