import { describe, it, expect, vi, beforeEach } from 'vitest' import { render, screen, waitFor } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { Sidebar } from './sidebar' // Mock next/navigation const mockPush = vi.fn() const mockPathname = vi.fn() vi.mock('next/navigation', () => ({ useRouter: () => ({ push: mockPush, }), usePathname: () => mockPathname(), })) // Mock supabase const mockSignOut = vi.fn() vi.mock('@/lib/supabase', () => ({ supabase: { auth: { signOut: () => mockSignOut(), }, }, })) describe('Sidebar', () => { beforeEach(() => { vi.clearAllMocks() mockPathname.mockReturnValue('/') }) it('should render sidebar with logo and navigation', () => { render() expect(screen.getByText('TabataFit')).toBeInTheDocument() expect(screen.getByText('Admin Dashboard')).toBeInTheDocument() expect(screen.getByRole('button', { name: /logout/i })).toBeInTheDocument() }) it('should render all navigation items', () => { render() expect(screen.getByRole('link', { name: /dashboard/i })).toBeInTheDocument() expect(screen.getByRole('link', { name: /workouts/i })).toBeInTheDocument() expect(screen.getByRole('link', { name: /trainers/i })).toBeInTheDocument() expect(screen.getByRole('link', { name: /collections/i })).toBeInTheDocument() expect(screen.getByRole('link', { name: /media/i })).toBeInTheDocument() }) it('should highlight active navigation item', () => { mockPathname.mockReturnValue('/workouts') render() const workoutsLink = screen.getByRole('link', { name: /workouts/i }) expect(workoutsLink).toHaveClass('text-orange-500') expect(workoutsLink).toHaveClass('bg-orange-500/10') }) it('should not highlight inactive navigation items', () => { mockPathname.mockReturnValue('/workouts') render() const dashboardLink = screen.getByRole('link', { name: /dashboard/i }) expect(dashboardLink).toHaveClass('text-neutral-400') expect(dashboardLink).not.toHaveClass('bg-orange-500/10') }) it('should navigate to correct routes when clicking links', () => { render() const workoutsLink = screen.getByRole('link', { name: /workouts/i }) expect(workoutsLink).toHaveAttribute('href', '/workouts') const trainersLink = screen.getByRole('link', { name: /trainers/i }) expect(trainersLink).toHaveAttribute('href', '/trainers') }) it('should handle logout', async () => { mockSignOut.mockResolvedValue({ error: null }) render() const logoutButton = screen.getByRole('button', { name: /logout/i }) await userEvent.click(logoutButton) await waitFor(() => { expect(mockSignOut).toHaveBeenCalled() }) expect(mockPush).toHaveBeenCalledWith('/login') }) it('should handle logout errors gracefully', async () => { mockSignOut.mockRejectedValueOnce(new Error('Network error')) render() const logoutButton = screen.getByRole('button', { name: /logout/i }) await userEvent.click(logoutButton) await waitFor(() => { expect(mockSignOut).toHaveBeenCalled() }) }) it('should have correct styling for navigation', () => { render() const nav = screen.getByRole('navigation') expect(nav).toBeInTheDocument() const links = screen.getAllByRole('link') links.forEach(link => { expect(link).toHaveClass('flex', 'items-center', 'gap-3') }) }) it('should display icons for navigation items', () => { render() // All nav links should have icons (lucide icons render as svg) const links = screen.getAllByRole('link') links.forEach(link => { const icon = link.querySelector('svg') expect(icon).toBeInTheDocument() }) }) it('should be sticky positioned', () => { render() const sidebar = screen.getByRole('complementary') || document.querySelector('aside') expect(sidebar).toHaveClass('sticky', 'top-0') }) })