From ac2201a648d376f19b62dbd09343fb1cbc6d6651 Mon Sep 17 00:00:00 2001 From: Will Daly Date: Fri, 24 Oct 2014 11:01:31 -0400 Subject: [PATCH] Add field from server to set custom error messages for logistration fields --- common/djangoapps/user_api/helpers.py | 15 ++- .../djangoapps/user_api/tests/test_helpers.py | 6 ++ .../djangoapps/user_api/tests/test_views.py | 98 +++++++------------ common/djangoapps/user_api/views.py | 39 +++++--- 4 files changed, 78 insertions(+), 80 deletions(-) diff --git a/common/djangoapps/user_api/helpers.py b/common/djangoapps/user_api/helpers.py index 0c659dc623..c36b6359b3 100644 --- a/common/djangoapps/user_api/helpers.py +++ b/common/djangoapps/user_api/helpers.py @@ -125,7 +125,7 @@ class FormDescription(object): def add_field( self, name, label=u"", field_type=u"text", default=u"", placeholder=u"", instructions=u"", required=True, restrictions=None, - options=None + options=None, error_messages=None ): """Add a field to the form description. @@ -158,6 +158,11 @@ class FormDescription(object): and `display_name` is the name to display to the user. If the field type is "select", you *must* provide this kwarg. + error_messages (dict): Custom validation error messages. + Currently, the only supported key is "required" indicating + that the messages should be displayed if the user does + not provide a value for a required field. + Raises: InvalidFieldError @@ -177,7 +182,8 @@ class FormDescription(object): "placeholder": placeholder, "instructions": instructions, "required": required, - "restrictions": {} + "restrictions": {}, + "errorMessages": {}, } if field_type == "select": @@ -201,6 +207,9 @@ class FormDescription(object): ) raise InvalidFieldError(msg) + if error_messages is not None: + field_dict["errorMessages"] = error_messages + # If there are overrides for this field, apply them now. # Any field property can be overwritten (for example, the default value or placeholder) field_dict.update(self._field_overrides.get(name, {})) @@ -228,6 +237,7 @@ class FormDescription(object): {"value": "wine", "name": "Wine"} ] "restrictions": {}, + "errorMessages": {}, }, { "name": "comments", @@ -240,6 +250,7 @@ class FormDescription(object): "restrictions": { "max_length": 200 } + "errorMessages": {}, }, ... ] diff --git a/common/djangoapps/user_api/tests/test_helpers.py b/common/djangoapps/user_api/tests/test_helpers.py index e66cf777ca..2968735668 100644 --- a/common/djangoapps/user_api/tests/test_helpers.py +++ b/common/djangoapps/user_api/tests/test_helpers.py @@ -87,6 +87,9 @@ class FormDescriptionTest(TestCase): restrictions={ "min_length": 2, "max_length": 10 + }, + error_messages={ + "required": "You must provide a value!" } ) @@ -105,6 +108,9 @@ class FormDescriptionTest(TestCase): "restrictions": { "min_length": 2, "max_length": 10, + }, + "errorMessages": { + "required": "You must provide a value!" } } ] diff --git a/common/djangoapps/user_api/tests/test_views.py b/common/djangoapps/user_api/tests/test_views.py index 4ffe53c579..721261fac4 100644 --- a/common/djangoapps/user_api/tests/test_views.py +++ b/common/djangoapps/user_api/tests/test_views.py @@ -609,6 +609,7 @@ class LoginSessionViewTest(ApiTestCase): "min_length": 3, "max_length": 254 }, + "errorMessages": {}, }, { "name": "password", @@ -622,6 +623,7 @@ class LoginSessionViewTest(ApiTestCase): "min_length": 2, "max_length": 75 }, + "errorMessages": {}, }, { "name": "remember", @@ -632,6 +634,7 @@ class LoginSessionViewTest(ApiTestCase): "placeholder": "", "instructions": "", "restrictions": {}, + "errorMessages": {}, } ]) @@ -762,7 +765,6 @@ class RegistrationViewTest(ApiTestCase): no_extra_fields_setting, { u"name": u"email", - u"defaultValue": u"", u"type": u"email", u"required": True, u"label": u"E-mail", @@ -779,15 +781,13 @@ class RegistrationViewTest(ApiTestCase): no_extra_fields_setting, { u"name": u"name", - u"defaultValue": u"", u"type": u"text", u"required": True, u"label": u"Full Name", - u"placeholder": u"", u"instructions": u"Needed for any certificates you may earn", u"restrictions": { "max_length": 255, - } + }, } ) @@ -795,16 +795,14 @@ class RegistrationViewTest(ApiTestCase): no_extra_fields_setting, { u"name": u"username", - u"defaultValue": u"", u"type": u"text", u"required": True, u"label": u"Public Username", - u"placeholder": u"", u"instructions": u"Will be shown in any discussions or forums you participate in (cannot be changed)", u"restrictions": { u"min_length": 2, u"max_length": 30, - } + }, } ) @@ -812,12 +810,9 @@ class RegistrationViewTest(ApiTestCase): no_extra_fields_setting, { u"name": u"password", - u"defaultValue": u"", u"type": u"text", u"required": True, u"label": u"Password", - u"placeholder": u"", - u"instructions": u"", u"restrictions": { u"min_length": 2, u"max_length": 75 @@ -838,13 +833,8 @@ class RegistrationViewTest(ApiTestCase): no_extra_fields_setting, { "name": "password", - "defaultValue": "", "type": "hidden", "required": False, - "label": "", - "placeholder": "", - "instructions": "", - "restrictions": {}, } ) @@ -875,7 +865,6 @@ class RegistrationViewTest(ApiTestCase): u"type": u"text", u"required": True, u"label": u"Full Name", - u"placeholder": u"", u"instructions": u"Needed for any certificates you may earn", u"restrictions": { "max_length": 255, @@ -906,12 +895,9 @@ class RegistrationViewTest(ApiTestCase): {"level_of_education": "optional"}, { "name": "level_of_education", - "defaultValue": "", "type": "select", "required": False, "label": "Highest Level of Education Completed", - "placeholder": "", - "instructions": "", "options": [ {"value": "", "name": "--"}, {"value": "p", "name": "Doctorate"}, @@ -924,7 +910,6 @@ class RegistrationViewTest(ApiTestCase): {"value": "none", "name": "None"}, {"value": "other", "name": "Other"}, ], - "restrictions": {}, } ) @@ -933,19 +918,15 @@ class RegistrationViewTest(ApiTestCase): {"gender": "optional"}, { "name": "gender", - "defaultValue": "", "type": "select", "required": False, "label": "Gender", - "placeholder": "", - "instructions": "", "options": [ {"value": "", "name": "--"}, {"value": "m", "name": "Male"}, {"value": "f", "name": "Female"}, {"value": "o", "name": "Other"}, ], - "restrictions": {}, } ) @@ -961,14 +942,10 @@ class RegistrationViewTest(ApiTestCase): {"year_of_birth": "optional"}, { "name": "year_of_birth", - "defaultValue": "", "type": "select", "required": False, "label": "Year of Birth", - "placeholder": "", - "instructions": "", "options": year_options, - "restrictions": {}, } ) @@ -977,13 +954,9 @@ class RegistrationViewTest(ApiTestCase): {"mailing_address": "optional"}, { "name": "mailing_address", - "defaultValue": "", "type": "textarea", "required": False, "label": "Mailing Address", - "placeholder": "", - "instructions": "", - "restrictions": {}, } ) @@ -992,13 +965,9 @@ class RegistrationViewTest(ApiTestCase): {"goals": "optional"}, { "name": "goals", - "defaultValue": "", "type": "textarea", "required": False, "label": "Please share with us your reasons for registering with edX", - "placeholder": "", - "instructions": "", - "restrictions": {}, } ) @@ -1007,13 +976,9 @@ class RegistrationViewTest(ApiTestCase): {"city": "optional"}, { "name": "city", - "defaultValue": "", "type": "text", "required": False, "label": "City", - "placeholder": "", - "instructions": "", - "restrictions": {}, } ) @@ -1030,13 +995,9 @@ class RegistrationViewTest(ApiTestCase): { "label": "Country", "name": "country", - "defaultValue": "", "type": "select", "required": True, - "placeholder": "", - "instructions": "", "options": country_options, - "restrictions": {}, } ) @@ -1053,9 +1014,9 @@ class RegistrationViewTest(ApiTestCase): "defaultValue": False, "type": "checkbox", "required": True, - "placeholder": "", - "instructions": "", - "restrictions": {}, + "errorMessages": { + "required": "You must agree to the Terms of Service and Honor Code" + } } ) @@ -1070,9 +1031,9 @@ class RegistrationViewTest(ApiTestCase): "defaultValue": False, "type": "checkbox", "required": True, - "placeholder": "", - "instructions": "", - "restrictions": {}, + "errorMessages": { + "required": "You must agree to the Terms of Service and Honor Code" + } } ) @@ -1093,9 +1054,9 @@ class RegistrationViewTest(ApiTestCase): "defaultValue": False, "type": "checkbox", "required": True, - "placeholder": "", - "instructions": "", - "restrictions": {}, + "errorMessages": { + "required": "You must agree to the Honor Code" + } } ) @@ -1108,9 +1069,9 @@ class RegistrationViewTest(ApiTestCase): "defaultValue": False, "type": "checkbox", "required": True, - "placeholder": "", - "instructions": "", - "restrictions": {}, + "errorMessages": { + "required": "You must agree to the Terms of Service" + } } ) @@ -1127,9 +1088,9 @@ class RegistrationViewTest(ApiTestCase): "defaultValue": False, "type": "checkbox", "required": True, - "placeholder": "", - "instructions": "", - "restrictions": {}, + "errorMessages": { + "required": "You must agree to the Honor Code" + } } ) @@ -1142,9 +1103,9 @@ class RegistrationViewTest(ApiTestCase): "defaultValue": False, "type": "checkbox", "required": True, - "placeholder": "", - "instructions": "", - "restrictions": {}, + "errorMessages": { + "required": "You must agree to the Terms of Service" + } } ) @@ -1384,6 +1345,19 @@ class RegistrationViewTest(ApiTestCase): AssertionError """ + # Add in fields that are always present + defaults = [ + ("label", ""), + ("instructions", ""), + ("placeholder", ""), + ("defaultValue", ""), + ("restrictions", {}), + ("errorMessages", {}), + ] + for key, value in defaults: + if key not in expected_field: + expected_field[key] = value + # Retrieve the registration form description with override_settings(REGISTRATION_EXTRA_FIELDS=extra_fields_setting): response = self.client.get(self.url) diff --git a/common/djangoapps/user_api/views.py b/common/djangoapps/user_api/views.py index 6cda635a2b..18d78374ec 100644 --- a/common/djangoapps/user_api/views.py +++ b/common/djangoapps/user_api/views.py @@ -377,37 +377,41 @@ class RegistrationView(APIView): # Translators: This is a legal document users must agree to in order to register a new account. terms_text = _(u"Terms of Service and Honor Code") - # Translators: "Terms of service" is a legal document users must agree to in order to register a new account. - label = _( - u"I agree to the {terms_of_service}" - ).format( - terms_of_service=u"{terms_text}".format( - url=marketing_link("HONOR"), - terms_text=terms_text - ) + terms_link = u"{terms_text}".format( + url=marketing_link("HONOR"), + terms_text=terms_text ) + # Translators: "Terms of service" is a legal document users must agree to in order to register a new account. + label = _(u"I agree to the {terms_of_service}").format(terms_of_service=terms_link) + + # Translators: "Terms of service" is a legal document users must agree to in order to register a new account. + error_msg = _(u"You must agree to the {terms_of_service}").format(terms_of_service=terms_link) + form_desc.add_field( "honor_code", label=label, field_type="checkbox", default=False, required=required, + error_messages={ + "required": error_msg + } ) def _add_terms_of_service_field(self, form_desc, required=True): # Translators: This is a legal document users must agree to in order to register a new account. terms_text = _(u"Terms of Service") + terms_link = u"{terms_text}".format( + url=marketing_link("TOS"), + terms_text=terms_text + ) # Translators: "Terms of service" is a legal document users must agree to in order to register a new account. - label = _( - u"I agree to the {terms_of_service}" - ).format( - terms_of_service=u"{terms_text}".format( - url=marketing_link("TOS"), - terms_text=terms_text - ) - ) + label = _(u"I agree to the {terms_of_service}").format(terms_of_service=terms_link) + + # Translators: "Terms of service" is a legal document users must agree to in order to register a new account. + error_msg = _("You must agree to the {terms_of_service}").format(terms_of_service=terms_link) form_desc.add_field( "terms_of_service", @@ -415,6 +419,9 @@ class RegistrationView(APIView): field_type="checkbox", default=False, required=required, + error_messages={ + "required": error_msg + } ) def _options_with_default(self, options):