diff --git a/src/common-components/AuthnValidationFormGroup.jsx b/src/common-components/AuthnValidationFormGroup.jsx index 34e46f1a..cc52478c 100644 --- a/src/common-components/AuthnValidationFormGroup.jsx +++ b/src/common-components/AuthnValidationFormGroup.jsx @@ -7,7 +7,9 @@ import { } from '@edx/paragon'; const AuthnCustomValidationFormGroup = (props) => { - const { onClick, onChange, onBlur } = props; + const { + onBlur, onChange, onClick, onFocus, + } = props; const [showHelpText, setShowHelpText] = useState(false); const [showLabelText, setShowLabelText] = useState(false); @@ -31,6 +33,11 @@ const AuthnCustomValidationFormGroup = (props) => { changeCb(e); } }; + const onFocusHandler = (e, focusCb) => { + if (focusCb) { + focusCb(e); + } + }; const onOptionalHandler = (e, clickCb) => { clickCb(e); }; const showLabel = () => { @@ -68,7 +75,7 @@ const AuthnCustomValidationFormGroup = (props) => { inputProps.onChange = (e) => onChangeHandler(e, onChange); inputProps.onClick = (e) => onClickHandler(e, onClick); inputProps.onBlur = (e) => onBlurHandler(e, onBlur); - inputProps.onFocus = (e) => onClickHandler(e, null); + inputProps.onFocus = (e) => onFocusHandler(e, onFocus); if (props.type === 'select') { inputProps.options = props.selectOptions; @@ -122,6 +129,7 @@ AuthnCustomValidationFormGroup.defaultProps = { onClick: null, onBlur: null, onChange: null, + onFocus: null, isChecked: false, checkboxMessage: '', selectOptions: null, @@ -147,6 +155,7 @@ AuthnCustomValidationFormGroup.propTypes = { onClick: PropTypes.func, onBlur: PropTypes.func, onChange: PropTypes.func, + onFocus: PropTypes.func, checkboxMessage: PropTypes.string, selectOptions: PropTypes.arrayOf(PropTypes.shape({ key: PropTypes.string, diff --git a/src/common-components/tests/AuthnValidationFormGroup.test.jsx b/src/common-components/tests/AuthnValidationFormGroup.test.jsx index 88f3dfbf..e7e77895 100644 --- a/src/common-components/tests/AuthnValidationFormGroup.test.jsx +++ b/src/common-components/tests/AuthnValidationFormGroup.test.jsx @@ -22,7 +22,7 @@ describe('AuthnCustomValidationFormGroup', () => { const validationFormGroup = mount(); validationFormGroup.find('input').simulate('focus'); - expect(validationFormGroup.find('label').prop('className')).toEqual('pt-10 h6 form-label'); + expect(validationFormGroup.find('label').prop('className')).toEqual('pt-10 focus-out form-label'); }); it('should keep label hidden for checkbox field', () => { diff --git a/src/register/RegistrationPage.jsx b/src/register/RegistrationPage.jsx index 2834c789..aac16d3a 100644 --- a/src/register/RegistrationPage.jsx +++ b/src/register/RegistrationPage.jsx @@ -235,6 +235,12 @@ class RegistrationPage extends React.Component { } } + handleOnFocus(e) { + const { errors } = this.state; + errors[e.target.name] = ''; + this.setState({ errors }); + } + handleOnOptional(e) { const optionalEnable = this.state.enableOptionalField; const targetValue = e.target.id === 'additionalFields' ? !optionalEnable : e.target.checked; @@ -479,6 +485,7 @@ class RegistrationPage extends React.Component { value={this.state.name} onBlur={(e) => this.handleOnBlur(e)} onChange={(e) => this.handleOnChange(e)} + onFocus={(e) => this.handleOnFocus(e)} helpText={intl.formatMessage(messages['helptext.name'])} inputFieldStyle="border-gray-600" /> @@ -494,6 +501,7 @@ class RegistrationPage extends React.Component { value={this.state.username} onBlur={(e) => this.handleOnBlur(e)} onChange={(e) => this.handleOnChange(e)} + onFocus={(e) => this.handleOnFocus(e)} helpText={intl.formatMessage(messages['helptext.username'])} inputFieldStyle="border-gray-600" /> @@ -509,6 +517,7 @@ class RegistrationPage extends React.Component { value={this.state.email} onBlur={(e) => this.handleOnBlur(e)} onChange={(e) => this.handleOnChange(e)} + onFocus={(e) => this.handleOnFocus(e)} helpText={intl.formatMessage(messages['helptext.email'])} inputFieldStyle="border-gray-600" /> @@ -524,6 +533,7 @@ class RegistrationPage extends React.Component { value={this.state.password} onBlur={(e) => this.handleOnBlur(e)} onChange={(e) => this.handleOnChange(e)} + onFocus={(e) => this.handleOnFocus(e)} helpText={intl.formatMessage(messages['helptext.password'])} inputFieldStyle="border-gray-600" /> @@ -541,6 +551,7 @@ class RegistrationPage extends React.Component { value={this.state.country} onBlur={(e) => this.handleOnBlur(e)} onChange={(e) => this.handleOnChange(e)} + onFocus={(e) => this.handleOnFocus(e)} selectOptions={this.getCountryOptions()} inputFieldStyle="border-gray-600 custom-select-size" /> diff --git a/src/register/tests/RegistrationPage.test.jsx b/src/register/tests/RegistrationPage.test.jsx index cf0c5307..d6961d6f 100644 --- a/src/register/tests/RegistrationPage.test.jsx +++ b/src/register/tests/RegistrationPage.test.jsx @@ -309,6 +309,29 @@ describe('RegistrationPageTests', () => { expect(registrationPage.find('#validation-errors').first().text()).toEqual(alertBanner); }); + it('should clear field related error messages on input field Focus', () => { + const errors = { + email: '', + name: '', + username: '', + password: '', + country: '', + }; + const registrationPage = mount(reduxWrapper()); + registrationPage.find('button.btn-brand').simulate('click'); + + expect(registrationPage.find('#name-invalid-feedback').text()).toEqual(emptyFieldValidation.name); + registrationPage.find('input#name').simulate('focus'); + expect(registrationPage.find('#username-invalid-feedback').text()).toEqual(emptyFieldValidation.username); + registrationPage.find('input#username').simulate('focus'); + expect(registrationPage.find('#email-invalid-feedback').text()).toEqual(emptyFieldValidation.email); + registrationPage.find('input#email').simulate('focus'); + expect(registrationPage.find('#password-invalid-feedback').text()).toEqual(emptyFieldValidation.password); + registrationPage.find('input#password').simulate('focus'); + registrationPage.find('select#country').simulate('focus', { target: { value: 'US', name: 'country' } }); + expect(registrationPage.find('RegistrationPage').state('errors')).toEqual(errors); + }); + it('should show error message on alert and below the fields in case of 409', () => { const errors = { email: 'It looks like test@gmail.com belongs to an existing account. Try again with a different email address.',