Implement client-side registration form validation.

Input forms that need validation will have AJAX requests
performed to get validation decisions live.

All but a few important and common form fields perform
generic validation; these will need a back-end handler
in the future in order to have them validated through AJAX requests.

Information is conveyed on focus and blur for both
errors and successes.
This commit is contained in:
Uman Shahzad
2017-06-27 06:58:04 +05:00
parent 39ac333b5d
commit cb034d4f2f
21 changed files with 1079 additions and 457 deletions

View File

@@ -22,7 +22,9 @@ from notification_prefs import NOTIFICATION_PREF_KEY
from openedx.core.djangoapps.external_auth.models import ExternalAuthMap
from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY
from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin
from openedx.core.djangoapps.user_api.accounts import USERNAME_INVALID_CHARS_ASCII, USERNAME_INVALID_CHARS_UNICODE
from openedx.core.djangoapps.user_api.accounts import (
USERNAME_BAD_LENGTH_MSG, USERNAME_INVALID_CHARS_ASCII, USERNAME_INVALID_CHARS_UNICODE
)
from openedx.core.djangoapps.user_api.preferences.api import get_user_preference
from student.models import UserAttribute
from student.views import REGISTRATION_AFFILIATE_ID, REGISTRATION_UTM_CREATED_AT, REGISTRATION_UTM_PARAMETERS
@@ -476,16 +478,16 @@ class TestCreateAccountValidation(TestCase):
# Missing
del params["username"]
assert_username_error("Username must be minimum of two characters long")
assert_username_error(USERNAME_BAD_LENGTH_MSG)
# Empty, too short
for username in ["", "a"]:
params["username"] = username
assert_username_error("Username must be minimum of two characters long")
assert_username_error(USERNAME_BAD_LENGTH_MSG)
# Too long
params["username"] = "this_username_has_31_characters"
assert_username_error("Username cannot be more than 30 characters long")
assert_username_error(USERNAME_BAD_LENGTH_MSG)
# Invalid
params["username"] = "invalid username"

View File

@@ -5,6 +5,8 @@ import json
from django.core.urlresolvers import reverse
from django.test import TestCase
from openedx.core.djangoapps.user_api.accounts import USERNAME_BAD_LENGTH_MSG
class TestLongUsernameEmail(TestCase):
@@ -34,7 +36,7 @@ class TestLongUsernameEmail(TestCase):
obj = json.loads(response.content)
self.assertEqual(
obj['value'],
"Username cannot be more than 30 characters long",
USERNAME_BAD_LENGTH_MSG,
)
def test_long_email(self):

View File

@@ -21,7 +21,7 @@
var _fn = {
validate: {
template: _.template('<li><%= content %></li>'),
template: _.template('<li id="<%- id %>-validation-error-container"><%- content %></li>'),
msg: {
email: gettext("The email address you've provided isn't formatted correctly."),
@@ -32,6 +32,7 @@
field: function(el) {
var $el = $(el),
id = $el.attr('id'),
required = true,
min = true,
max = true,
@@ -66,6 +67,8 @@
});
}
response.id = id;
return response;
},
@@ -107,7 +110,7 @@
regex: new RegExp(
[
'(^[-!#$%&\'*+/=?^_`{}|~0-9A-Z]+(\\.[-!#$%&\'*+/=?^_`{}|~0-9A-Z]+)*',
'|^"([\\001-\\010\\013\\014\\016-\\037!#-\\[\\]-\\177]|\\\\[\\001-\\011\\013\\014\\016-\\177])*"',
'|^"([\\001-\\010\\013\\014\\016-\\037!#-\\[\\]-\\177]|\\\\[\\001-\\011\\013\\014\\016-\\177])*"', // eslint-disable-line max-len
')@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\\.)+[A-Z]{2,6}\\.?$)',
'|\\[(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\]$'
].join(''), 'i'
@@ -124,7 +127,7 @@
getLabel: function(id) {
// Extract the field label, remove the asterisk (if it appears) and any extra whitespace
return $('label[for=' + id + ']').text().split('*')[0].trim();
return $('label[for=' + id + '] > span.label-text').text().split('*')[0].trim();
},
getMessage: function($el, tests) {
@@ -154,7 +157,10 @@
content = _.sprintf(_fn.validate.msg[key], context);
}
txt.push(_fn.validate.template({content: content}));
txt.push(_fn.validate.template({
content: content,
id: $el.attr('id')
}));
}
});
@@ -173,7 +179,7 @@
return {
validate: _fn.validate.field
};
})();
}());
return utils;
});

View File

@@ -344,10 +344,7 @@ class RegisterFromCombinedPageTest(UniqueCourseTest):
# Verify that the expected errors are displayed.
errors = self.register_page.wait_for_errors()
self.assertIn(u'Please enter your Public Username.', errors)
self.assertIn(
u'You must agree to the édX Terms of Service and Honor Code',
errors
)
self.assertIn(u'You must agree to the édX Terms of Service and Honor Code', errors)
self.assertIn(u'Please select your Country.', errors)
self.assertIn(u'Please tell us your favorite movie.', errors)