import type { RefAttributes } from 'react'; import React from 'react'; import type { RadioGroupProps } from '..'; import Radio from '..'; import { fireEvent, render } from '../../../tests/utils'; describe('Radio Group', () => { function createRadioGroup(props?: RadioGroupProps & RefAttributes) { return ( A B C ); } function createRadioGroupByOption(props?: RadioGroupProps & RefAttributes) { const options = [ { label: 'A', value: 'A' }, { label: 'B', value: 'B' }, { label: 'C', value: 'C' }, ]; return ; } it('responses hover events', () => { const onMouseEnter = jest.fn(); const onMouseLeave = jest.fn(); const { container } = render( , ); fireEvent.mouseEnter(container.querySelector('div')!); expect(onMouseEnter).toHaveBeenCalled(); fireEvent.mouseLeave(container.querySelector('div')!); expect(onMouseLeave).toHaveBeenCalled(); }); it('fire change events when value changes', () => { const onChange = jest.fn(); const { container, rerender } = render( createRadioGroup({ onChange, }), ); const radios = container.querySelectorAll('input'); // controlled component rerender( createRadioGroup({ onChange, value: 'A', }), ); fireEvent.click(radios[1]); expect(onChange.mock.calls.length).toBe(1); }); it('both of radio and radioGroup will trigger onchange event when they exists', () => { const onChange = jest.fn(); const onChangeRadioGroup = jest.fn(); const RadioGroup: React.FC< RadioGroupProps & { onChangeRadioGroup: RadioGroupProps['onChange'] } > = (props) => ( A B C ); const { container, rerender } = render( , ); const radios = container.querySelectorAll('input'); // controlled component rerender(); fireEvent.click(radios[1]); expect(onChange.mock.calls.length).toBe(1); expect(onChangeRadioGroup.mock.calls.length).toBe(1); }); it('Trigger onChange when both of radioButton and radioGroup exists', () => { const onChange = jest.fn(); const RadioGroup: React.FC = (props) => ( A B C ); const { container, rerender } = render(); const radios = container.querySelectorAll('input'); // controlled component rerender(); fireEvent.click(radios[1]); expect(onChange.mock.calls.length).toBe(1); }); it('should only trigger once when in group with options', () => { const onChange = jest.fn(); const options = [{ label: 'Bamboo', value: 'Bamboo' }]; const { container } = render(); fireEvent.click(container.querySelector('input')!); expect(onChange).toHaveBeenCalledTimes(1); }); it("won't fire change events when value not changes", () => { const onChange = jest.fn(); const { container, rerender } = render( createRadioGroup({ onChange, }), ); const radios = container.querySelectorAll('input'); // controlled component rerender( createRadioGroup({ onChange, value: 'A', }), ); fireEvent.click(radios[0]); expect(onChange.mock.calls.length).toBe(0); }); it('optional should correct render', () => { const { container } = render(createRadioGroupByOption()); const radios = container.querySelectorAll('input'); expect(radios.length).toBe(3); }); it('all children should have a name property', () => { const GROUP_NAME = 'GROUP_NAME'; const { container } = render(createRadioGroup({ name: GROUP_NAME })); container.querySelectorAll('input[type="radio"]').forEach((el) => { expect(el.name).toEqual(GROUP_NAME); }); }); it('passes prefixCls down to radio', () => { const options = [ { label: 'Apple', value: 'Apple' }, { label: 'Orange', value: 'Orange', style: { fontSize: 12 } }, ]; const { container } = render(); expect(container.firstChild).toMatchSnapshot(); }); it('should forward ref', () => { let radioGroupRef: HTMLDivElement; const { container } = render( createRadioGroupByOption({ ref(ref: HTMLDivElement) { radioGroupRef = ref; }, }), ); expect(radioGroupRef!).toBe(container.querySelector('.ant-radio-group')); }); it('should support data-* or aria-* props', () => { const { container } = render( createRadioGroup({ 'data-radio-group-id': 'radio-group-id', 'aria-label': 'radio-group', } as RadioGroupProps), ); expect((container.firstChild as HTMLDivElement)?.getAttribute('data-radio-group-id')).toBe( 'radio-group-id', ); expect((container.firstChild as HTMLDivElement)?.getAttribute('aria-label')).toBe( 'radio-group', ); }); it('Radio type should not be override', () => { const onChange = jest.fn(); const { container } = render( A B C D , ); const radios = container.querySelectorAll('input'); fireEvent.click(radios[0]); expect(onChange).toHaveBeenCalled(); expect(radios[1].type).toBe('radio'); }); describe('value is null or undefined', () => { it('use `defaultValue` when `value` is undefined', () => { const options = [{ label: 'Bamboo', value: 'bamboo' }]; const { container } = render( , ); expect(container.querySelectorAll('.ant-radio-wrapper-checked').length).toBe(1); }); [undefined, null].forEach((newValue) => { it(`should set value back when value change back to ${newValue}`, () => { const options = [{ label: 'Bamboo', value: 'bamboo' }]; const { container, rerender } = render(); expect(container.querySelectorAll('.ant-radio-wrapper-checked').length).toBe(1); rerender(); expect(container.querySelectorAll('.ant-radio-wrapper-checked').length).toBe(0); }); }); }); it('onBlur & onFocus should work', () => { const handleBlur = jest.fn(); const handleFocus = jest.fn(); const { container } = render( , ); fireEvent.focus(container.firstChild!); expect(handleFocus).toHaveBeenCalledTimes(1); fireEvent.blur(container.firstChild!); expect(handleBlur).toHaveBeenCalledTimes(1); }); it('options support id', () => { const { container } = render( , ); expect(container.querySelector('#bamboo')).toBeTruthy(); }); it('options support title', () => { const { container } = render( , ); const select = container.querySelector('.ant-radio-group label > span'); expect(select).toBeTruthy(); // https://github.com/ant-design/ant-design/issues/46739 expect(select!.getAttribute('title')).toBeFalsy(); // fix 46739 solution expect(container.querySelector('.ant-radio-group label')).toHaveAttribute('title', 'bamboo'); }); });