diff --git a/src/components/Checkbox/Checkbox.jsx b/src/components/Checkbox/Checkbox.jsx index c9b0a72d0c..5f052413c4 100644 --- a/src/components/Checkbox/Checkbox.jsx +++ b/src/components/Checkbox/Checkbox.jsx @@ -15,7 +15,15 @@ import displayStyles from '../Display.modules.scss' class Checkbox extends React.Component { state = { checked: this.props.checked, - focused: false, + focus: false, + } + + componentWillReceiveProps(nextProps) { + if (this.state.checked !== nextProps.checked) { + this.setState({ + checked: nextProps.checked, + }) + } } onChange = event => { @@ -30,16 +38,28 @@ class Checkbox extends React.Component { } } - onFocus = () => { - this.setState({ focused: true }) + onFocus = event => { + const { onFocus } = this.props + + this.setState({ focus: true }) + + if (onFocus) { + onFocus(event) + } } - onBlur = () => { - this.setState({ focused: false }) + onBlur = event => { + const { onBlur } = this.props + + this.setState({ focus: false }) + + if (onBlur) { + onBlur(event) + } } render() { - const { label, checked, ...rest } = this.props + const { label, ...rest } = this.props const checkboxId = generateId(rest.id, rest.name, label) return ( @@ -48,7 +68,7 @@ class Checkbox extends React.Component { @@ -78,11 +98,15 @@ Checkbox.propTypes = { label: PropTypes.string.isRequired, checked: PropTypes.bool, onChange: PropTypes.func, + onFocus: PropTypes.func, + onBlur: PropTypes.func, } Checkbox.defaultProps = { checked: false, onChange: undefined, + onFocus: undefined, + onBlur: undefined, } export default Checkbox diff --git a/src/components/Checkbox/__tests__/Checkbox.spec.jsx b/src/components/Checkbox/__tests__/Checkbox.spec.jsx index 8268c7e1ee..796e033484 100644 --- a/src/components/Checkbox/__tests__/Checkbox.spec.jsx +++ b/src/components/Checkbox/__tests__/Checkbox.spec.jsx @@ -21,8 +21,8 @@ describe('Checkbox', () => { findFakeCheckbox: () => checkbox.find('[data-testid="fake-checkbox"]'), check: () => findCheckboxElement().simulate('change', { target: { checked: true } }), uncheck: () => findCheckboxElement().simulate('change', { target: { checked: false } }), - focus: () => findCheckboxElement().simulate('focus'), - blur: () => findCheckboxElement().simulate('blur'), + focus: (focusEvent = {}) => findCheckboxElement().simulate('focus', focusEvent), + blur: (blurEvent = {}) => findCheckboxElement().simulate('blur', blurEvent), } } @@ -109,20 +109,28 @@ describe('Checkbox', () => { expect(findFakeCheckbox().find(DecorativeIcon)).toBeEmpty() }) - it('triggers a change handler when checked or unchecked', () => { - const onChangeSpy = jest.fn() - const { check, uncheck } = doMount({ onChange: onChangeSpy }) + it('notifies when it is checked or unchecked', () => { + const onChangeMock = jest.fn() + const { check, uncheck } = doMount({ onChange: onChangeMock }) check() - expect(onChangeSpy).toHaveBeenCalledWith( + expect(onChangeMock).toHaveBeenCalledWith( expect.objectContaining({ target: { checked: true } }) ) uncheck() - expect(onChangeSpy).toHaveBeenCalledWith( + expect(onChangeMock).toHaveBeenCalledWith( expect.objectContaining({ target: { checked: false } }) ) }) + + it('can receive a new value from a parent component', () => { + const { checkbox, findCheckboxElement } = doMount({ checked: false }) + + checkbox.setProps({ checked: true }) + + expect(findCheckboxElement()).toHaveProp('checked', true) + }) }) describe('focusing', () => { @@ -136,6 +144,26 @@ describe('Checkbox', () => { expect(findFakeCheckbox()).not.toHaveClassName('focused') expect(findFakeCheckbox()).toHaveClassName('unchecked') }) + + it('will notify when focus is gained', () => { + const onFocusMock = jest.fn() + const event = { target: { value: 'the value' } } + + const { focus } = doMount({ onFocus: onFocusMock }) + focus(event) + + expect(onFocusMock).toHaveBeenCalledWith(expect.objectContaining(event)) + }) + + it('will notify when focus is lost', () => { + const onBlurMock = jest.fn() + const event = { target: { value: 'the value' } } + + const { blur } = doMount({ onBlur: onBlurMock }) + blur(event) + + expect(onBlurMock).toHaveBeenCalledWith(expect.objectContaining(event)) + }) }) // diff --git a/src/components/FormField/FormField.jsx b/src/components/FormField/FormField.jsx index a68f177c3d..e0913c856f 100644 --- a/src/components/FormField/FormField.jsx +++ b/src/components/FormField/FormField.jsx @@ -69,13 +69,9 @@ const renderHelper = (helper, helperId, feedback, value) => { } class FormField extends React.Component { - constructor(props) { - super(props) - - this.state = { - value: props.value, - focus: false, - } + state = { + value: this.props.value, + focus: false, } componentWillReceiveProps(nextProps) {