import React from 'react' import { render, screen, fireEvent } from '@testing-library/react' import '@testing-library/jest-dom' import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '../accordion' describe('Accordion Components', () => { describe('Accordion Component', () => { it('renders correctly with default props', () => { render( Test Trigger Test Content ) const accordion = screen.getByTestId('accordion') expect(accordion).toBeInTheDocument() expect(screen.getByText('Test Trigger')).toBeInTheDocument() }) it('supports single type accordion', () => { render( Item 1 Content 1 Item 2 Content 2 ) const accordion = screen.getByTestId('accordion') expect(accordion).toBeInTheDocument() expect(screen.getByText('Item 1')).toBeInTheDocument() expect(screen.getByText('Item 2')).toBeInTheDocument() }) it('supports multiple type accordion', () => { render( Item 1 Content 1 Item 2 Content 2 ) const accordion = screen.getByTestId('accordion') expect(accordion).toBeInTheDocument() }) it('passes through HTML attributes', () => { render( Test Content ) const accordion = screen.getByTestId('accordion') expect(accordion).toHaveAttribute('id', 'custom-accordion') expect(accordion).toHaveAttribute('data-custom', 'value') }) it('handles controlled state', () => { const TestComponent = () => { const [value, setValue] = React.useState('') return ( Item 1 Content 1 ) } render() const accordion = screen.getByTestId('accordion') expect(accordion).toBeInTheDocument() }) }) describe('AccordionItem Component', () => { it('renders correctly with default props', () => { render( Test Trigger Test Content ) const item = screen.getByTestId('accordion-item') expect(item).toBeInTheDocument() expect(item).toHaveAttribute('data-state', 'closed') }) it('applies custom className', () => { render( Test Content ) const item = screen.getByTestId('accordion-item') expect(item).toHaveClass('custom-item') }) it('has correct default styling', () => { render( Test Content ) const item = screen.getByTestId('accordion-item') expect(item).toHaveClass('border-b') expect(item).toHaveClass('border-gray-200') expect(item).toHaveClass('dark:border-gray-800') }) it('forwards ref correctly', () => { const ref = React.createRef() render( Test Content ) expect(ref.current).toBeInstanceOf(HTMLDivElement) }) it('maintains displayName', () => { expect(AccordionItem.displayName).toBe('AccordionItem') }) it('passes through HTML attributes', () => { render( Test Content ) const item = screen.getByTestId('accordion-item') expect(item).toHaveAttribute('id', 'custom-item') expect(item).toHaveAttribute('data-custom', 'value') }) }) describe('AccordionTrigger Component', () => { it('renders correctly with default props', () => { render( Test Trigger Test Content ) const trigger = screen.getByTestId('accordion-trigger') expect(trigger).toBeInTheDocument() expect(trigger).toHaveTextContent('Test Trigger') expect(trigger).toHaveAttribute('type', 'button') }) it('applies custom className', () => { render( Test Content ) const trigger = screen.getByTestId('accordion-trigger') expect(trigger).toHaveClass('custom-trigger') }) it('has correct default styling', () => { render( Test Content ) const trigger = screen.getByTestId('accordion-trigger') expect(trigger).toHaveClass('flex') expect(trigger).toHaveClass('flex-1') expect(trigger).toHaveClass('items-center') expect(trigger).toHaveClass('justify-between') expect(trigger).toHaveClass('py-4') expect(trigger).toHaveClass('font-medium') }) it('renders chevron icon', () => { render( Test Content ) const trigger = screen.getByTestId('accordion-trigger') const chevron = trigger.querySelector('svg') expect(chevron).toBeInTheDocument() expect(chevron).toHaveClass('h-4') expect(chevron).toHaveClass('w-4') expect(chevron).toHaveClass('shrink-0') }) it('handles click events', () => { render( Test Content ) const trigger = screen.getByTestId('accordion-trigger') fireEvent.click(trigger) // Check if the item is now open const item = trigger.closest('[data-state]') expect(item).toHaveAttribute('data-state', 'open') }) it('toggles chevron rotation when opened', () => { render( Test Content ) const trigger = screen.getByTestId('accordion-trigger') fireEvent.click(trigger) // Check if chevron has rotation class expect(trigger).toHaveClass('[&[data-state=open]>svg]:rotate-180') }) it('forwards ref correctly', () => { const ref = React.createRef() render( Test Content ) expect(ref.current).toBeInstanceOf(HTMLButtonElement) }) it('passes through HTML attributes', () => { render( Test Content ) const trigger = screen.getByTestId('accordion-trigger') expect(trigger).toHaveAttribute('id', 'custom-trigger') expect(trigger).toHaveAttribute('data-custom', 'value') }) }) describe('AccordionContent Component', () => { it('renders correctly when accordion is open', () => { render( Test Trigger Test Content ) const content = screen.getByTestId('accordion-content') expect(content).toBeInTheDocument() expect(content).toHaveTextContent('Test Content') }) it('applies custom className', () => { render( Test Content ) const content = screen.getByTestId('accordion-content') expect(content).toHaveClass('custom-content') }) it('has correct default styling', () => { render( Test Content ) const content = screen.getByTestId('accordion-content') expect(content).toHaveClass('overflow-hidden') expect(content).toHaveClass('text-sm') expect(content).toHaveClass('text-gray-700') expect(content).toHaveClass('dark:text-gray-300') }) it('has animation classes', () => { render( Test Content ) const content = screen.getByTestId('accordion-content') expect(content).toHaveClass('data-[state=closed]:animate-accordion-up') expect(content).toHaveClass('data-[state=open]:animate-accordion-down') }) it('renders content wrapper with correct styling', () => { render( Test Test Content ) const content = screen.getByTestId('accordion-content') const wrapper = content.querySelector('div') expect(wrapper).toBeInTheDocument() expect(wrapper).toHaveClass('pb-4') expect(wrapper).toHaveClass('pt-0') expect(wrapper).toHaveTextContent('Test Content') }) it('forwards ref correctly', () => { const ref = React.createRef() render( Test Content ) expect(ref.current).toBeInstanceOf(HTMLDivElement) }) it('passes through HTML attributes', () => { render( Test Content ) const content = screen.getByTestId('accordion-content') expect(content).toHaveAttribute('id', 'custom-content') expect(content).toHaveAttribute('data-custom', 'value') }) }) describe('Complex Combinations', () => { it('renders multiple accordion items', () => { render( Item 1 Content 1 Item 2 Content 2 Item 3 Content 3 ) expect(screen.getByText('Item 1')).toBeInTheDocument() expect(screen.getByText('Item 2')).toBeInTheDocument() expect(screen.getByText('Item 3')).toBeInTheDocument() }) it('handles single type accordion interaction', () => { render( Item 1 Content 1 Item 2 Content 2 ) const trigger1 = screen.getByTestId('trigger-1') const trigger2 = screen.getByTestId('trigger-2') // Open first item fireEvent.click(trigger1) expect(trigger1.closest('[data-state]')).toHaveAttribute('data-state', 'open') // Open second item (should close first) fireEvent.click(trigger2) expect(trigger1.closest('[data-state]')).toHaveAttribute('data-state', 'closed') expect(trigger2.closest('[data-state]')).toHaveAttribute('data-state', 'open') }) it('handles multiple type accordion interaction', () => { render( Item 1 Content 1 Item 2 Content 2 ) const trigger1 = screen.getByTestId('trigger-1') const trigger2 = screen.getByTestId('trigger-2') // Open both items fireEvent.click(trigger1) fireEvent.click(trigger2) expect(trigger1.closest('[data-state]')).toHaveAttribute('data-state', 'open') expect(trigger2.closest('[data-state]')).toHaveAttribute('data-state', 'open') }) it('renders with all custom props', () => { render( Custom Item Custom Content ) const accordion = screen.getByTestId('accordion') expect(accordion).toHaveClass('custom-accordion') const item = accordion.querySelector('[data-state]') expect(item).toHaveClass('custom-item') const trigger = screen.getByText('Custom Item') expect(trigger).toHaveClass('custom-trigger') }) }) describe('Edge Cases', () => { it('handles empty accordion', () => { render() const accordion = screen.getByTestId('accordion') expect(accordion).toBeInTheDocument() }) it('handles accordion with no content', () => { render( Empty Item ) expect(screen.getByText('Empty Item')).toBeInTheDocument() }) it('handles accordion with complex content', () => { render( Complex Item

Paragraph 1

Paragraph 2

) expect(screen.getByText('Paragraph 1')).toBeInTheDocument() expect(screen.getByText('Paragraph 2')).toBeInTheDocument() expect(screen.getByText('Action Button')).toBeInTheDocument() }) it('handles disabled accordion item', () => { render( Disabled Item Content ) const trigger = screen.getByTestId('disabled-trigger') expect(trigger).toBeDisabled() }) }) })