Commit ac2201a6 by Will Daly

Add field from server to set custom error messages for logistration fields

parent 56d55608
...@@ -125,7 +125,7 @@ class FormDescription(object): ...@@ -125,7 +125,7 @@ class FormDescription(object):
def add_field( def add_field(
self, name, label=u"", field_type=u"text", default=u"", self, name, label=u"", field_type=u"text", default=u"",
placeholder=u"", instructions=u"", required=True, restrictions=None, placeholder=u"", instructions=u"", required=True, restrictions=None,
options=None options=None, error_messages=None
): ):
"""Add a field to the form description. """Add a field to the form description.
...@@ -158,6 +158,11 @@ class FormDescription(object): ...@@ -158,6 +158,11 @@ class FormDescription(object):
and `display_name` is the name to display to the user. and `display_name` is the name to display to the user.
If the field type is "select", you *must* provide this kwarg. 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: Raises:
InvalidFieldError InvalidFieldError
...@@ -177,7 +182,8 @@ class FormDescription(object): ...@@ -177,7 +182,8 @@ class FormDescription(object):
"placeholder": placeholder, "placeholder": placeholder,
"instructions": instructions, "instructions": instructions,
"required": required, "required": required,
"restrictions": {} "restrictions": {},
"errorMessages": {},
} }
if field_type == "select": if field_type == "select":
...@@ -201,6 +207,9 @@ class FormDescription(object): ...@@ -201,6 +207,9 @@ class FormDescription(object):
) )
raise InvalidFieldError(msg) raise InvalidFieldError(msg)
if error_messages is not None:
field_dict["errorMessages"] = error_messages
# If there are overrides for this field, apply them now. # If there are overrides for this field, apply them now.
# Any field property can be overwritten (for example, the default value or placeholder) # Any field property can be overwritten (for example, the default value or placeholder)
field_dict.update(self._field_overrides.get(name, {})) field_dict.update(self._field_overrides.get(name, {}))
...@@ -228,6 +237,7 @@ class FormDescription(object): ...@@ -228,6 +237,7 @@ class FormDescription(object):
{"value": "wine", "name": "Wine"} {"value": "wine", "name": "Wine"}
] ]
"restrictions": {}, "restrictions": {},
"errorMessages": {},
}, },
{ {
"name": "comments", "name": "comments",
...@@ -240,6 +250,7 @@ class FormDescription(object): ...@@ -240,6 +250,7 @@ class FormDescription(object):
"restrictions": { "restrictions": {
"max_length": 200 "max_length": 200
} }
"errorMessages": {},
}, },
... ...
] ]
......
...@@ -87,6 +87,9 @@ class FormDescriptionTest(TestCase): ...@@ -87,6 +87,9 @@ class FormDescriptionTest(TestCase):
restrictions={ restrictions={
"min_length": 2, "min_length": 2,
"max_length": 10 "max_length": 10
},
error_messages={
"required": "You must provide a value!"
} }
) )
...@@ -105,6 +108,9 @@ class FormDescriptionTest(TestCase): ...@@ -105,6 +108,9 @@ class FormDescriptionTest(TestCase):
"restrictions": { "restrictions": {
"min_length": 2, "min_length": 2,
"max_length": 10, "max_length": 10,
},
"errorMessages": {
"required": "You must provide a value!"
} }
} }
] ]
......
...@@ -609,6 +609,7 @@ class LoginSessionViewTest(ApiTestCase): ...@@ -609,6 +609,7 @@ class LoginSessionViewTest(ApiTestCase):
"min_length": 3, "min_length": 3,
"max_length": 254 "max_length": 254
}, },
"errorMessages": {},
}, },
{ {
"name": "password", "name": "password",
...@@ -622,6 +623,7 @@ class LoginSessionViewTest(ApiTestCase): ...@@ -622,6 +623,7 @@ class LoginSessionViewTest(ApiTestCase):
"min_length": 2, "min_length": 2,
"max_length": 75 "max_length": 75
}, },
"errorMessages": {},
}, },
{ {
"name": "remember", "name": "remember",
...@@ -632,6 +634,7 @@ class LoginSessionViewTest(ApiTestCase): ...@@ -632,6 +634,7 @@ class LoginSessionViewTest(ApiTestCase):
"placeholder": "", "placeholder": "",
"instructions": "", "instructions": "",
"restrictions": {}, "restrictions": {},
"errorMessages": {},
} }
]) ])
...@@ -762,7 +765,6 @@ class RegistrationViewTest(ApiTestCase): ...@@ -762,7 +765,6 @@ class RegistrationViewTest(ApiTestCase):
no_extra_fields_setting, no_extra_fields_setting,
{ {
u"name": u"email", u"name": u"email",
u"defaultValue": u"",
u"type": u"email", u"type": u"email",
u"required": True, u"required": True,
u"label": u"E-mail", u"label": u"E-mail",
...@@ -779,15 +781,13 @@ class RegistrationViewTest(ApiTestCase): ...@@ -779,15 +781,13 @@ class RegistrationViewTest(ApiTestCase):
no_extra_fields_setting, no_extra_fields_setting,
{ {
u"name": u"name", u"name": u"name",
u"defaultValue": u"",
u"type": u"text", u"type": u"text",
u"required": True, u"required": True,
u"label": u"Full Name", u"label": u"Full Name",
u"placeholder": u"",
u"instructions": u"Needed for any certificates you may earn", u"instructions": u"Needed for any certificates you may earn",
u"restrictions": { u"restrictions": {
"max_length": 255, "max_length": 255,
} },
} }
) )
...@@ -795,16 +795,14 @@ class RegistrationViewTest(ApiTestCase): ...@@ -795,16 +795,14 @@ class RegistrationViewTest(ApiTestCase):
no_extra_fields_setting, no_extra_fields_setting,
{ {
u"name": u"username", u"name": u"username",
u"defaultValue": u"",
u"type": u"text", u"type": u"text",
u"required": True, u"required": True,
u"label": u"Public Username", 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"instructions": u"Will be shown in any discussions or forums you participate in (cannot be changed)",
u"restrictions": { u"restrictions": {
u"min_length": 2, u"min_length": 2,
u"max_length": 30, u"max_length": 30,
} },
} }
) )
...@@ -812,12 +810,9 @@ class RegistrationViewTest(ApiTestCase): ...@@ -812,12 +810,9 @@ class RegistrationViewTest(ApiTestCase):
no_extra_fields_setting, no_extra_fields_setting,
{ {
u"name": u"password", u"name": u"password",
u"defaultValue": u"",
u"type": u"text", u"type": u"text",
u"required": True, u"required": True,
u"label": u"Password", u"label": u"Password",
u"placeholder": u"",
u"instructions": u"",
u"restrictions": { u"restrictions": {
u"min_length": 2, u"min_length": 2,
u"max_length": 75 u"max_length": 75
...@@ -838,13 +833,8 @@ class RegistrationViewTest(ApiTestCase): ...@@ -838,13 +833,8 @@ class RegistrationViewTest(ApiTestCase):
no_extra_fields_setting, no_extra_fields_setting,
{ {
"name": "password", "name": "password",
"defaultValue": "",
"type": "hidden", "type": "hidden",
"required": False, "required": False,
"label": "",
"placeholder": "",
"instructions": "",
"restrictions": {},
} }
) )
...@@ -875,7 +865,6 @@ class RegistrationViewTest(ApiTestCase): ...@@ -875,7 +865,6 @@ class RegistrationViewTest(ApiTestCase):
u"type": u"text", u"type": u"text",
u"required": True, u"required": True,
u"label": u"Full Name", u"label": u"Full Name",
u"placeholder": u"",
u"instructions": u"Needed for any certificates you may earn", u"instructions": u"Needed for any certificates you may earn",
u"restrictions": { u"restrictions": {
"max_length": 255, "max_length": 255,
...@@ -906,12 +895,9 @@ class RegistrationViewTest(ApiTestCase): ...@@ -906,12 +895,9 @@ class RegistrationViewTest(ApiTestCase):
{"level_of_education": "optional"}, {"level_of_education": "optional"},
{ {
"name": "level_of_education", "name": "level_of_education",
"defaultValue": "",
"type": "select", "type": "select",
"required": False, "required": False,
"label": "Highest Level of Education Completed", "label": "Highest Level of Education Completed",
"placeholder": "",
"instructions": "",
"options": [ "options": [
{"value": "", "name": "--"}, {"value": "", "name": "--"},
{"value": "p", "name": "Doctorate"}, {"value": "p", "name": "Doctorate"},
...@@ -924,7 +910,6 @@ class RegistrationViewTest(ApiTestCase): ...@@ -924,7 +910,6 @@ class RegistrationViewTest(ApiTestCase):
{"value": "none", "name": "None"}, {"value": "none", "name": "None"},
{"value": "other", "name": "Other"}, {"value": "other", "name": "Other"},
], ],
"restrictions": {},
} }
) )
...@@ -933,19 +918,15 @@ class RegistrationViewTest(ApiTestCase): ...@@ -933,19 +918,15 @@ class RegistrationViewTest(ApiTestCase):
{"gender": "optional"}, {"gender": "optional"},
{ {
"name": "gender", "name": "gender",
"defaultValue": "",
"type": "select", "type": "select",
"required": False, "required": False,
"label": "Gender", "label": "Gender",
"placeholder": "",
"instructions": "",
"options": [ "options": [
{"value": "", "name": "--"}, {"value": "", "name": "--"},
{"value": "m", "name": "Male"}, {"value": "m", "name": "Male"},
{"value": "f", "name": "Female"}, {"value": "f", "name": "Female"},
{"value": "o", "name": "Other"}, {"value": "o", "name": "Other"},
], ],
"restrictions": {},
} }
) )
...@@ -961,14 +942,10 @@ class RegistrationViewTest(ApiTestCase): ...@@ -961,14 +942,10 @@ class RegistrationViewTest(ApiTestCase):
{"year_of_birth": "optional"}, {"year_of_birth": "optional"},
{ {
"name": "year_of_birth", "name": "year_of_birth",
"defaultValue": "",
"type": "select", "type": "select",
"required": False, "required": False,
"label": "Year of Birth", "label": "Year of Birth",
"placeholder": "",
"instructions": "",
"options": year_options, "options": year_options,
"restrictions": {},
} }
) )
...@@ -977,13 +954,9 @@ class RegistrationViewTest(ApiTestCase): ...@@ -977,13 +954,9 @@ class RegistrationViewTest(ApiTestCase):
{"mailing_address": "optional"}, {"mailing_address": "optional"},
{ {
"name": "mailing_address", "name": "mailing_address",
"defaultValue": "",
"type": "textarea", "type": "textarea",
"required": False, "required": False,
"label": "Mailing Address", "label": "Mailing Address",
"placeholder": "",
"instructions": "",
"restrictions": {},
} }
) )
...@@ -992,13 +965,9 @@ class RegistrationViewTest(ApiTestCase): ...@@ -992,13 +965,9 @@ class RegistrationViewTest(ApiTestCase):
{"goals": "optional"}, {"goals": "optional"},
{ {
"name": "goals", "name": "goals",
"defaultValue": "",
"type": "textarea", "type": "textarea",
"required": False, "required": False,
"label": "Please share with us your reasons for registering with edX", "label": "Please share with us your reasons for registering with edX",
"placeholder": "",
"instructions": "",
"restrictions": {},
} }
) )
...@@ -1007,13 +976,9 @@ class RegistrationViewTest(ApiTestCase): ...@@ -1007,13 +976,9 @@ class RegistrationViewTest(ApiTestCase):
{"city": "optional"}, {"city": "optional"},
{ {
"name": "city", "name": "city",
"defaultValue": "",
"type": "text", "type": "text",
"required": False, "required": False,
"label": "City", "label": "City",
"placeholder": "",
"instructions": "",
"restrictions": {},
} }
) )
...@@ -1030,13 +995,9 @@ class RegistrationViewTest(ApiTestCase): ...@@ -1030,13 +995,9 @@ class RegistrationViewTest(ApiTestCase):
{ {
"label": "Country", "label": "Country",
"name": "country", "name": "country",
"defaultValue": "",
"type": "select", "type": "select",
"required": True, "required": True,
"placeholder": "",
"instructions": "",
"options": country_options, "options": country_options,
"restrictions": {},
} }
) )
...@@ -1053,9 +1014,9 @@ class RegistrationViewTest(ApiTestCase): ...@@ -1053,9 +1014,9 @@ class RegistrationViewTest(ApiTestCase):
"defaultValue": False, "defaultValue": False,
"type": "checkbox", "type": "checkbox",
"required": True, "required": True,
"placeholder": "", "errorMessages": {
"instructions": "", "required": "You must agree to the <a href=\"https://www.test.com/honor\">Terms of Service and Honor Code</a>"
"restrictions": {}, }
} }
) )
...@@ -1070,9 +1031,9 @@ class RegistrationViewTest(ApiTestCase): ...@@ -1070,9 +1031,9 @@ class RegistrationViewTest(ApiTestCase):
"defaultValue": False, "defaultValue": False,
"type": "checkbox", "type": "checkbox",
"required": True, "required": True,
"placeholder": "", "errorMessages": {
"instructions": "", "required": "You must agree to the <a href=\"/honor\">Terms of Service and Honor Code</a>"
"restrictions": {}, }
} }
) )
...@@ -1093,9 +1054,9 @@ class RegistrationViewTest(ApiTestCase): ...@@ -1093,9 +1054,9 @@ class RegistrationViewTest(ApiTestCase):
"defaultValue": False, "defaultValue": False,
"type": "checkbox", "type": "checkbox",
"required": True, "required": True,
"placeholder": "", "errorMessages": {
"instructions": "", "required": "You must agree to the <a href=\"https://www.test.com/honor\">Honor Code</a>"
"restrictions": {}, }
} }
) )
...@@ -1108,9 +1069,9 @@ class RegistrationViewTest(ApiTestCase): ...@@ -1108,9 +1069,9 @@ class RegistrationViewTest(ApiTestCase):
"defaultValue": False, "defaultValue": False,
"type": "checkbox", "type": "checkbox",
"required": True, "required": True,
"placeholder": "", "errorMessages": {
"instructions": "", "required": "You must agree to the <a href=\"https://www.test.com/tos\">Terms of Service</a>"
"restrictions": {}, }
} }
) )
...@@ -1127,9 +1088,9 @@ class RegistrationViewTest(ApiTestCase): ...@@ -1127,9 +1088,9 @@ class RegistrationViewTest(ApiTestCase):
"defaultValue": False, "defaultValue": False,
"type": "checkbox", "type": "checkbox",
"required": True, "required": True,
"placeholder": "", "errorMessages": {
"instructions": "", "required": "You must agree to the <a href=\"/honor\">Honor Code</a>"
"restrictions": {}, }
} }
) )
...@@ -1142,9 +1103,9 @@ class RegistrationViewTest(ApiTestCase): ...@@ -1142,9 +1103,9 @@ class RegistrationViewTest(ApiTestCase):
"defaultValue": False, "defaultValue": False,
"type": "checkbox", "type": "checkbox",
"required": True, "required": True,
"placeholder": "", "errorMessages": {
"instructions": "", "required": "You must agree to the <a href=\"/tos\">Terms of Service</a>"
"restrictions": {}, }
} }
) )
...@@ -1384,6 +1345,19 @@ class RegistrationViewTest(ApiTestCase): ...@@ -1384,6 +1345,19 @@ class RegistrationViewTest(ApiTestCase):
AssertionError 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 # Retrieve the registration form description
with override_settings(REGISTRATION_EXTRA_FIELDS=extra_fields_setting): with override_settings(REGISTRATION_EXTRA_FIELDS=extra_fields_setting):
response = self.client.get(self.url) response = self.client.get(self.url)
......
...@@ -377,37 +377,41 @@ class RegistrationView(APIView): ...@@ -377,37 +377,41 @@ class RegistrationView(APIView):
# Translators: This is a legal document users must agree to in order to register a new account. # 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") 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. terms_link = u"<a href=\"{url}\">{terms_text}</a>".format(
label = _( url=marketing_link("HONOR"),
u"I agree to the {terms_of_service}" terms_text=terms_text
).format(
terms_of_service=u"<a href=\"{url}\">{terms_text}</a>".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( form_desc.add_field(
"honor_code", "honor_code",
label=label, label=label,
field_type="checkbox", field_type="checkbox",
default=False, default=False,
required=required, required=required,
error_messages={
"required": error_msg
}
) )
def _add_terms_of_service_field(self, form_desc, required=True): 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. # Translators: This is a legal document users must agree to in order to register a new account.
terms_text = _(u"Terms of Service") terms_text = _(u"Terms of Service")
terms_link = u"<a href=\"{url}\">{terms_text}</a>".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. # Translators: "Terms of service" is a legal document users must agree to in order to register a new account.
label = _( label = _(u"I agree to the {terms_of_service}").format(terms_of_service=terms_link)
u"I agree to the {terms_of_service}"
).format( # Translators: "Terms of service" is a legal document users must agree to in order to register a new account.
terms_of_service=u"<a href=\"{url}\">{terms_text}</a>".format( error_msg = _("You must agree to the {terms_of_service}").format(terms_of_service=terms_link)
url=marketing_link("TOS"),
terms_text=terms_text
)
)
form_desc.add_field( form_desc.add_field(
"terms_of_service", "terms_of_service",
...@@ -415,6 +419,9 @@ class RegistrationView(APIView): ...@@ -415,6 +419,9 @@ class RegistrationView(APIView):
field_type="checkbox", field_type="checkbox",
default=False, default=False,
required=required, required=required,
error_messages={
"required": error_msg
}
) )
def _options_with_default(self, options): def _options_with_default(self, options):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment