import '@testing-library/jest-dom'
import { fireEvent,render, screen } from '@testing-library/react'
import { axe, toHaveNoViolations } from 'jest-axe'
import { vi } from 'vitest'
import { createRef } from 'react'
import { PktAccordion } from './Accordion'
import { PktAccordionItem } from './AccordionItem'
expect.extend(toHaveNoViolations)
describe('PktAccordion', () => {
test('renders without errors', () => {
render(
content
,
)
// Assert that the Accordion component renders without throwing any errors
})
test('renders children', () => {
const mockToggleOpen = vi.fn()
render(
Content 1
Content 2
,
)
// Assert that the Accordion component renders its children correctly
expect(screen.getByText('Title 1')).toBeInTheDocument()
expect(screen.getByText('Content 1')).toBeInTheDocument()
expect(screen.getByText('Title 2')).toBeInTheDocument()
expect(screen.getByText('Content 2')).toBeInTheDocument()
})
test('applies compact and skin classes', () => {
const { container } = render(
<>
Accordion Heading
Content
>,
)
const accordion = container.querySelector('[data-testid="pkt-accordion"]')!
expect(accordion).toBeInTheDocument()
expect(accordion).toHaveClass('pkt-accordion')
expect(accordion).toHaveClass('pkt-accordion--compact')
expect(accordion).toHaveClass('pkt-accordion--blue')
expect(accordion).toHaveAttribute('aria-labelledby', 'accordion-heading')
})
test('forwards ref correctly', () => {
const ref = createRef()
render(
Content
,
)
expect(ref.current).toBeDefined()
expect(ref.current?.tagName).toBe('DIV')
expect(ref.current).toHaveClass('pkt-accordion')
})
})
describe('PktAccordionItem', () => {
test('applies compact and skin classes', () => {
const { container } = render(
Content
,
)
const details = container.querySelector('details')!
expect(details).toBeInTheDocument()
expect(details).toHaveClass('pkt-accordion-item')
expect(details).toHaveClass('pkt-accordion-item--blue')
expect(details).toHaveClass('pkt-accordion-item--compact')
})
test('renders with correct structure', () => {
const { container } = render(
Test Content
,
)
const details = container.querySelector('details')!
const summary = details.querySelector('summary')!
const content = details.querySelector('.pkt-accordion-item__content')!
const contentInner = content.querySelector('.pkt-accordion-item__content-inner')!
expect(details).toHaveAttribute('id', 'test-item')
expect(summary).toHaveClass('pkt-accordion-item__title')
expect(summary).toHaveAttribute('id', 'pkt-accordion-item-summary-test-item')
expect(summary).toHaveTextContent('Test Title')
expect(content).toHaveAttribute('id', 'pkt-accordion-item__content-test-item')
expect(content).toHaveAttribute('role', 'region')
expect(contentInner).toHaveTextContent('Test Content')
})
test('handles defaultOpen prop', () => {
const { container } = render(
Content
,
)
const details = container.querySelector('details')!
expect(details).toHaveAttribute('open')
})
test('handles controlled isOpen prop', () => {
const { container, rerender } = render(
Content
,
)
const details = container.querySelector('details')!
expect(details).not.toHaveAttribute('open')
rerender(
Content
,
)
expect(details).toHaveAttribute('open')
})
test('calls onClick handler', () => {
const mockOnClick = vi.fn()
const { container } = render(
Content
,
)
const details = container.querySelector('details')!
fireEvent.click(details)
// onClick is called after a setTimeout, so we need to wait
setTimeout(() => {
expect(mockOnClick).toHaveBeenCalledTimes(1)
}, 10)
})
test('forwards ref correctly', () => {
const ref = createRef()
render(
Content
,
)
expect(ref.current).toBeDefined()
expect(ref.current?.tagName).toBe('DETAILS')
expect(ref.current).toHaveClass('pkt-accordion-item')
})
test('renders PktIcon', async () => {
const { container } = render(
Content
,
)
await window.customElements.whenDefined('pkt-icon')
const icon = container.querySelector('pkt-icon')
expect(icon).toBeInTheDocument()
expect(icon).toHaveAttribute('name', 'chevron-thin-down')
expect(icon).toHaveClass('pkt-accordion-item__icon')
expect(icon).toHaveAttribute('aria-hidden', 'true')
})
})
describe('accessibility', () => {
it('renders with no wcag errors with axe', async () => {
const { container } = render(
Content 1
Content 2
,
)
const results = await axe(container)
expect(results).toHaveNoViolations()
})
})