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..6bdf6e8
--- /dev/null
+++ b/components/radio/__tests__/__snapshots__/group.test.tsx.snap
@@ -0,0 +1,265 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Radio Group 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..b4045e5
--- /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 Group', () => {
+ 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()
+ })
+})
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 (
-