import { render, screen } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { describe, it, expect, vi } from 'vitest' import { axe } from 'vitest-axe' import { Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbSeparator, BreadcrumbEllipsis, } from './breadcrumb' function renderBasic() { return render( Home Components Breadcrumb , ) } describe('Breadcrumb', () => { it('renders a nav with breadcrumb label and an ordered list', () => { renderBasic() const nav = screen.getByRole('navigation', { name: 'breadcrumb' }) expect(nav.tagName).toBe('NAV') expect(nav).toHaveAttribute('data-slot', 'breadcrumb') const list = screen.getByRole('list') expect(list.tagName).toBe('OL') expect(list).toHaveAttribute('data-slot', 'breadcrumb-list') }) it('renders BreadcrumbItem as li', () => { renderBasic() const items = screen.getAllByRole('listitem') expect(items.length).toBeGreaterThan(0) items.forEach((li) => expect(li.tagName).toBe('LI')) }) it('renders an inactive link as and fires onClick', async () => { const user = userEvent.setup() const onClick = vi.fn() render( Home , ) const link = screen.getByRole('link', { name: 'Home' }) expect(link.tagName).toBe('A') await user.click(link) expect(onClick).toHaveBeenCalledOnce() }) it('renders an active link as a non-focusable with aria-current="page" and data-active', () => { renderBasic() const active = screen.getByText('Breadcrumb') expect(active.tagName).toBe('SPAN') expect(active).toHaveAttribute('aria-current', 'page') expect(active).toHaveAttribute('aria-disabled', 'true') expect(active).toHaveAttribute('data-active') expect(active).toHaveAttribute('tabindex', '-1') }) it('marks a disabled link with aria-disabled and data-disabled', () => { render( Frozen , ) const link = screen.getByRole('link', { name: 'Frozen' }) expect(link).toHaveAttribute('aria-disabled', 'true') expect(link).toHaveAttribute('data-disabled') }) it('forwards className to the link alongside default classes', () => { render( Home , ) expect(screen.getByRole('link', { name: 'Home' }).className).toContain('my-link') }) it('renders the link as a different element via render prop', () => { const onClick = vi.fn() render( }>Settings , ) const el = screen.getByRole('button', { name: 'Settings' }) expect(el.tagName).toBe('BUTTON') }) it('renders a default separator svg, overridable via children', () => { const { rerender } = render( A , ) const sep = screen.getByTestId('sep') expect(sep).toHaveAttribute('data-slot', 'breadcrumb-separator') expect(sep.querySelector('svg')).not.toBeNull() rerender( A / , ) const sepAgain = screen.getByTestId('sep') expect(sepAgain.querySelector('svg')).toBeNull() expect(sepAgain).toHaveTextContent('/') }) it('renders the ellipsis as a decorative (aria-hidden) element', () => { renderBasic() const ellipsis = document.querySelector('[data-slot="breadcrumb-ellipsis"]') expect(ellipsis).not.toBeNull() expect(ellipsis).toHaveAttribute('aria-hidden') }) it('has no accessibility violations', async () => { const { container } = renderBasic() expect(await axe(container)).toHaveNoViolations() }) })