import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/react'; import React from 'react'; import MasqueradeBanner from '../MasqueradeBanner'; import { User } from '../../types'; // Mock react-i18next vi.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key: string, options?: any) => { const translations: Record = { 'platform.masquerade.masqueradingAs': 'Masquerading as', 'platform.masquerade.loggedInAs': `Logged in as ${options?.name || ''}`, 'platform.masquerade.returnTo': `Return to ${options?.name || ''}`, 'platform.masquerade.stopMasquerading': 'Stop Masquerading', }; return translations[key] || key; }, }), })); // Mock lucide-react icons vi.mock('lucide-react', () => ({ Eye: ({ size }: { size: number }) => , XCircle: ({ size }: { size: number }) => , })); describe('MasqueradeBanner', () => { const mockOnStop = vi.fn(); const effectiveUser: User = { id: '2', name: 'John Doe', email: 'john@example.com', role: 'owner', }; const originalUser: User = { id: '1', name: 'Admin User', email: 'admin@platform.com', role: 'superuser', }; const previousUser: User = { id: '3', name: 'Manager User', email: 'manager@example.com', role: 'platform_manager', }; beforeEach(() => { vi.clearAllMocks(); }); describe('Rendering', () => { it('renders the banner with correct structure', () => { const { container } = render( ); // Check for main container - it's the first child div const banner = container.firstChild as HTMLElement; expect(banner).toBeInTheDocument(); expect(banner).toHaveClass('bg-orange-600', 'text-white'); }); it('displays the Eye icon', () => { render( ); const eyeIcon = screen.getByTestId('eye-icon'); expect(eyeIcon).toBeInTheDocument(); expect(eyeIcon).toHaveAttribute('width', '18'); expect(eyeIcon).toHaveAttribute('height', '18'); }); it('displays the XCircle icon in the button', () => { render( ); const xCircleIcon = screen.getByTestId('xcircle-icon'); expect(xCircleIcon).toBeInTheDocument(); expect(xCircleIcon).toHaveAttribute('width', '14'); expect(xCircleIcon).toHaveAttribute('height', '14'); }); }); describe('User Information Display', () => { it('displays the effective user name and role', () => { render( ); expect(screen.getByText('John Doe')).toBeInTheDocument(); expect(screen.getByText(/owner/i)).toBeInTheDocument(); }); it('displays the original user name', () => { render( ); expect(screen.getByText(/Logged in as Admin User/i)).toBeInTheDocument(); }); it('displays masquerading as message', () => { render( ); expect(screen.getByText(/Masquerading as/i)).toBeInTheDocument(); }); it('displays different user roles correctly', () => { const staffUser: User = { id: '4', name: 'Staff Member', email: 'staff@example.com', role: 'staff', }; render( ); expect(screen.getByText('Staff Member')).toBeInTheDocument(); // Use a more specific query to avoid matching "Staff Member" text expect(screen.getByText(/\(staff\)/i)).toBeInTheDocument(); }); }); describe('Stop Masquerade Button', () => { it('renders the stop masquerade button when no previous user', () => { render( ); const button = screen.getByRole('button', { name: /Stop Masquerading/i }); expect(button).toBeInTheDocument(); }); it('renders the return to user button when previous user exists', () => { render( ); const button = screen.getByRole('button', { name: /Return to Manager User/i }); expect(button).toBeInTheDocument(); }); it('calls onStop when button is clicked', () => { render( ); const button = screen.getByRole('button', { name: /Stop Masquerading/i }); fireEvent.click(button); expect(mockOnStop).toHaveBeenCalledTimes(1); }); it('calls onStop when return button is clicked with previous user', () => { render( ); const button = screen.getByRole('button', { name: /Return to Manager User/i }); fireEvent.click(button); expect(mockOnStop).toHaveBeenCalledTimes(1); }); it('can be clicked multiple times', () => { render( ); const button = screen.getByRole('button', { name: /Stop Masquerading/i }); fireEvent.click(button); fireEvent.click(button); fireEvent.click(button); expect(mockOnStop).toHaveBeenCalledTimes(3); }); }); describe('Styling and Visual State', () => { it('has warning/info styling with orange background', () => { const { container } = render( ); const banner = container.firstChild as HTMLElement; expect(banner).toHaveClass('bg-orange-600'); expect(banner).toHaveClass('text-white'); }); it('has proper button styling', () => { render( ); const button = screen.getByRole('button', { name: /Stop Masquerading/i }); expect(button).toHaveClass('bg-white'); expect(button).toHaveClass('text-orange-600'); expect(button).toHaveClass('hover:bg-orange-50'); }); it('has animated pulse effect on Eye icon container', () => { render( ); const eyeIcon = screen.getByTestId('eye-icon'); const iconContainer = eyeIcon.closest('div'); expect(iconContainer).toHaveClass('animate-pulse'); }); it('has proper layout classes for flexbox', () => { const { container } = render( ); const banner = container.firstChild as HTMLElement; expect(banner).toHaveClass('flex'); expect(banner).toHaveClass('items-center'); expect(banner).toHaveClass('justify-between'); }); it('has z-index for proper stacking', () => { const { container } = render( ); const banner = container.firstChild as HTMLElement; expect(banner).toHaveClass('z-50'); expect(banner).toHaveClass('relative'); }); it('has shadow for visual prominence', () => { const { container } = render( ); const banner = container.firstChild as HTMLElement; expect(banner).toHaveClass('shadow-md'); }); }); describe('Edge Cases', () => { it('handles users with numeric IDs', () => { const numericIdUser: User = { id: 123, name: 'Numeric User', email: 'numeric@example.com', role: 'customer', }; render( ); expect(screen.getByText('Numeric User')).toBeInTheDocument(); }); it('handles users with long names', () => { const longNameUser: User = { id: '5', name: 'This Is A Very Long User Name That Should Still Display Properly', email: 'longname@example.com', role: 'manager', }; render( ); expect( screen.getByText('This Is A Very Long User Name That Should Still Display Properly') ).toBeInTheDocument(); }); it('handles all possible user roles', () => { const roles: Array = [ 'superuser', 'platform_manager', 'platform_support', 'owner', 'manager', 'staff', 'resource', 'customer', ]; roles.forEach((role) => { const { unmount } = render( ); expect(screen.getByText(new RegExp(role, 'i'))).toBeInTheDocument(); unmount(); }); }); it('handles previousUser being null', () => { render( ); expect(screen.getByRole('button', { name: /Stop Masquerading/i })).toBeInTheDocument(); expect(screen.queryByText(/Return to/i)).not.toBeInTheDocument(); }); it('handles previousUser being defined', () => { render( ); expect(screen.getByRole('button', { name: /Return to Manager User/i })).toBeInTheDocument(); expect(screen.queryByText(/Stop Masquerading/i)).not.toBeInTheDocument(); }); }); describe('Accessibility', () => { it('has a clickable button element', () => { render( ); const button = screen.getByRole('button'); expect(button).toBeInTheDocument(); expect(button.tagName).toBe('BUTTON'); }); it('button has descriptive text', () => { render( ); const button = screen.getByRole('button'); expect(button).toHaveTextContent(/Stop Masquerading/i); }); it('displays user information in semantic HTML', () => { render( ); const strongElement = screen.getByText('John Doe'); expect(strongElement.tagName).toBe('STRONG'); }); }); describe('Component Integration', () => { it('renders without crashing with minimal props', () => { const minimalEffectiveUser: User = { id: '1', name: 'Test', email: 'test@test.com', role: 'customer', }; const minimalOriginalUser: User = { id: '2', name: 'Admin', email: 'admin@test.com', role: 'superuser', }; expect(() => render( ) ).not.toThrow(); }); it('renders all required elements together', () => { render( ); // Check all major elements are present expect(screen.getByTestId('eye-icon')).toBeInTheDocument(); expect(screen.getByTestId('xcircle-icon')).toBeInTheDocument(); expect(screen.getByText(/Masquerading as/i)).toBeInTheDocument(); expect(screen.getByText('John Doe')).toBeInTheDocument(); expect(screen.getByText(/Logged in as Admin User/i)).toBeInTheDocument(); expect(screen.getByRole('button')).toBeInTheDocument(); }); }); });