- Add tests for useClickOutside hook - Add tests for UserDropdown component - Add tests for TicketPrizeDisplay component - Add tests for TicketTableRow component - Increase test count from 181 to 222 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
212 lines
5.4 KiB
TypeScript
212 lines
5.4 KiB
TypeScript
/**
|
|
* Tests for the UserDropdown component
|
|
* @jest-environment jsdom
|
|
*/
|
|
|
|
import React from 'react';
|
|
import { render, screen, fireEvent } from '@testing-library/react';
|
|
import { UserDropdown } from '@/components/UserDropdown';
|
|
|
|
// Mock next/link
|
|
jest.mock('next/link', () => {
|
|
return ({ children, href }: { children: React.ReactNode; href: string }) => (
|
|
<a href={href}>{children}</a>
|
|
);
|
|
});
|
|
|
|
describe('UserDropdown', () => {
|
|
const mockUser = {
|
|
firstName: 'John',
|
|
lastName: 'Doe',
|
|
email: 'john.doe@example.com',
|
|
};
|
|
|
|
const mockOnLogout = jest.fn();
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
it('should render user initials', () => {
|
|
render(
|
|
<UserDropdown
|
|
user={mockUser}
|
|
profilePath="/profil"
|
|
onLogout={mockOnLogout}
|
|
/>
|
|
);
|
|
|
|
expect(screen.getByText('JD')).toBeInTheDocument();
|
|
});
|
|
|
|
it('should render user name and email', () => {
|
|
render(
|
|
<UserDropdown
|
|
user={mockUser}
|
|
profilePath="/profil"
|
|
onLogout={mockOnLogout}
|
|
/>
|
|
);
|
|
|
|
expect(screen.getByText('John Doe')).toBeInTheDocument();
|
|
expect(screen.getByText('john.doe@example.com')).toBeInTheDocument();
|
|
});
|
|
|
|
it('should toggle dropdown on click', () => {
|
|
render(
|
|
<UserDropdown
|
|
user={mockUser}
|
|
profilePath="/profil"
|
|
onLogout={mockOnLogout}
|
|
/>
|
|
);
|
|
|
|
// Dropdown should be closed initially
|
|
expect(screen.queryByText('Profil')).not.toBeInTheDocument();
|
|
|
|
// Click to open - get the main trigger button (contains user name)
|
|
const triggerButton = screen.getByText('John Doe').closest('button');
|
|
fireEvent.click(triggerButton!);
|
|
expect(screen.getByText('Profil')).toBeInTheDocument();
|
|
expect(screen.getByText('Deconnexion')).toBeInTheDocument();
|
|
|
|
// Click to close
|
|
fireEvent.click(triggerButton!);
|
|
expect(screen.queryByText('Profil')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('should render profile link with correct path', () => {
|
|
render(
|
|
<UserDropdown
|
|
user={mockUser}
|
|
profilePath="/admin/profil"
|
|
onLogout={mockOnLogout}
|
|
/>
|
|
);
|
|
|
|
const triggerButton = screen.getByText('John Doe').closest('button');
|
|
fireEvent.click(triggerButton!);
|
|
|
|
const profileLink = screen.getByText('Profil').closest('a');
|
|
expect(profileLink).toHaveAttribute('href', '/admin/profil');
|
|
});
|
|
|
|
it('should call onLogout when logout button is clicked', () => {
|
|
render(
|
|
<UserDropdown
|
|
user={mockUser}
|
|
profilePath="/profil"
|
|
onLogout={mockOnLogout}
|
|
/>
|
|
);
|
|
|
|
const triggerButton = screen.getByText('John Doe').closest('button');
|
|
fireEvent.click(triggerButton!);
|
|
fireEvent.click(screen.getByText('Deconnexion'));
|
|
|
|
expect(mockOnLogout).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('should have onClick handler on profile link', () => {
|
|
render(
|
|
<UserDropdown
|
|
user={mockUser}
|
|
profilePath="/profil"
|
|
onLogout={mockOnLogout}
|
|
/>
|
|
);
|
|
|
|
const triggerButton = screen.getByText('John Doe').closest('button');
|
|
fireEvent.click(triggerButton!);
|
|
|
|
const profileLink = screen.getByText('Profil').closest('a');
|
|
expect(profileLink).toBeInTheDocument();
|
|
expect(profileLink).toHaveAttribute('href', '/profil');
|
|
});
|
|
|
|
it('should apply blue accent color by default', () => {
|
|
const { container } = render(
|
|
<UserDropdown
|
|
user={mockUser}
|
|
profilePath="/profil"
|
|
onLogout={mockOnLogout}
|
|
/>
|
|
);
|
|
|
|
const avatar = container.querySelector('.bg-blue-600');
|
|
expect(avatar).toBeInTheDocument();
|
|
});
|
|
|
|
it('should apply green accent color when specified', () => {
|
|
const { container } = render(
|
|
<UserDropdown
|
|
user={mockUser}
|
|
profilePath="/profil"
|
|
onLogout={mockOnLogout}
|
|
accentColor="green"
|
|
/>
|
|
);
|
|
|
|
const avatar = container.querySelector('.bg-green-600');
|
|
expect(avatar).toBeInTheDocument();
|
|
});
|
|
|
|
it('should handle null user gracefully', () => {
|
|
const { container } = render(
|
|
<UserDropdown
|
|
user={null}
|
|
profilePath="/profil"
|
|
onLogout={mockOnLogout}
|
|
/>
|
|
);
|
|
|
|
// Should render empty initials
|
|
const avatarDiv = container.querySelector('.bg-blue-600');
|
|
expect(avatarDiv).toBeInTheDocument();
|
|
});
|
|
|
|
it('should handle user with missing firstName', () => {
|
|
render(
|
|
<UserDropdown
|
|
user={{ lastName: 'Doe', email: 'test@test.com' }}
|
|
profilePath="/profil"
|
|
onLogout={mockOnLogout}
|
|
/>
|
|
);
|
|
|
|
expect(screen.getByText('D')).toBeInTheDocument();
|
|
});
|
|
|
|
it('should apply custom className', () => {
|
|
const { container } = render(
|
|
<UserDropdown
|
|
user={mockUser}
|
|
profilePath="/profil"
|
|
onLogout={mockOnLogout}
|
|
className="custom-class"
|
|
/>
|
|
);
|
|
|
|
expect(container.firstChild).toHaveClass('custom-class');
|
|
});
|
|
|
|
it('should rotate chevron icon when dropdown is open', () => {
|
|
const { container } = render(
|
|
<UserDropdown
|
|
user={mockUser}
|
|
profilePath="/profil"
|
|
onLogout={mockOnLogout}
|
|
/>
|
|
);
|
|
|
|
const chevron = container.querySelector('.w-4.h-4.text-gray-500');
|
|
expect(chevron).not.toHaveClass('rotate-180');
|
|
|
|
const triggerButton = screen.getByText('John Doe').closest('button');
|
|
fireEvent.click(triggerButton!);
|
|
|
|
const rotatedChevron = container.querySelector('.rotate-180');
|
|
expect(rotatedChevron).toBeInTheDocument();
|
|
});
|
|
});
|