import { isInaccessible } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { render } from '~/src/utils/test' import { Radio, RadioGroup } from './RadioGroup' import { type RadioGroupProps, type RadioProps } from './RadioGroup.types' const VALUES = ['0', '1', '2'] describe('RadioGroup', () => { const renderRadioGroup = ({ radioGroupProps, radioProps, }: { radioGroupProps?: RadioGroupProps radioProps?: Partial> } = {}) => render( {VALUES.map((value) => ( {value} ))} ) let user: ReturnType beforeEach(() => { user = userEvent.setup() }) describe('ARIA', () => { it('should be accessible', () => { const { container } = renderRadioGroup() expect(isInaccessible(container)).toBe(false) }) it('should have \'role="radiogroup"\' attribute', () => { const { getByRole } = renderRadioGroup() expect(getByRole('radiogroup')).toBeInTheDocument() }) it('should be required when required prop is true', () => { const { getByRole } = renderRadioGroup({ radioGroupProps: { required: true }, }) expect(getByRole('radiogroup')).toBeRequired() }) it('should be disabled when disabled prop is true', () => { const { getByRole } = renderRadioGroup({ radioGroupProps: { disabled: true }, }) expect(getByRole('radiogroup')).toHaveAttribute('aria-disabled', 'true') }) it('children(Radio) should be disabled when disabled prop is true', () => { const { getAllByRole } = renderRadioGroup({ radioGroupProps: { disabled: true }, }) const radios = getAllByRole('radio') radios.forEach((radio) => expect(radio).toBeDisabled()) }) }) describe('User Interactions', () => { it('should focus and check radio when user clicks on a radio', async () => { const { getByRole } = renderRadioGroup() const radio = getByRole('radio', { name: VALUES[0] }) await user.click(radio) expect(radio).toHaveFocus() expect(radio).toBeChecked() }) it('should call the change event handler when user clicks on a radio in a controlled radio group', async () => { const onValueChange = jest.fn() const { getByRole } = renderRadioGroup({ radioGroupProps: { value: VALUES[0], onValueChange }, }) const radio = getByRole('radio', { name: VALUES[1] }) await user.click(radio) expect(onValueChange).toHaveBeenCalledTimes(1) }) it('should focus on the first radio item when user presses tab key', async () => { const { getByRole } = renderRadioGroup() const radio = getByRole('radio', { name: VALUES[0] }) await user.tab() expect(radio).toHaveFocus() }) it('should check radio when user presses space key on a focused radio', async () => { const { getByRole } = renderRadioGroup() const radio = getByRole('radio', { name: VALUES[0] }) await user.tab() expect(radio).toHaveFocus() await user.keyboard('{ }') expect(radio).toHaveFocus() expect(radio).toBeChecked() }) it('should focus and check the next radio item when user presses arrow down key on a radio', async () => { const { getByRole } = renderRadioGroup() const radio = getByRole('radio', { name: VALUES[0] }) const nextRadio = getByRole('radio', { name: VALUES[1] }) await user.tab() expect(radio).toHaveFocus() await user.keyboard('{ArrowDown}') expect(nextRadio).toHaveFocus() // FIXME: Checking behavior does not work in test environment when arrow key is pressed // expect(nextRadio).toBeChecked() }) it('should focus and check the next radio item when user presses arrow right key on a radio', async () => { const { getByRole } = renderRadioGroup() const radio = getByRole('radio', { name: VALUES[0] }) const nextRadio = getByRole('radio', { name: VALUES[1] }) await user.tab() expect(radio).toHaveFocus() await user.keyboard('{ArrowRight}') expect(nextRadio).toHaveFocus() // FIXME: Checking behavior does not work in test environment when arrow key is pressed // expect(nextRadio).toBeChecked() }) it('should focus and check the previous radio item when user presses arrow up key on a radio', async () => { const { getByRole } = renderRadioGroup() const radio = getByRole('radio', { name: VALUES[0] }) const nextRadio = getByRole('radio', { name: VALUES[2] }) await user.tab() expect(radio).toHaveFocus() await user.keyboard('{ArrowUp}') expect(nextRadio).toHaveFocus() // FIXME: Checking behavior does not work in test environment when arrow key is pressed // expect(nextRadio).toBeChecked() }) it('should focus and check the previous radio item when user presses arrow left key on a radio', async () => { const { getByRole } = renderRadioGroup() const radio = getByRole('radio', { name: VALUES[0] }) const nextRadio = getByRole('radio', { name: VALUES[2] }) await user.tab() expect(radio).toHaveFocus() await user.keyboard('{ArrowLeft}') expect(nextRadio).toHaveFocus() // FIXME: Checking behavior does not work in test environment when arrow key is pressed // expect(nextRadio).toBeChecked() }) }) describe('Radio', () => { describe('ARIA', () => { it('should have \'role="radio"\' attribute', () => { const { getAllByRole } = renderRadioGroup() const radios = getAllByRole('radio') radios.forEach((radio) => expect(radio).toBeInTheDocument()) }) it('should be disabled when disabled prop is true', () => { const { getAllByRole } = renderRadioGroup({ radioProps: { disabled: true }, }) const radios = getAllByRole('radio') radios.forEach((radio) => expect(radio).toBeDisabled()) }) }) }) })