From 7777f42ba5bcd521370119dbc8a76e7a61f69e67 Mon Sep 17 00:00:00 2001 From: unix Date: Thu, 23 Apr 2020 11:41:12 +0800 Subject: [PATCH 1/7] test(radio): add testcase --- .../__snapshots__/group.test.tsx.snap | 265 ++++++++++++++++++ .../__snapshots__/index.test.tsx.snap | 251 +++++++++++++++++ components/radio/__tests__/group.test.tsx | 120 ++++++++ components/radio/__tests__/index.test.tsx | 65 +++++ 4 files changed, 701 insertions(+) create mode 100644 components/radio/__tests__/__snapshots__/group.test.tsx.snap create mode 100644 components/radio/__tests__/__snapshots__/index.test.tsx.snap create mode 100644 components/radio/__tests__/group.test.tsx create mode 100644 components/radio/__tests__/index.test.tsx diff --git a/components/radio/__tests__/__snapshots__/group.test.tsx.snap b/components/radio/__tests__/__snapshots__/group.test.tsx.snap new file mode 100644 index 0000000..35d689b --- /dev/null +++ b/components/radio/__tests__/__snapshots__/group.test.tsx.snap @@ -0,0 +1,265 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Radio should render correctly 1`] = ` +"
" +`; diff --git a/components/radio/__tests__/__snapshots__/index.test.tsx.snap b/components/radio/__tests__/__snapshots__/index.test.tsx.snap new file mode 100644 index 0000000..2bc1d91 --- /dev/null +++ b/components/radio/__tests__/__snapshots__/index.test.tsx.snap @@ -0,0 +1,251 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Radio should render correctly 1`] = ` +"
" +`; + +exports[`Radio should support react-node in description 1`] = ` +"
" +`; diff --git a/components/radio/__tests__/group.test.tsx b/components/radio/__tests__/group.test.tsx new file mode 100644 index 0000000..c5f278e --- /dev/null +++ b/components/radio/__tests__/group.test.tsx @@ -0,0 +1,120 @@ +import React from 'react' +import { mount } from 'enzyme' +import { Radio } from 'components' +import { nativeEvent } from 'tests/utils' + +describe('Radio', () => { + it('should render correctly', () => { + const wrapper = mount( +
+ + 1 + 2 + + + 1 + 2 + +
+ ) + expect(wrapper.html()).toMatchSnapshot() + expect(() => wrapper.unmount()).not.toThrow() + }) + + it('should trigger events in group', () => { + let value = '' + const changeHandler = jest.fn() + .mockImplementation(val => value = val) + const wrapper = mount( + + Option 1 + Option 2 + + ) + + wrapper.find('input').at(0) + .simulate('change', { + ...nativeEvent, + target: { checked: true }, + }) + expect(changeHandler).toHaveBeenCalled() + expect(value).toEqual('1') + changeHandler.mockRestore() + }) + + it('should ignore events when disabled', () => { + const changeHandler = jest.fn() + const wrapper = mount( + + Option 1 + Option 2 + + ) + + wrapper.find('input').at(0) + .simulate('change', { + ...nativeEvent, + target: { checked: true }, + }) + expect(changeHandler).not.toHaveBeenCalled() + changeHandler.mockRestore() + }) + + it('should render correctly with inital-value', () => { + const wrapper = mount( + + Option 1 + Option 2 + + ) + const input = wrapper.find('input').at(1).getDOMNode() as HTMLInputElement + expect(input.checked).toEqual(true) + }) + + it('should be warning when value unset', () => { + const errorSpy = jest.spyOn(console, 'error') + .mockImplementation(() => {}) + mount( + + Option 1 + Option 2 + + ) + + expect(errorSpy).toHaveBeenCalled() + errorSpy.mockRestore() + }) + + it('should be warning when checked is set', () => { + const errorSpy = jest.spyOn(console, 'error') + .mockImplementation(() => {}) + mount( + + Option 1 + Option 2 + + ) + + expect(errorSpy).toHaveBeenCalled() + errorSpy.mockRestore() + }) + + it('should set state through value prop', () => { + const wrapper = mount( + + Option 1 + Option 2 + + ) + let input = wrapper.find('input').at(0).getDOMNode() as HTMLInputElement + expect(input.checked).toEqual(false) + + wrapper.setProps({ value: '1' }) + input = wrapper.find('input').at(0).getDOMNode() as HTMLInputElement + expect(input.checked).toEqual(true) + + wrapper.setProps({ value: '2' }) + input = wrapper.find('input').at(1).getDOMNode() as HTMLInputElement + expect(input.checked).toEqual(true) + }) +}) diff --git a/components/radio/__tests__/index.test.tsx b/components/radio/__tests__/index.test.tsx new file mode 100644 index 0000000..2520252 --- /dev/null +++ b/components/radio/__tests__/index.test.tsx @@ -0,0 +1,65 @@ +import React from 'react' +import { mount } from 'enzyme' +import { Radio } from 'components' +import { nativeEvent } from 'tests/utils' + +describe('Radio', () => { + it('should render correctly', () => { + const wrapper = mount(Option) + expect(wrapper.html()).toMatchSnapshot() + expect(() => wrapper.unmount()).not.toThrow() + }) + + it('should render correctly with checked prop', () => { + const wrapper = mount(Option) + wrapper.setProps({ checked: false }) + let input = wrapper.find('input').at(0).getDOMNode() as HTMLInputElement + expect(input.checked).toEqual(false) + + wrapper.setProps({ checked: true }) + input = wrapper.find('input').at(0).getDOMNode() as HTMLInputElement + expect(input.checked).toEqual(true) + }) + + it('should trigger events when use alone', () => { + const changeHandler = jest.fn() + const wrapper = mount(Option) + wrapper.find('input').at(0) + .simulate('change', { + ...nativeEvent, + target: { checked: true }, + }) + expect(changeHandler).toHaveBeenCalled() + changeHandler.mockRestore() + }) + + it('should ignore events when disabled', () => { + const changeHandler = jest.fn() + const wrapper = mount(Option) + wrapper.find('input').at(0) + .simulate('change', { + ...nativeEvent, + target: { checked: true }, + }) + expect(changeHandler).not.toHaveBeenCalled() + changeHandler.mockRestore() + }) + + it('should support react-node in description', () => { + const wrapper = mount( +
+ Option + + Option 1 + Description for Option1 + + + Option 1 + Description for Option1 + +
+ ) + expect(wrapper.html()).toMatchSnapshot() + expect(() => wrapper.unmount()).not.toThrow() + }) +}) From 6b91036aa0284ea53540efd433d1208fe0b933cb Mon Sep 17 00:00:00 2001 From: unix Date: Thu, 23 Apr 2020 11:42:01 +0800 Subject: [PATCH 2/7] fix(radio): fix the initial-value does not work correctly --- components/radio/radio-group.tsx | 3 ++- components/radio/radio.tsx | 21 ++++++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/components/radio/radio-group.tsx b/components/radio/radio-group.tsx index 835eb9a..1278a52 100644 --- a/components/radio/radio-group.tsx +++ b/components/radio/radio-group.tsx @@ -4,7 +4,7 @@ import useTheme from '../styles/use-theme' import { RadioContext } from './radio-context' interface Props { - value: string + value?: string initialValue?: string disabled?: boolean onChange?: (value: string) => void @@ -42,6 +42,7 @@ const RadioGroup: React.FC> = React.mem },[disabled, selfVal]) useEffect(() => { + if (value === undefined) return setSelfVal(value) }, [value]) diff --git a/components/radio/radio.tsx b/components/radio/radio.tsx index 49b895b..88dff18 100644 --- a/components/radio/radio.tsx +++ b/components/radio/radio.tsx @@ -20,10 +20,9 @@ export interface RadioEvent { interface Props { checked?: boolean value?: string - id?: string className?: string disabled?: boolean - onChange: (e: RadioEvent) => void + onChange?: (e: RadioEvent) => void } const defaultProps = { @@ -35,8 +34,8 @@ type NativeAttrs = Omit, keyof Props> export type RadioProps = Props & typeof defaultProps & NativeAttrs const Radio: React.FC> = React.memo(({ - className, id: customId, checked, onChange, disabled, - value: radioValue, children, ...props + className, checked, onChange, disabled, value: radioValue, + children, ...props }) => { const theme = useTheme() const [selfChecked, setSelfChecked] = useState(!!checked) @@ -50,10 +49,11 @@ const Radio: React.FC> = React.memo(({ if (radioValue === undefined) { useWarning('Props "value" must be deinfed if in the Radio.Group.', 'Radio') } - useEffect(() => setSelfChecked(groupValue === radioValue), [groupValue, radioValue]) + useEffect(() => { + setSelfChecked(groupValue === radioValue) + }, [groupValue, radioValue]) } - // const id = useMemo(() => customId || `zeit-ui-radio-${label}`, [customId, label]) const isDisabled = useMemo(() => disabled || disabledAll, [disabled, disabledAll]) const changeHandler = (event: React.ChangeEvent) => { if (isDisabled) return @@ -72,12 +72,15 @@ const Radio: React.FC> = React.memo(({ onChange && onChange(selfEvent) } - useEffect(() => setSelfChecked(!!checked), [checked]) + useEffect(() => { + if (checked === undefined) return + setSelfChecked(!!checked) + }, [checked]) return (
-