This patch fixes following;

*) Empty fields error messages
*) Removes onChange validations

VAN-204
This commit is contained in:
Adeel Khan
2020-12-25 00:01:50 +05:00
parent 605968c903
commit f696587533
6 changed files with 75 additions and 86 deletions

View File

@@ -14,14 +14,13 @@ const RegistrationFailureMessage = (props) => {
Object.keys(errorMessage).forEach((key) => {
const errors = errorMessage[key];
const errorList = errors.map((error) => {
const errorMsg = error.user_message;
return (
const errorList = errors.map((error) => (
(error.user_message) ? (
<li key={error} style={{ textAlign: 'left' }}>
{errorMsg}
{error.user_message}
</li>
);
});
) : null
));
userErrors.push(errorList);
});

View File

@@ -61,6 +61,7 @@ class RegistrationPage extends React.Component {
confirmEmail: '',
enableOptionalField: false,
validationFieldName: '',
emptyFields: {},
errors: {
email: '',
name: '',
@@ -96,8 +97,31 @@ class RegistrationPage extends React.Component {
const { errors } = this.state;
const errorMsg = nextProps.validations.validation_decisions[this.state.validationFieldName];
errors[this.state.validationFieldName] = errorMsg;
this.setState({
errors,
const stateValidKey = `${camelCase(this.state.validationFieldName)}Valid`;
const stateValidValue = !errorMsg;
this.setState(({ [stateValidKey]: stateValidValue }), () => {
const {
emailValid,
nameValid,
usernameValid,
passwordValid,
} = this.state;
const validityMap = REGISTRATION_VALIDITY_MAP;
let extraFieldsValid = true;
Object.entries(validityMap).forEach(([key, value]) => {
if (value) {
const stateValid = `${camelCase(key)}Valid`;
extraFieldsValid = extraFieldsValid && this.state[stateValid];
}
});
const formValid = emailValid && nameValid && usernameValid && passwordValid && extraFieldsValid;
this.setState({
errors,
formValid,
});
});
return false;
}
@@ -112,10 +136,10 @@ class RegistrationPage extends React.Component {
e.preventDefault();
const params = (new URL(document.location)).searchParams;
const payload = {
email: this.state.email,
username: this.state.username,
password: this.state.password,
name: this.state.name,
username: this.state.username,
email: this.state.email,
password: this.state.password,
};
const fieldMap = { ...REGISTRATION_VALIDITY_MAP, ...REGISTRATION_OPTIONAL_MAP };
@@ -133,11 +157,10 @@ class RegistrationPage extends React.Component {
if (courseId) {
payload.course_id = params.course_id;
}
if (!this.state.formValid) {
// Special case where honor code and tos is a single field, true by default. We don't need
// to validate this field
Object.entries(payload).filter(([key]) => (key !== 'honor_code' || !('terms_of_service' in REGISTRATION_EXTRA_FIELDS)))
Object.entries(payload).filter(([key]) => (key !== 'honor_code' || 'terms_of_service' in REGISTRATION_VALIDITY_MAP))
.forEach(([key, value]) => {
this.validateInput(key, value);
});
@@ -167,7 +190,6 @@ class RegistrationPage extends React.Component {
this.setState({
[camelCase(e.target.name)]: targetValue,
});
this.validateInput(e.target.name, targetValue);
}
handleOnOptional(e) {
@@ -180,6 +202,7 @@ class RegistrationPage extends React.Component {
validateInput(inputName, value) {
const { errors } = this.state;
const { emptyFields } = this.state;
let {
emailValid,
nameValid,
@@ -192,24 +215,24 @@ class RegistrationPage extends React.Component {
switch (inputName) {
case 'email':
emailValid = value.match(/^([\w.%+-]+)@([\w-]+\.)+([\w]{2,})$/i);
errors.email = emailValid ? '' : this.intl.formatMessage(messages['logistration.email.validation.message']);
emailValid = value.length >= 1;
emptyFields.email = this.generateUserMessage(emailValid, 'logistration.email.validation.message');
break;
case 'name':
nameValid = value.length >= 1;
errors.name = nameValid ? '' : this.intl.formatMessage(messages['logistration.fullname.validation.message']);
emptyFields.name = this.generateUserMessage(nameValid, 'logistration.fullname.validation.message');
break;
case 'username':
usernameValid = value.length >= 2 && value.length <= 30;
errors.username = usernameValid ? '' : this.intl.formatMessage(messages['logistration.username.validation.message']);
usernameValid = value.length >= 1;
emptyFields.username = this.generateUserMessage(usernameValid, 'logistration.username.validation.message');
break;
case 'password':
passwordValid = !!(value.length >= 8 && value.match(/\d+/g));
errors.password = passwordValid ? '' : this.intl.formatMessage(messages['logistration.register.page.password.validation.message']);
passwordValid = value.length >= 1;
emptyFields.password = this.generateUserMessage(passwordValid, 'logistration.register.page.password.validation.message');
break;
case 'country':
countryValid = value !== '';
errors.country = countryValid ? '' : this.intl.formatMessage(messages['logistration.country.validation.message']);
emptyFields.country = this.generateUserMessage(countryValid, 'logistration.country.validation.message');
break;
case 'honor_code':
honorCodeValid = value !== false;
@@ -224,7 +247,7 @@ class RegistrationPage extends React.Component {
}
this.setState({
errors,
emptyFields,
emailValid,
nameValid,
usernameValid,
@@ -232,32 +255,7 @@ class RegistrationPage extends React.Component {
countryValid,
honorCodeValid,
termsOfServiceValid,
}, this.validateForm);
}
validateForm() {
const {
emailValid,
nameValid,
usernameValid,
passwordValid,
} = this.state;
const validityMap = REGISTRATION_VALIDITY_MAP;
let extraFieldsValid = true;
Object.entries(validityMap).forEach(([key, value]) => {
if (value) {
const stateValid = `${camelCase(key)}Valid`;
extraFieldsValid = extraFieldsValid && this.state[stateValid];
}
});
let formValid = emailValid && nameValid && usernameValid && extraFieldsValid;
if (!this.props.thirdPartyAuthContext.currentProvider) {
formValid = formValid && passwordValid;
}
this.setState({ formValid });
}
addExtraRequiredFields() {
@@ -330,6 +328,7 @@ class RegistrationPage extends React.Component {
label: item.name,
}));
props.options = options;
props.onBlur = e => this.handleOnBlur(e);
}
return (
<ValidationFormGroup
@@ -397,6 +396,22 @@ class RegistrationPage extends React.Component {
return fields;
}
generateUserMessage(isFieldValid, messageID) {
return [{ user_message: isFieldValid ? '' : this.intl.formatMessage(messages[messageID]) }];
}
renderErrors() {
let errorsObject = null;
if (Object.keys(this.state.emptyFields).length > 0) {
errorsObject = this.state.emptyFields;
} else if (this.props.registrationError) {
errorsObject = this.props.registrationError;
} else {
return null;
}
return <RegistrationFailure errors={errorsObject} />;
}
render() {
const { intl, submitState } = this.props;
const {
@@ -426,7 +441,7 @@ class RegistrationPage extends React.Component {
finishAuthUrl={finishAuthUrl}
/>
<div className="register-container mx-auto">
{this.props.registrationError ? <RegistrationFailure errors={this.props.registrationError} /> : null}
{this.renderErrors()}
{currentProvider && (
<ThirdPartyAuthAlert
currentProvider={currentProvider}

View File

@@ -218,3 +218,7 @@ $apple-focus-black: $apple-black;
.opt-year-field{
padding-left: 15px;
}
.invalid-feedback {
color: $red;
}

View File

@@ -128,7 +128,7 @@ const messages = defineMessages({
},
'logistration.email.validation.message': {
id: 'logistration.email.validation.message',
defaultMessage: 'Enter a valid email address that contains at least 3 characters.',
defaultMessage: 'Please enter your Email.',
description: 'Validation message that appears when email address is empty',
},
'logistration.email.help.message': {
@@ -153,7 +153,7 @@ const messages = defineMessages({
},
'logistration.register.page.password.validation.message': {
id: 'logistration.register.page.password.validation.message',
defaultMessage: 'This password is too short. It must contain at least 8 characters. This password must contain at least 1 number.',
defaultMessage: 'Please enter your Password.',
description: 'Validation message that appears when password is non compliant with edX requirement',
},
'logistration.fullname.label': {
@@ -163,7 +163,7 @@ const messages = defineMessages({
},
'logistration.fullname.validation.message': {
id: 'logistration.fullname.validation.message',
defaultMessage: 'Enter your full name.',
defaultMessage: 'Please enter your Full Name.',
description: 'Validation message that appears when fullname is empty',
},
'logistration.username.label': {
@@ -173,7 +173,7 @@ const messages = defineMessages({
},
'logistration.username.validation.message': {
id: 'logistration.username.validation.message',
defaultMessage: 'Username must be between 2 and 30 characters long.',
defaultMessage: 'Please enter your Public Username.',
description: 'Validation message that appears when username is invalid',
},
'logistration.country.validation.message': {

View File

@@ -87,39 +87,6 @@ describe('./RegistrationPage.js', () => {
jest.clearAllMocks();
});
it('should show error message on invalid email', () => {
const validationMessage = 'Enter a valid email address that contains at least 3 characters.';
const registrationPage = mount(reduxWrapper(<IntlRegistrationPage {...props} />));
registrationPage.find('input#email').simulate('change', { target: { value: '', name: 'email' } });
registrationPage.update();
expect(registrationPage.find('#email-invalid-feedback').text()).toEqual(validationMessage);
});
it('should show error message on invalid username', () => {
const validationMessage = 'Username must be between 2 and 30 characters long.';
const registrationPage = mount(reduxWrapper(<IntlRegistrationPage {...props} />));
registrationPage.find('input#username').simulate('change', { target: { value: '', name: 'username' } });
registrationPage.update();
expect(registrationPage.find('#username-invalid-feedback').text()).toEqual(validationMessage);
});
it('should show error message on invalid name', () => {
const validationMessage = 'Enter your full name.';
const registrationPage = mount(reduxWrapper(<IntlRegistrationPage {...props} />));
registrationPage.find('input#name').simulate('change', { target: { value: '', name: 'name' } });
registrationPage.update();
expect(registrationPage.find('#name-invalid-feedback').text()).toEqual(validationMessage);
});
it('should show error message on invalid password', () => {
const validationMessage = 'This password is too short. It must contain at least 8 characters. This password must contain at least 1 number.';
const registrationPage = mount(reduxWrapper(<IntlRegistrationPage {...props} />));
registrationPage.find('input#password').simulate('change', { target: { value: '', name: 'password' } });
registrationPage.update();
expect(registrationPage.find('#password-invalid-feedback').text()).toEqual(validationMessage);
});
it('should show error messages on invalid extra fields', () => {
const validationMessage = {
honorCode: 'You must agree to the Your Platform Name Here Honor Code',

View File

@@ -20,3 +20,7 @@ export default function initializeMockLogging() {
return { loggingService };
}
window.scrollTo = (x, y) => {
document.documentElement.scrollTop = y;
};