/** * Tests for Admin Layout * Verifies layout rendering, auth guard, and accessibility features */ import { render, screen } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import AdminLayout from '@/app/admin/layout'; import { useAuth } from '@/lib/auth/AuthContext'; // Mock dependencies jest.mock('@/lib/auth/AuthContext'); jest.mock('@/components/layout/Header', () => ({ Header: () =>
Header
, })); jest.mock('@/components/layout/Footer', () => ({ Footer: () => , })); jest.mock('@/components/admin/AdminSidebar', () => ({ AdminSidebar: () => , })); jest.mock('@/components/admin/Breadcrumbs', () => ({ Breadcrumbs: () =>
Breadcrumbs
, })); // Mock next/navigation jest.mock('next/navigation', () => ({ useRouter: () => ({ push: jest.fn(), replace: jest.fn(), prefetch: jest.fn(), }), usePathname: () => '/admin', })); const mockUseAuth = useAuth as jest.MockedFunction; describe('AdminLayout', () => { let queryClient: QueryClient; beforeEach(() => { queryClient = new QueryClient({ defaultOptions: { queries: { retry: false, }, }, }); jest.clearAllMocks(); }); const wrapper = ({ children }: { children: React.ReactNode }) => ( {children} ); it('renders layout with all components for superuser', () => { mockUseAuth.mockReturnValue({ user: { is_superuser: true } as any, isAuthenticated: true, isLoading: false, login: jest.fn(), logout: jest.fn(), }); render(
Test Content
, { wrapper } ); expect(screen.getByTestId('header')).toBeInTheDocument(); expect(screen.getByTestId('footer')).toBeInTheDocument(); expect(screen.getByTestId('sidebar')).toBeInTheDocument(); expect(screen.getByTestId('breadcrumbs')).toBeInTheDocument(); expect(screen.getByText('Test Content')).toBeInTheDocument(); }); it('renders skip link with correct attributes', () => { mockUseAuth.mockReturnValue({ user: { is_superuser: true } as any, isAuthenticated: true, isLoading: false, login: jest.fn(), logout: jest.fn(), }); render(
Test Content
, { wrapper } ); const skipLink = screen.getByText('Skip to main content'); expect(skipLink).toBeInTheDocument(); expect(skipLink).toHaveAttribute('href', '#main-content'); expect(skipLink).toHaveClass('sr-only'); }); it('renders main element with id', () => { mockUseAuth.mockReturnValue({ user: { is_superuser: true } as any, isAuthenticated: true, isLoading: false, login: jest.fn(), logout: jest.fn(), }); const { container } = render(
Test Content
, { wrapper } ); const mainElement = container.querySelector('#main-content'); expect(mainElement).toBeInTheDocument(); expect(mainElement?.tagName).toBe('MAIN'); }); it('renders children inside main content area', () => { mockUseAuth.mockReturnValue({ user: { is_superuser: true } as any, isAuthenticated: true, isLoading: false, login: jest.fn(), logout: jest.fn(), }); render(
Child Content
, { wrapper } ); const mainElement = screen.getByTestId('child-content').closest('main'); expect(mainElement).toHaveAttribute('id', 'main-content'); }); it('applies correct layout structure classes', () => { mockUseAuth.mockReturnValue({ user: { is_superuser: true } as any, isAuthenticated: true, isLoading: false, login: jest.fn(), logout: jest.fn(), }); const { container } = render(
Test Content
, { wrapper } ); // Check root container has min-height class const rootDiv = container.querySelector('.min-h-screen'); expect(rootDiv).toBeInTheDocument(); expect(rootDiv).toHaveClass('flex', 'flex-col'); // Check main content area has flex and overflow classes const mainElement = container.querySelector('#main-content'); expect(mainElement).toHaveClass('flex-1', 'overflow-y-auto'); }); });