This patch fixes following;
*) Empty fields error messages *) Removes onChange validations VAN-204
This commit is contained in:
@@ -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);
|
||||
});
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -218,3 +218,7 @@ $apple-focus-black: $apple-black;
|
||||
.opt-year-field{
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.invalid-feedback {
|
||||
color: $red;
|
||||
}
|
||||
|
||||
@@ -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': {
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -20,3 +20,7 @@ export default function initializeMockLogging() {
|
||||
|
||||
return { loggingService };
|
||||
}
|
||||
|
||||
window.scrollTo = (x, y) => {
|
||||
document.documentElement.scrollTop = y;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user