From 6f3c78dbe6f17997aa9d115d041bbb0318061ba7 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Tue, 27 Sep 2016 09:56:19 -0400 Subject: [PATCH] Fixed #27266 -- Allowed using assertFormError()/assertFormsetError() in admin forms and formsets. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks Diego Andrés Sanabria Martín for the report and review. --- django/contrib/admin/helpers.py | 16 ++++++++++++ tests/admin_views/tests.py | 46 ++++++++++++++++----------------- 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/django/contrib/admin/helpers.py b/django/contrib/admin/helpers.py index 157c90af47..c433f32579 100644 --- a/django/contrib/admin/helpers.py +++ b/django/contrib/admin/helpers.py @@ -56,6 +56,14 @@ class AdminForm(object): **options ) + @property + def errors(self): + return self.form.errors + + @property + def non_field_errors(self): + return self.form.non_field_errors + @property def media(self): media = self.form.media @@ -303,6 +311,14 @@ class InlineAdminFormSet(object): } }) + @property + def forms(self): + return self.formset.forms + + @property + def non_form_errors(self): + return self.formset.non_form_errors + @property def media(self): media = self.opts.media + self.formset.media diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index c4ef2b5114..ba15e18a2c 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -1474,8 +1474,7 @@ class AdminViewPermissionsTest(TestCase): self.assertEqual(response.status_code, 302) login = self.client.post(login_url, self.no_username_login) self.assertEqual(login.status_code, 200) - form = login.context[0].get('form') - self.assertEqual(form.errors['username'][0], 'This field is required.') + self.assertFormError(login, 'form', 'username', ['This field is required.']) def test_login_redirect_for_direct_get(self): """ @@ -4935,9 +4934,8 @@ class UserAdminTest(TestCase): 'password2': 'mismatch', }) self.assertEqual(response.status_code, 200) - adminform = response.context['adminform'] - self.assertNotIn('password', adminform.form.errors) - self.assertEqual(adminform.form.errors['password2'], ["The two password fields didn't match."]) + self.assertFormError(response, 'adminform', 'password', []) + self.assertFormError(response, 'adminform', 'password2', ["The two password fields didn't match."]) def test_user_fk_add_popup(self): """User addition through a FK popup should return the appropriate JavaScript response.""" @@ -5922,7 +5920,9 @@ class AdminViewOnSiteTests(TestCase): """ Issue #20522 Verifying that if the parent form fails validation, the inlines also - run validation even if validation is contingent on parent form data + run validation even if validation is contingent on parent form data. + Also, assertFormError() and assertFormsetError() is usable for admin + forms and formsets. """ # The form validation should fail because 'some_required_info' is # not included on the parent form, and the family_name of the parent @@ -5936,15 +5936,17 @@ class AdminViewOnSiteTests(TestCase): "dependentchild_set-0-family_name": "Test2"} response = self.client.post(reverse('admin:admin_views_parentwithdependentchildren_add'), post_data) - - # just verifying the parent form failed validation, as expected -- - # this isn't the regression test - self.assertIn('some_required_info', response.context['adminform'].form.errors) - - # actual regression test - for error_set in response.context['inline_admin_formset'].formset.errors: - self.assertEqual(['Children must share a family name with their parents in this contrived test case'], - error_set.get('__all__')) + self.assertFormError(response, 'adminform', 'some_required_info', ['This field is required.']) + msg = "The form 'adminform' in context 0 does not contain the non-field error 'Error'" + with self.assertRaisesMessage(AssertionError, msg): + self.assertFormError(response, 'adminform', None, ['Error']) + self.assertFormsetError( + response, 'inline_admin_formset', 0, None, + ['Children must share a family name with their parents in this contrived test case'] + ) + msg = "The formset 'inline_admin_formset' in context 4 does not contain any non-form errors." + with self.assertRaisesMessage(AssertionError, msg): + self.assertFormsetError(response, 'inline_admin_formset', None, None, ['Error']) def test_change_view_form_and_formsets_run_validation(self): """ @@ -5967,15 +5969,11 @@ class AdminViewOnSiteTests(TestCase): response = self.client.post( reverse('admin:admin_views_parentwithdependentchildren_change', args=(pwdc.id,)), post_data ) - - # just verifying the parent form failed validation, as expected -- - # this isn't the regression test - self.assertIn('some_required_info', response.context['adminform'].form.errors) - - # actual regression test - for error_set in response.context['inline_admin_formset'].formset.errors: - self.assertEqual(['Children must share a family name with their parents in this contrived test case'], - error_set.get('__all__')) + self.assertFormError(response, 'adminform', 'some_required_info', ['This field is required.']) + self.assertFormsetError( + response, 'inline_admin_formset', 0, None, + ['Children must share a family name with their parents in this contrived test case'] + ) def test_check(self): "Ensure that the view_on_site value is either a boolean or a callable"