import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { describe, expect, it, vi } from 'vitest'; import { MdRadioButton } from '../MdRadioButton'; describe('MdRadioButton', () => { describe('rendering', () => { it('renders a radio input', () => { render(); expect(screen.getByRole('radio')).toBeInTheDocument(); }); it('renders with label', () => { render(); expect(screen.getByLabelText('Option 1')).toBeInTheDocument(); }); it('renders selected dot when checked', () => { const { container } = render( {}} />); expect(container.querySelector('.md-radiobutton__selected-dot')).toBeInTheDocument(); }); it('does not render selected dot when unchecked', () => { const { container } = render( {}} />); expect(container.querySelector('.md-radiobutton__selected-dot')).not.toBeInTheDocument(); }); }); describe('states', () => { it('can be checked', () => { render( {}} />); expect(screen.getByRole('radio')).toBeChecked(); }); it('can be unchecked', () => { render( {}} />); expect(screen.getByRole('radio')).not.toBeChecked(); }); it('can be disabled', () => { render(); expect(screen.getByRole('radio')).toBeDisabled(); }); it('applies disabled class', () => { const { container } = render(); expect(container.querySelector('.md-radiobutton--disabled')).toBeInTheDocument(); }); }); describe('interactions', () => { it('handles change events', async () => { const user = userEvent.setup(); const onChange = vi.fn(); render(); await user.click(screen.getByRole('radio')); expect(onChange).toHaveBeenCalledTimes(1); }); it('does not fire change when disabled', async () => { const user = userEvent.setup(); const onChange = vi.fn(); render(); await user.click(screen.getByRole('radio')); expect(onChange).not.toHaveBeenCalled(); }); }); describe('accessibility', () => { it('has aria-checked attribute', () => { render( {}} />); expect(screen.getByRole('radio')).toHaveAttribute('aria-checked', 'true'); }); it('associates label with radio', () => { render(); expect(screen.getByLabelText('My option')).toBeInTheDocument(); }); }); describe('props forwarding', () => { it('forwards id', () => { render(); expect(screen.getByRole('radio')).toHaveAttribute('id', 'my-radio'); }); it('forwards name for radio group', () => { render(); expect(screen.getByRole('radio')).toHaveAttribute('name', 'options'); }); it('forwards value', () => { render(); expect(screen.getByRole('radio')).toHaveAttribute('value', 'option1'); }); it('merges custom className', () => { const { container } = render(); expect(container.querySelector('.md-radiobutton')).toHaveClass('custom-class'); }); }); describe('radio group behavior', () => { it('works in a group with same name', async () => { const user = userEvent.setup(); const onChange = vi.fn(); render( <> , ); const radioA = screen.getByLabelText('Option A'); const radioB = screen.getByLabelText('Option B'); await user.click(radioA); expect(onChange).toHaveBeenCalled(); await user.click(radioB); expect(radioA).not.toBeChecked(); expect(radioB).toBeChecked(); }); }); });