From b68c7a5abbb737c54dff91e56e0e56e67cd3f718 Mon Sep 17 00:00:00 2001 From: Loic Bistuer Date: Tue, 1 Jul 2014 20:48:00 +0700 Subject: [1.7.x] Fixed #22915 -- Document backward incompatible changes in the ValidationError constructor. This patch also fixes update_error_dict to better handle the use case described in this ticket, previously the type of the provided container could be lost in some conditions. Thanks Russell Keith-Magee for the report and Tim Graham for review. Backport of eb7df6b8d7 from master --- tests/forms_tests/tests/test_forms.py | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'tests') diff --git a/tests/forms_tests/tests/test_forms.py b/tests/forms_tests/tests/test_forms.py index a410e9a0f1..a2be118e10 100644 --- a/tests/forms_tests/tests/test_forms.py +++ b/tests/forms_tests/tests/test_forms.py @@ -6,6 +6,7 @@ import datetime import json import warnings +from django.core.exceptions import NON_FIELD_ERRORS from django.core.files.uploadedfile import SimpleUploadedFile from django.core.validators import RegexValidator from django.forms import ( @@ -739,6 +740,53 @@ class FormsTestCase(TestCase): with six.assertRaisesRegex(self, ValueError, "has no field named"): f.add_error('missing_field', 'Some error.') + def test_update_error_dict(self): + class CodeForm(Form): + code = CharField(max_length=10) + + def clean(self): + try: + raise ValidationError({'code': [ValidationError('Code error 1.')]}) + except ValidationError as e: + self._errors = e.update_error_dict(self._errors) + + try: + raise ValidationError({'code': [ValidationError('Code error 2.')]}) + except ValidationError as e: + self._errors = e.update_error_dict(self._errors) + + try: + raise ValidationError({'code': forms.ErrorList(['Code error 3.'])}) + except ValidationError as e: + self._errors = e.update_error_dict(self._errors) + + try: + raise ValidationError('Non-field error 1.') + except ValidationError as e: + self._errors = e.update_error_dict(self._errors) + + try: + raise ValidationError([ValidationError('Non-field error 2.')]) + except ValidationError as e: + self._errors = e.update_error_dict(self._errors) + + # Ensure that the newly added list of errors is an instance of ErrorList. + for field, error_list in self._errors.items(): + if not isinstance(error_list, self.error_class): + self._errors[field] = self.error_class(error_list) + + form = CodeForm({'code': 'hello'}) + # Trigger validation. + self.assertFalse(form.is_valid()) + + # Check that update_error_dict didn't lose track of the ErrorDict type. + self.assertTrue(isinstance(form._errors, forms.ErrorDict)) + + self.assertEqual(dict(form.errors), { + 'code': ['Code error 1.', 'Code error 2.', 'Code error 3.'], + NON_FIELD_ERRORS: ['Non-field error 1.', 'Non-field error 2.'], + }) + def test_dynamic_construction(self): # It's possible to construct a Form dynamically by adding to the self.fields # dictionary in __init__(). Don't forget to call Form.__init__() within the -- cgit v1.3