import { render, screen, fireEvent } from '@testing-library/react' import { Sidebar, SidebarLayout } from '../sidebar' // next/link and next/navigation are mocked via jest.config.js moduleNameMapper const sections = [ { title: 'Main', links: [ { href: '/', label: 'Dashboard', icon: }, { href: '/contacts', label: 'Contacts' }, ], }, { title: 'Admin', links: [ { href: '/settings', label: 'Account Settings' }, ], }, ] describe('Sidebar', () => { it('renders app name', () => { render() expect(screen.getByText('MarketSimpli')).toBeInTheDocument() }) it('renders section titles', () => { render() expect(screen.getByText('Main')).toBeInTheDocument() expect(screen.getByText('Admin')).toBeInTheDocument() }) it('renders all nav links', () => { render() expect(screen.getByText('Dashboard')).toBeInTheDocument() expect(screen.getByText('Contacts')).toBeInTheDocument() expect(screen.getByText('Account Settings')).toBeInTheDocument() }) it('renders icons for links that have icons', () => { render() expect(screen.getByTestId('icon-dashboard')).toBeInTheDocument() }) it('renders collapse toggle button when collapsible is true (default)', () => { render() expect(screen.getByText('Collapse')).toBeInTheDocument() }) it('does not render collapse toggle when collapsible is false', () => { render() expect(screen.queryByText('Collapse')).not.toBeInTheDocument() }) it('collapses when toggle button is clicked', () => { const { container } = render( ) fireEvent.click(screen.getByText('Collapse')) // After collapse, the sidebar should have w-20 class expect(container.firstChild).toHaveClass('w-20') }) it('expands back when toggle is clicked again', () => { const { container } = render( ) // Collapse fireEvent.click(screen.getByText('Collapse')) // Expand — the chevron button is still present, click it const expandBtn = screen.getByRole('button') fireEvent.click(expandBtn) expect(container.firstChild).toHaveClass('w-64') }) it('hides link labels when collapsed', () => { render( ) // Labels are wrapped in a that only renders when not collapsed expect(screen.queryByText('Dashboard')).not.toBeInTheDocument() expect(screen.queryByText('Contacts')).not.toBeInTheDocument() }) it('hides section titles when collapsed', () => { render( ) expect(screen.queryByText('Main')).not.toBeInTheDocument() }) it('shows abbreviated app name when collapsed', () => { render( ) expect(screen.getByText('MA')).toBeInTheDocument() }) it('renders user dropdown when provided', () => { render( User Menu} /> ) expect(screen.getByTestId('user-menu')).toBeInTheDocument() }) it('applies custom className', () => { const { container } = render( ) expect(container.firstChild).toHaveClass('my-sidebar') }) it('active link uses primary background (pathname matches)', () => { // The mock usePathname returns '/test-path' // We add a link with that href const customSections = [ { links: [ { href: '/test-path', label: 'Active Link' }, { href: '/other', label: 'Inactive Link' }, ], }, ] render() const activeLink = screen.getByText('Active Link').closest('a') // Semantic token, not a numeric ramp — `bg-primary-600` is undefined in apps // that only declare --color-primary, so the active pill vanished (startsim-1f3n). expect(activeLink).toHaveClass('bg-primary') expect(activeLink).toHaveClass('text-primary-foreground') }) it('inactive link uses gray text', () => { const customSections = [ { links: [ { href: '/test-path', label: 'Active Link' }, { href: '/other', label: 'Inactive Link' }, ], }, ] render() const inactiveLink = screen.getByText('Inactive Link').closest('a') expect(inactiveLink).toHaveClass('text-gray-300') }) it('root href "/" is active only for exact match', () => { // usePathname returns '/test-path', so '/' should not be active const customSections = [ { links: [{ href: '/', label: 'Home' }], }, ] render() const homeLink = screen.getByText('Home').closest('a') expect(homeLink).not.toHaveClass('bg-primary') }) }) // --------------------------------------------------------------------------- // SidebarLayout // --------------------------------------------------------------------------- describe('SidebarLayout', () => { it('renders children', () => { render(

Page content

) expect(screen.getByText('Page content')).toBeInTheDocument() }) it('applies expanded width spacer by default', () => { const { container } = render(

Content

) const spacer = container.querySelector('.w-64') expect(spacer).toBeInTheDocument() }) it('applies collapsed width spacer when collapsed is true', () => { const { container } = render(

Content

) const spacer = container.querySelector('.w-20') expect(spacer).toBeInTheDocument() }) })