// src/components/Header.test.tsx import React from 'react'; import { screen, fireEvent } from '@testing-library/react'; import { describe, it, expect, vi, beforeEach } from 'vitest'; import { Header } from './Header'; import type { UserProfile } from '../types'; import { createMockUserProfile } from '../tests/utils/mockFactories'; import { renderWithProviders } from '../tests/utils/renderWithProviders'; // Unmock the component to test the real implementation vi.unmock('./Header'); const mockUserProfile: UserProfile = createMockUserProfile({ role: 'user', user: { user_id: 'user-123', email: 'test@example.com' }, }); const mockAdminProfile: UserProfile = createMockUserProfile({ role: 'admin', user: { user_id: 'admin-123', email: 'admin@example.com' }, }); const mockOnOpenProfile = vi.fn(); const mockOnOpenVoiceAssistant = vi.fn(); const mockOnSignOut = vi.fn(); const defaultProps = { isDarkMode: false, unitSystem: 'imperial' as const, userProfile: null, authStatus: 'SIGNED_OUT' as const, onOpenProfile: mockOnOpenProfile, onOpenVoiceAssistant: mockOnOpenVoiceAssistant, onSignOut: mockOnSignOut, }; // Helper to render with router context const renderHeader = (props: Partial>) => { return renderWithProviders(
); }; describe('Header', () => { beforeEach(() => { vi.clearAllMocks(); }); it('should render the application title', () => { renderHeader({}); expect(screen.getByRole('heading', { name: /flyer crawler/i })).toBeInTheDocument(); }); it('should display unit system and theme mode', () => { renderHeader({ isDarkMode: true, unitSystem: 'metric' }); expect(screen.getByText(/metric/i)).toBeInTheDocument(); expect(screen.getByText(/dark mode/i)).toBeInTheDocument(); }); describe('When user is logged out', () => { it('should show a Login button', () => { renderHeader({ userProfile: null, authStatus: 'SIGNED_OUT' }); expect(screen.getByRole('button', { name: /login/i })).toBeInTheDocument(); }); it('should call onOpenProfile when Login button is clicked', () => { renderHeader({ userProfile: null, authStatus: 'SIGNED_OUT' }); fireEvent.click(screen.getByRole('button', { name: /login/i })); expect(mockOnOpenProfile).toHaveBeenCalledTimes(1); }); it('should not show user-specific buttons', () => { renderHeader({ userProfile: null, authStatus: 'SIGNED_OUT' }); expect(screen.queryByLabelText(/open voice assistant/i)).not.toBeInTheDocument(); expect(screen.queryByLabelText(/open my account settings/i)).not.toBeInTheDocument(); expect(screen.queryByRole('button', { name: /logout/i })).not.toBeInTheDocument(); }); }); describe('When user is authenticated', () => { it('should display the user email', () => { renderHeader({ userProfile: mockUserProfile, authStatus: 'AUTHENTICATED' }); expect(screen.getByText(mockUserProfile.user.email)).toBeInTheDocument(); }); it('should display "Guest" for anonymous users', () => { renderHeader({ userProfile: mockUserProfile, authStatus: 'SIGNED_OUT' }); expect(screen.getByText(/guest/i)).toBeInTheDocument(); }); it('should call onOpenVoiceAssistant when microphone icon is clicked', () => { renderHeader({ userProfile: mockUserProfile, authStatus: 'AUTHENTICATED' }); fireEvent.click(screen.getByLabelText(/open voice assistant/i)); expect(mockOnOpenVoiceAssistant).toHaveBeenCalledTimes(1); }); it('should call onOpenProfile when cog icon is clicked', () => { renderHeader({ userProfile: mockUserProfile, authStatus: 'AUTHENTICATED' }); fireEvent.click(screen.getByLabelText(/open my account settings/i)); expect(mockOnOpenProfile).toHaveBeenCalledTimes(1); }); it('should call onSignOut when Logout button is clicked', () => { renderHeader({ userProfile: mockUserProfile, authStatus: 'AUTHENTICATED' }); fireEvent.click(screen.getByRole('button', { name: /logout/i })); expect(mockOnSignOut).toHaveBeenCalledTimes(1); }); }); describe('Admin user', () => { it('should show the Admin Area link for admin users', () => { renderHeader({ userProfile: mockAdminProfile, authStatus: 'AUTHENTICATED' }); const adminLink = screen.getByTitle(/admin area/i); expect(adminLink).toBeInTheDocument(); expect(adminLink.closest('a')).toHaveAttribute('href', '/admin'); }); it('should not show the Admin Area link for non-admin users', () => { renderHeader({ userProfile: mockUserProfile, authStatus: 'AUTHENTICATED' }); expect(screen.queryByTitle(/admin area/i)).not.toBeInTheDocument(); }); }); });