import { describe, it, expect } from 'vitest' import { render, screen } from '@testing-library/react' import { axe } from 'vitest-axe' import { Breadcrumbs } from './breadcrumbs' describe('Breadcrumbs', () => { const items = [ { label: 'Home', href: '/' }, { label: 'Development', href: '/c/development' }, { label: 'Current Page' }, ] it('renders all breadcrumb items in desktop layout', () => { render() const desktopList = screen.getByRole('list') expect(desktopList).toHaveTextContent('Home') expect(desktopList).toHaveTextContent('Development') expect(desktopList).toHaveTextContent('Current Page') }) it('renders links for non-last items in desktop layout', () => { render() const homeLinks = screen.getAllByRole('link', { name: 'Home' }) expect(homeLinks.length).toBeGreaterThanOrEqual(1) expect(homeLinks[0]).toHaveAttribute('href', '/') }) it('renders mobile back-link with last navigable item', () => { render() const devLinks = screen.getAllByRole('link', { name: /Development/i }) const mobileLink = devLinks.find((el) => el.classList.contains('md:hidden')) expect(mobileLink).toBeDefined() expect(mobileLink).toHaveAttribute('href', '/c/development') }) it('renders CaretLeft icon with aria-hidden in mobile back-link', () => { const { container } = render() const svgs = container.querySelectorAll('svg') expect(svgs.length).toBeGreaterThan(0) const caretIcon = svgs[0] expect(caretIcon).toHaveAttribute('aria-hidden', 'true') }) it('has accessible navigation landmark', () => { render() expect(screen.getByRole('navigation', { name: /breadcrumb/i })).toBeInTheDocument() }) it('renders separator between items in desktop layout', () => { render() const separators = screen.getAllByText('/') expect(separators).toHaveLength(2) }) it('includes JSON-LD structured data from items', () => { const { container } = render() const script = container.querySelector('script[type="application/ld+json"]') expect(script).toBeInTheDocument() const jsonLd = JSON.parse(script!.textContent!) expect(jsonLd['@type']).toBe('BreadcrumbList') // Only items with href are included in JSON-LD expect(jsonLd.itemListElement).toHaveLength(2) expect(jsonLd.itemListElement[0].name).toBe('Home') expect(jsonLd.itemListElement[1].name).toBe('Development') }) it('uses jsonLdItems for JSON-LD when provided', () => { const jsonLdItems = [ { label: 'Home', href: '/' }, { label: 'Development', href: '/c/development' }, { label: 'My Topic Title', href: '/jay.bsky.team/abc123' }, ] const visualItems = [ { label: 'Home', href: '/' }, { label: 'Development', href: '/c/development' }, ] const { container } = render() const script = container.querySelector('script[type="application/ld+json"]') const jsonLd = JSON.parse(script!.textContent!) expect(jsonLd.itemListElement).toHaveLength(3) expect(jsonLd.itemListElement[2].name).toBe('My Topic Title') }) it('desktop layout is hidden on mobile via hidden md:flex', () => { render() const desktopList = screen.getByRole('list') expect(desktopList).toHaveClass('hidden') expect(desktopList).toHaveClass('md:flex') }) it('returns null for empty items', () => { const { container } = render() expect(container.querySelector('nav')).not.toBeInTheDocument() }) it('passes axe accessibility check', async () => { const { container } = render() const results = await axe(container) expect(results).toHaveNoViolations() }) })