From a395042548cbc66c81ae43269414afb040df8f3f Mon Sep 17 00:00:00 2001 From: Peter Kulko <93188219+PKulkoRaccoonGang@users.noreply.github.com> Date: Fri, 13 Oct 2023 11:01:50 +0300 Subject: [PATCH] fix: avoid duplicate onChange calls in FormRadioSet and FormCheckboxSet (#2705) * fix: fixed duplicate calls in FormRadioSet and FormCheckboxSet * refactor: added new tests * refactor: refactoring after review --- src/Form/FormCheckbox.jsx | 20 ++++--- src/Form/FormRadio.jsx | 63 +++++++++++------------ src/Form/tests/FormCheckboxSet.test.jsx | 19 +++++++ src/Form/tests/FormRadioSet.test.jsx | 19 +++++++ src/Menu/__snapshots__/Menu.test.jsx.snap | 1 + 5 files changed, 82 insertions(+), 40 deletions(-) diff --git a/src/Form/FormCheckbox.jsx b/src/Form/FormCheckbox.jsx index 9a9b736b89..d2e1951ba5 100644 --- a/src/Form/FormCheckbox.jsx +++ b/src/Form/FormCheckbox.jsx @@ -62,7 +62,7 @@ const FormCheckbox = React.forwardRef(({ floatLabelLeft, ...props }, ref) => { - const { getCheckboxControlProps, hasCheckboxSetProvider } = useCheckboxSetContext(); + const { hasCheckboxSetProvider } = useCheckboxSetContext(); const { hasFormGroupProvider, useSetIsControlGroupEffect, getControlProps } = useFormGroupContext(); useSetIsControlGroupEffect(true); const shouldActAsGroup = hasFormGroupProvider && !hasCheckboxSetProvider; @@ -70,14 +70,11 @@ const FormCheckbox = React.forwardRef(({ ...getControlProps({}), role: 'group', } : {}; - const checkboxInputProps = getCheckboxControlProps({ - ...props, - className: controlClassName, - }); - const control = React.createElement(controlAs, { ...checkboxInputProps, ref }); + + const control = React.createElement(controlAs, { ...props, className: controlClassName, ref }); return ( @@ -85,7 +82,7 @@ const FormCheckbox = React.forwardRef(({ className={classNames('pgn__form-checkbox', className, { 'pgn__form-control-valid': isValid, 'pgn__form-control-invalid': isInvalid, - 'pgn__form-control-disabled': checkboxInputProps.disabled, + 'pgn__form-control-disabled': props.disabled, 'pgn__form-control-label-left': !!floatLabelLeft, })} {...groupProps} @@ -107,6 +104,8 @@ const FormCheckbox = React.forwardRef(({ }); FormCheckbox.propTypes = { + /** Specifies id of the FormCheckbox component. */ + id: PropTypes.string, /** Specifies contents of the component. */ children: PropTypes.node.isRequired, /** Specifies class name to append to the base element. */ @@ -123,10 +122,14 @@ FormCheckbox.propTypes = { isValid: PropTypes.bool, /** Specifies control element. */ controlAs: PropTypes.elementType, + /** Specifies whether the floating label should be aligned to the left. */ floatLabelLeft: PropTypes.bool, + /** Specifies whether the `FormCheckbox` is disabled. */ + disabled: PropTypes.bool, }; FormCheckbox.defaultProps = { + id: undefined, className: undefined, controlClassName: undefined, labelClassName: undefined, @@ -135,6 +138,7 @@ FormCheckbox.defaultProps = { isValid: false, controlAs: CheckboxControl, floatLabelLeft: false, + disabled: false, }; export { CheckboxControl }; diff --git a/src/Form/FormRadio.jsx b/src/Form/FormRadio.jsx index 9840f6ab53..4021e408d5 100644 --- a/src/Form/FormRadio.jsx +++ b/src/Form/FormRadio.jsx @@ -40,42 +40,37 @@ const FormRadio = React.forwardRef(({ isInvalid, isValid, ...props -}, ref) => { - const { getRadioControlProps } = useRadioSetContext(); - const radioInputProps = getRadioControlProps({ - ...props, - className: controlClassName, - }); - return ( - ( + +
-
- -
- - {children} - - {description && ( - - {description} - - )} -
+ +
+ + {children} + + {description && ( + + {description} + + )}
- - ); -}); +
+ +)); FormRadio.propTypes = { + /** Specifies id of the FormRadio component. */ + id: PropTypes.string, /** Specifies contents of the component. */ children: PropTypes.node.isRequired, /** Specifies class name to append to the base element. */ @@ -90,15 +85,19 @@ FormRadio.propTypes = { isInvalid: PropTypes.bool, /** Specifies whether to display component in valid state, this affects styling. */ isValid: PropTypes.bool, + /** Specifies whether the `FormRadio` is disabled. */ + disabled: PropTypes.bool, }; FormRadio.defaultProps = { + id: undefined, className: undefined, controlClassName: undefined, labelClassName: undefined, description: undefined, isInvalid: false, isValid: false, + disabled: false, }; export { RadioControl }; diff --git a/src/Form/tests/FormCheckboxSet.test.jsx b/src/Form/tests/FormCheckboxSet.test.jsx index be5c0a9082..393364f6e3 100644 --- a/src/Form/tests/FormCheckboxSet.test.jsx +++ b/src/Form/tests/FormCheckboxSet.test.jsx @@ -165,4 +165,23 @@ describe('FormCheckboxSet', () => { expect(checkboxNode.defaultChecked).toBe(true); }); }); + + it('checks if onClick is called once in FormCheckboxSet', () => { + const handleChange = jest.fn(); + const { getByLabelText } = render( + + Which color? + + Red + Green + + , + ); + + userEvent.click(getByLabelText('Red')); + expect(handleChange).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/Form/tests/FormRadioSet.test.jsx b/src/Form/tests/FormRadioSet.test.jsx index 4d5a5d0a66..23cf96dd23 100644 --- a/src/Form/tests/FormRadioSet.test.jsx +++ b/src/Form/tests/FormRadioSet.test.jsx @@ -108,4 +108,23 @@ describe('FormRadioSet', () => { expect(evergreenRadio).toHaveAttribute('name', 'trees'); expect(deciduousRadio).toHaveAttribute('name', 'trees'); }); + + it('checks if onClick is called once in FormRadioSet', () => { + const handleChange = jest.fn(); + const { getByLabelText } = render( + + Which color? + + Red + Green + + , + ); + + userEvent.click(getByLabelText('Red')); + expect(handleChange).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/Menu/__snapshots__/Menu.test.jsx.snap b/src/Menu/__snapshots__/Menu.test.jsx.snap index ced5b21403..75f4f1b1cf 100644 --- a/src/Menu/__snapshots__/Menu.test.jsx.snap +++ b/src/Menu/__snapshots__/Menu.test.jsx.snap @@ -126,6 +126,7 @@ exports[`Menu Item renders correctly renders as expected with menu items 1`] = ` >