diff --git a/src/logistration/RegistrationFailure.jsx b/src/logistration/RegistrationFailure.jsx
index c346bcd2..6778309b 100644
--- a/src/logistration/RegistrationFailure.jsx
+++ b/src/logistration/RegistrationFailure.jsx
@@ -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) ? (
- {errorMsg}
+ {error.user_message}
- );
- });
+ ) : null
+ ));
userErrors.push(errorList);
});
diff --git a/src/logistration/RegistrationPage.jsx b/src/logistration/RegistrationPage.jsx
index 6b651d92..3cc472e7 100644
--- a/src/logistration/RegistrationPage.jsx
+++ b/src/logistration/RegistrationPage.jsx
@@ -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 (
0) {
+ errorsObject = this.state.emptyFields;
+ } else if (this.props.registrationError) {
+ errorsObject = this.props.registrationError;
+ } else {
+ return null;
+ }
+ return ;
+ }
+
render() {
const { intl, submitState } = this.props;
const {
@@ -426,7 +441,7 @@ class RegistrationPage extends React.Component {
finishAuthUrl={finishAuthUrl}
/>
- {this.props.registrationError ? : null}
+ {this.renderErrors()}
{currentProvider && (
{
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());
- 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());
- 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());
- 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());
- 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',
diff --git a/src/setupTest.js b/src/setupTest.js
index 156b68d6..dd28bfd5 100755
--- a/src/setupTest.js
+++ b/src/setupTest.js
@@ -20,3 +20,7 @@ export default function initializeMockLogging() {
return { loggingService };
}
+
+window.scrollTo = (x, y) => {
+ document.documentElement.scrollTop = y;
+};