import React from 'react'
import { describe, expect, it, vi } from 'vitest'
import { fireEvent, renderWithProviders, screen } from '../../test/utils'
import { getAvatarEmoji } from '../Avatar/getAvatarEmoji'
import { FaqListItem } from './FaqListItem'
import { FaqList } from './index'
const faqs = [
{
id: 'second',
question: 'What payment methods do you accept?',
answer: 'Cards and bank transfers.',
enabled: true,
order: 2,
},
{
id: 'disabled',
question: 'What is your phone number?',
answer: 'This FAQ is disabled.',
enabled: false,
order: 0,
},
{
id: 'first',
question: 'How do I get started?',
answer: 'Create an account.',
enabled: true,
order: 1,
},
]
const baseItemClasses = [
'w-full',
'text-center',
'p-4',
'rounded-xl',
'text-charcoal',
'font-medium',
'transition-colors',
'focus-ring',
]
describe('FaqListItem', () => {
it('renders its question and defaults to an enabled button', () => {
renderWithProviders(
)
const button = screen.getByRole('button', {
name: 'How do I get started?',
})
expect(button).toBeEnabled()
expect(button.className.split(/\s+/)).toEqual([
...baseItemClasses,
'hover:brightness-95',
'active:brightness-90',
])
})
it('renders the FAQ surface color', () => {
renderWithProviders(
)
expect(
screen.getByRole('button', { name: 'How do I get started?' })
).toHaveStyle({ backgroundColor: '#E6E5E3' })
})
it('uses loading-only classes and blocks clicks while loading', () => {
const onClick = vi.fn()
renderWithProviders(
)
const button = screen.getByRole('button', {
name: 'How do I get started?',
})
expect(button).toBeDisabled()
expect(button.className.split(/\s+/)).toEqual([
...baseItemClasses,
'opacity-50',
'cursor-not-allowed',
])
fireEvent.click(button)
expect(onClick).not.toHaveBeenCalled()
})
it('calls the click handler once when enabled', () => {
const onClick = vi.fn()
renderWithProviders(
)
fireEvent.click(screen.getByRole('button'))
expect(onClick).toHaveBeenCalledTimes(1)
})
})
describe('FaqList', () => {
it('returns nothing when no FAQ is enabled', () => {
const { container } = renderWithProviders(
({ ...faq, enabled: false }))}
onFaqClick={vi.fn()}
/>
)
expect(container.firstChild).toBeNull()
})
it('renders enabled FAQs in ascending order and filters disabled FAQs', () => {
renderWithProviders()
expect(
screen.getByRole('button', { name: 'How do I get started?' })
.parentElement
).toHaveStyle({ backgroundColor: '#F1F0EE' })
expect(
screen.getAllByRole('button').map((button) => button.textContent)
).toEqual(['How do I get started?', 'What payment methods do you accept?'])
expect(
screen.queryByRole('button', { name: 'What is your phone number?' })
).toBeNull()
})
it('renders the header only when headerText is provided', () => {
const { container, rerender } = renderWithProviders(
)
expect(screen.queryByText('Frequently asked questions')).toBeNull()
expect(container.querySelector('p')).toBeNull()
rerender(
)
expect(screen.getByText('Frequently asked questions')).toBeInTheDocument()
})
it('passes className to the list root', () => {
const { container } = renderWithProviders(
)
expect(container.firstElementChild).toHaveClass('faq-list-custom-class')
})
it('renders an avatar only when avatar data is provided', () => {
const { rerender } = renderWithProviders(
)
expect(screen.queryAllByTestId('avatar-ring')).toHaveLength(0)
rerender(
)
expect(screen.queryAllByTestId('avatar-ring')).toHaveLength(1)
expect(screen.getByText(getAvatarEmoji('Brie Nala'))).toBeInTheDocument()
rerender(
)
expect(screen.queryAllByTestId('avatar-ring')).toHaveLength(1)
})
it('passes the clicked FAQ id and marks only its matching row as loading', () => {
const onFaqClick = vi.fn()
renderWithProviders(
)
const firstButton = screen.getByRole('button', {
name: 'How do I get started?',
})
const secondButton = screen.getByRole('button', {
name: 'What payment methods do you accept?',
})
expect(firstButton).toBeEnabled()
expect(secondButton).toBeDisabled()
expect(firstButton).not.toHaveClass('opacity-50', 'cursor-not-allowed')
expect(secondButton).toHaveClass('opacity-50', 'cursor-not-allowed')
fireEvent.click(firstButton)
fireEvent.click(secondButton)
expect(onFaqClick).toHaveBeenCalledTimes(1)
expect(onFaqClick).toHaveBeenCalledWith('first')
})
})