import { describe, expect, it } from 'vitest'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from './accordion'; /* Only the two knobs these tests turn — `Partial` would widen `type` back to the full union and stop matching `type="single"`. */ const Example = (props: { variant?: 'card' | 'list'; defaultValue?: string } = {}) => ( Shipping Two to five working days. Returns Thirty days from delivery. ); describe('Accordion', () => { it('keeps collapsed content out of the document', () => { render(); expect(screen.queryByText('Two to five working days.')).not.toBeInTheDocument(); }); it('opens a section on click', async () => { render(); await userEvent.click(screen.getByRole('button', { name: 'Shipping' })); expect(await screen.findByText('Two to five working days.')).toBeInTheDocument(); }); it('closes the open section when another is opened', async () => { render(); await userEvent.click(screen.getByRole('button', { name: 'Returns' })); expect(screen.queryByText('Two to five working days.')).not.toBeInTheDocument(); expect(screen.getByText('Thirty days from delivery.')).toBeInTheDocument(); }); /* * The item reads its shape off the root through `group-data-*`, so the * attribute is the contract between them — losing it leaves every item * unstyled rather than throwing. */ it('publishes the variant the items style themselves from', () => { const { container, rerender } = render(); expect(container.querySelector('[data-slot="accordion"]')).toHaveAttribute( 'data-variant', 'card' ); rerender(); expect(container.querySelector('[data-slot="accordion"]')).toHaveAttribute( 'data-variant', 'list' ); }); /* * `--card` is the tinted surface CBAR gives an actual card; an accordion * section is flat white. The two roles used to hold the same value, so a * regression here is invisible until someone looks at both side by side. */ it('draws a card section on the page surface, not the card surface', () => { const { container } = render(); const item = container.querySelector('[data-slot="accordion-item"]'); expect(item?.className).toContain('bg-background'); expect(item?.className).not.toContain('bg-card'); }); it('defaults to the secondary palette the chevron is drawn from', () => { const { container } = render(); expect(container.querySelector('[data-slot="accordion"]')).toHaveClass('palette-secondary'); }); /* Radix marks the trigger, not the item, so this is what the icon rotation and its colour change both hang off. */ it('reflects the open state on the trigger', async () => { render(); const trigger = screen.getByRole('button', { name: 'Shipping' }); expect(trigger).toHaveAttribute('data-state', 'closed'); await userEvent.click(trigger); expect(trigger).toHaveAttribute('data-state', 'open'); }); });