import { fireEvent, render, screen } from '@testing-library/react' import { IndexingType } from '../../create/step-two' import IndexMethod from './index' // Note: react-i18next is globally mocked in vitest.setup.ts describe('IndexMethod', () => { const defaultProps = { value: IndexingType.QUALIFIED, onChange: vi.fn(), keywordNumber: 10, onKeywordNumberChange: vi.fn(), } beforeEach(() => { vi.clearAllMocks() }) describe('Rendering', () => { it('should render without crashing', () => { render() expect(screen.getByText(/stepTwo\.qualified/)).toBeInTheDocument() }) it('should render High Quality option', () => { render() expect(screen.getByText(/stepTwo\.qualified/)).toBeInTheDocument() }) it('should render Economy option', () => { render() expect(screen.getAllByText(/form\.indexMethodEconomy/).length).toBeGreaterThan(0) }) it('should render High Quality description', () => { render() expect(screen.getByText(/form\.indexMethodHighQualityTip/)).toBeInTheDocument() }) it('should render Economy description', () => { render() expect(screen.getByText(/form\.indexMethodEconomyTip/)).toBeInTheDocument() }) it('should render recommended badge on High Quality', () => { render() expect(screen.getByText(/stepTwo\.recommend/)).toBeInTheDocument() }) }) describe('Active State', () => { it('should mark High Quality as active when value is QUALIFIED', () => { const { container } = render() const activeCards = container.querySelectorAll('.ring-\\[1px\\]') expect(activeCards).toHaveLength(1) }) it('should mark Economy as active when value is ECONOMICAL', () => { const { container } = render() const activeCards = container.querySelectorAll('.ring-\\[1px\\]') expect(activeCards).toHaveLength(1) }) }) describe('User Interactions', () => { it('should call onChange with QUALIFIED when High Quality is clicked', () => { const handleChange = vi.fn() render() // Find and click High Quality option const highQualityTitle = screen.getByText(/stepTwo\.qualified/) const card = highQualityTitle.closest('div')?.parentElement?.parentElement?.parentElement fireEvent.click(card!) expect(handleChange).toHaveBeenCalledWith(IndexingType.QUALIFIED) }) it('should call onChange with ECONOMICAL when Economy is clicked', () => { const handleChange = vi.fn() render() // Find and click Economy option - use getAllByText and get the first one (title) const economyTitles = screen.getAllByText(/form\.indexMethodEconomy/) const economyTitle = economyTitles[0] const card = economyTitle.closest('div')?.parentElement?.parentElement?.parentElement fireEvent.click(card!) expect(handleChange).toHaveBeenCalledWith(IndexingType.ECONOMICAL) }) it('should not call onChange when clicking already active option', () => { const handleChange = vi.fn() render() // Click on already active High Quality const highQualityTitle = screen.getByText(/stepTwo\.qualified/) const card = highQualityTitle.closest('div')?.parentElement?.parentElement?.parentElement fireEvent.click(card!) expect(handleChange).not.toHaveBeenCalled() }) }) describe('Disabled State', () => { it('should disable both options when disabled is true', () => { const { container } = render() const disabledCards = container.querySelectorAll('.cursor-not-allowed') expect(disabledCards.length).toBeGreaterThan(0) }) it('should disable Economy option when currentValue is QUALIFIED', () => { const handleChange = vi.fn() render() // Try to click Economy option - use getAllByText and get the first one (title) const economyTitles = screen.getAllByText(/form\.indexMethodEconomy/) const economyTitle = economyTitles[0] const card = economyTitle.closest('div')?.parentElement?.parentElement?.parentElement fireEvent.click(card!) // Should not call onChange because Economy is disabled when current is QUALIFIED expect(handleChange).not.toHaveBeenCalled() }) }) describe('KeywordNumber', () => { it('should render KeywordNumber component inside Economy option', () => { render() // KeywordNumber has a slider expect(screen.getByRole('slider')).toBeInTheDocument() }) it('should pass keywordNumber to KeywordNumber component', () => { render() const input = screen.getByRole('spinbutton') expect(input).toHaveValue(25) }) it('should call onKeywordNumberChange when KeywordNumber changes', () => { const handleKeywordChange = vi.fn() render() const input = screen.getByRole('spinbutton') fireEvent.change(input, { target: { value: '30' } }) expect(handleKeywordChange).toHaveBeenCalled() }) }) describe('Tooltip', () => { it('should show tooltip when hovering over disabled Economy option', () => { // The tooltip is shown via PortalToFollowElem when hovering // This is controlled by useHover hook render() // The tooltip content should exist in DOM but may not be visible // We just verify the component renders without error expect(screen.getAllByText(/form\.indexMethodEconomy/).length).toBeGreaterThan(0) }) }) describe('Effect Colors', () => { it('should show orange effect color for High Quality option', () => { const { container } = render() const orangeEffect = container.querySelector('.bg-util-colors-orange-orange-500') expect(orangeEffect).toBeInTheDocument() }) it('should show indigo effect color for Economy option', () => { const { container } = render() const indigoEffect = container.querySelector('.bg-util-colors-indigo-indigo-600') expect(indigoEffect).toBeInTheDocument() }) }) describe('Props', () => { it('should update active state when value prop changes', () => { const { rerender, container } = render() let activeCards = container.querySelectorAll('.ring-\\[1px\\]') expect(activeCards).toHaveLength(1) rerender() activeCards = container.querySelectorAll('.ring-\\[1px\\]') expect(activeCards).toHaveLength(1) }) }) describe('Edge Cases', () => { it('should handle undefined currentValue', () => { render() // Should render without error expect(screen.getByText(/stepTwo\.qualified/)).toBeInTheDocument() }) it('should handle keywordNumber of 0', () => { render() const input = screen.getByRole('spinbutton') expect(input).toHaveValue(0) }) it('should handle max keywordNumber', () => { render() const input = screen.getByRole('spinbutton') expect(input).toHaveValue(50) }) }) })