Ticket #11603: assertformseterror.diff.patch

File assertformseterror.diff.patch, 20.4 KB (added by martin_speleo, 12 years ago)

Maintance update of patch, and removal of entry in release notes for 1.4

  • AUTHORS

     
    219219    pradeep.gowda@gmail.com
    220220    Collin Grady <collin@collingrady.com>
    221221    Gabriel Grant <g@briel.ca>
     222    Martin Green
    222223    Simon Greenhill <dev@simon.net.nz>
    223224    Owen Griffiths
    224225    Espen Grindhaug <http://grindhaug.org/>
  • django/test/testcases.py

     
    717717            self.fail(msg_prefix + "The form '%s' was not used to render the"
    718718                      " response" % form)
    719719
     720    def assertFormsetError(self, response, formset, form_index, field, errors,
     721                           msg_prefix=''):
     722        """
     723        Asserts that a formset used to render the response has a specific error.
     724
     725        For field errors specify the form_index and the field.
     726        For non-field errors specify the form_index and the field as None.
     727        For non-form errors specify form_index as None and the field as None.
     728        """
     729
     730        # Add punctuation to msg_prefix
     731        if msg_prefix:
     732            msg_prefix += ": "
     733
     734        # Put context(s) into a list to simplify processing.
     735        contexts = to_list(response.context)
     736        if not contexts:
     737            self.fail(msg_prefix + 'Response did not use any contexts to '
     738                      'render the response')
     739
     740        # Put error(s) into a list to simplify processing.
     741        errors = to_list(errors)
     742
     743        # Search all contexts for the error.
     744        found_formset = False
     745        for i,context in enumerate(contexts):
     746            if formset not in context:
     747                continue
     748            found_formset = True
     749            for err in errors:
     750                if field is not None:
     751                    if field in context[formset].forms[form_index].errors:
     752                        field_errors = \
     753                                     context[formset].forms[form_index].errors[field]
     754                        self.assertTrue(err in field_errors,
     755                                msg_prefix + "The field '%s' on formset '%s', "
     756                                "form %d in context %d does not contain the "
     757                                "error '%s' (actual errors: %s)" %
     758                                        (field, formset, form_index, i, err,
     759                                        repr(field_errors)))
     760                    elif field in context[formset].forms[form_index].fields:
     761                        self.fail(msg_prefix + "The field '%s' "
     762                                  "on formset '%s', form %d in "
     763                                  "context %d contains no errors" %
     764                                        (field, formset, form_index,i))
     765                    else:
     766                        self.fail(msg_prefix + "The formset '%s', form %d in "
     767                                 "context %d does not contain the field '%s'" %
     768                                        (formset, form_index, i, field))
     769                elif form_index is not None:
     770                    non_field_errors = \
     771                                context[formset].forms[form_index].non_field_errors()
     772                    self.assertFalse(len(non_field_errors) == 0,
     773                                msg_prefix + "The formset '%s', form %d in "
     774                                "context %d does not contain any non-field "
     775                                "errors." % (formset, form_index, i))
     776                    self.assertTrue(err in non_field_errors,
     777                                    msg_prefix + "The formset '%s', form %d "
     778                                    "in context %d does not contain the "
     779                                    "non-field error '%s' "
     780                                    "(actual errors: %s)" %
     781                                        (formset, form_index, i, err,
     782                                         repr(non_field_errors)))
     783                else:
     784                    non_form_errors = context[formset].non_form_errors()
     785                    self.assertFalse(len(non_form_errors) == 0,
     786                                     msg_prefix + "The formset '%s' in "
     787                                     "context %d does not contain any "
     788                                     "non-form errors." % (formset, i))
     789                    self.assertTrue(err in non_form_errors,
     790                                    msg_prefix + "The formset '%s' in context "
     791                                    "%d does not contain the "
     792                                    "non-form error '%s' (actual errors: %s)" %
     793                                      (formset, i, err, repr(non_form_errors)))
     794        if not found_formset:
     795            self.fail(msg_prefix + "The formset '%s' was not used to render "
     796                      "the response" % formset)
     797
    720798    def assertTemplateUsed(self, response=None, template_name=None, msg_prefix=''):
    721799        """
    722800        Asserts that the template with the provided name was used in rendering
  • docs/topics/testing.txt

     
    15831583
    15841584    ``errors`` is an error string, or a list of error strings, that are
    15851585    expected as a result of form validation.
     1586 
     1587.. method:: TestCase.assertFormsetError(response, formset, form_index, field, errors, msg_prefix='')
    15861588
     1589    .. versionadded:: 1.4
     1590   
     1591    Asserts that the formset raises the provided list of errors when rendered.
     1592
     1593    ``formset`` is the name the ``Formset`` instance was given in the template
     1594    context.
     1595
     1596    ``form_index`` is the number of the form within the ``Formset``.  If ``form_index``
     1597    has a value of ``None``, non-form errors (errors you can access via
     1598    ``formset.non_form_errors()``) will be checked.
     1599
     1600    ``field`` is the name of the field on the form to check. If ``field``
     1601    has a value of ``None``, non-field errors (errors you can access via
     1602    ``form.non_field_errors()``) will be checked.
     1603
     1604    ``errors`` is an error string, or a list of error strings, that are
     1605    expected as a result of form validation.
     1606
    15871607.. method:: TestCase.assertTemplateUsed(response, template_name, msg_prefix='')
    15881608
    15891609    Asserts that the template with the given name was used in rendering the
  • tests/modeltests/test_client/urls.py

     
    2121    (r'^bad_view/$', views.bad_view),
    2222    (r'^form_view/$', views.form_view),
    2323    (r'^form_view_with_template/$', views.form_view_with_template),
     24    (r'^formset_view/$', views.formset_view),
    2425    (r'^login_protected_view/$', views.login_protected_view),
    2526    (r'^login_protected_method_view/$', views.login_protected_method_view),
    2627    (r'^login_protected_view_custom_redirect/$', views.login_protected_view_changed_redirect),
  • tests/modeltests/test_client/views.py

     
    33from django.contrib.auth.decorators import login_required, permission_required
    44from django.core import mail
    55from django.forms import fields
    6 from django.forms.forms import Form
     6from django.forms.forms import Form, ValidationError
     7from django.forms.formsets import formset_factory, BaseFormSet
    78from django.http import HttpResponse, HttpResponseRedirect, HttpResponseNotFound
    89from django.shortcuts import render_to_response
    910from django.template import Context, Template
     
    9293    value = fields.IntegerField()
    9394    single = fields.ChoiceField(choices=TestChoices)
    9495    multi = fields.MultipleChoiceField(choices=TestChoices)
     96    def clean(self):
     97        cleaned_data = self.cleaned_data
     98        if cleaned_data.get("text") == "Raise non-field error":
     99            raise ValidationError(u"Non-field error.")
     100        # Always return the full collection of cleaned data.
     101        return cleaned_data
    95102
    96103def form_view(request):
    97104    "A view that tests a simple form"
     
    128135        }
    129136    )
    130137
     138class BaseTestFormSet(BaseFormSet):
     139    def clean(self):
     140        """Checks that no two E-mail addresses are the same."""
     141        if any(self.errors):
     142               # Don't bother validating the formset unless each form is valid
     143               # (form.cleaned_data will not exist)
     144               return
     145        emails = []
     146        for i in range(0, self.total_form_count()):
     147            form = self.forms[i]
     148
     149            email = form.cleaned_data['email']
     150            if email in emails:
     151                raise ValidationError, \
     152                      "Forms in a set must have distinct E-mail addresses."
     153            emails.append(email)
     154
     155TestFormSet = formset_factory(TestForm, BaseTestFormSet)
     156
     157def formset_view(request):
     158    "A view that tests a simple formset"
     159    if request.method == 'POST':
     160        formset = TestFormSet(request.POST)
     161        if formset.is_valid():
     162            t = Template('Valid POST data.', name='Valid POST Template')
     163            c = Context()
     164        else:
     165            t = Template('Invalid POST data. {{ my_formset.errors }}',
     166                         name='Invalid POST Template')
     167            c = Context({'my_formset': formset})
     168    else:
     169        formset = TestForm(request.GET)
     170        t = Template('Viewing base formset. {{ my_formset }}.',
     171                     name='Formset GET Template')
     172        c = Context({'my_formset': formset})
     173    return HttpResponse(t.render(c))
     174
    131175def login_protected_view(request):
    132176    "A simple view that is login protected."
    133177    t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template')
  • tests/regressiontests/test_client_regress/models.py

     
    22"""
    33Regression tests for the Test Client, especially the customized assertions.
    44"""
     5from __future__ import with_statement
    56import os
    67import warnings
    78
     
    523524        except AssertionError, e:
    524525            self.assertIn("abc: The form 'form' in context 0 does not contain the non-field error 'Some error.' (actual errors: )", str(e))
    525526
     527class AssertFormsetErrorTests(TestCase):
     528    msg_prefixes = [("", {}), ("abc: ", {"msg_prefix": "abc"})]
     529    def setUp(self):
     530        """Makes response object for testing field and non-field errors"""
     531        #For testing field and non-field errors
     532        self.response_form_errors = self.getResponse(
     533           {'form-TOTAL_FORMS': u'2',
     534            'form-INITIAL_FORMS': u'2',
     535            'form-0-text': 'Raise non-field error',
     536            'form-0-email': 'not an email address',
     537            'form-0-value': 37,
     538            'form-0-single': 'b',
     539            'form-0-multi': ('b','c','e'),
     540            'form-1-text': 'Hello World',
     541            'form-1-email': 'email@domain.com',
     542            'form-1-value': 37,
     543            'form-1-single': 'b',
     544            'form-1-multi': ('b','c','e'),
     545        })
     546        #For testing non-form errors
     547        self.response_nonform_errors = self.getResponse(
     548           {'form-TOTAL_FORMS': u'2',
     549            'form-INITIAL_FORMS': u'2',
     550            'form-0-text': 'Hello World',
     551            'form-0-email': 'email@domain.com',
     552            'form-0-value': 37,
     553            'form-0-single': 'b',
     554            'form-0-multi': ('b','c','e'),
     555            'form-1-text': 'Hello World',
     556            'form-1-email': 'email@domain.com',
     557            'form-1-value': 37,
     558            'form-1-single': 'b',
     559            'form-1-multi': ('b','c','e'),
     560        })
     561
     562    def getResponse(self, post_data):
     563        response = self.client.post('/test_client/formset_view/',
     564                                    post_data)
     565        self.assertEqual(response.status_code, 200)
     566        self.assertTemplateUsed(response, "Invalid POST Template")
     567        return response
     568
     569    def test_unknown_formset(self):
     570        "An assertion is raised if the formset name is unknown"
     571        for prefix, kwargs in self.msg_prefixes:
     572            with self.assertRaises(AssertionError) as cm:
     573                self.assertFormsetError(self.response_form_errors,
     574                                        'wrong_formset',
     575                                        0,
     576                                        'Some_field',
     577                                        'Some error.',
     578                                        **kwargs)           
     579            self.assertIn(prefix + "The formset 'wrong_formset' was not "
     580                                   "used to render the response",
     581                          str(cm.exception))
     582
     583    def test_unknown_field(self):
     584        "An assertion is raised if the field name is unknown"
     585        for prefix, kwargs in self.msg_prefixes:
     586            with self.assertRaises(AssertionError) as cm:
     587                self.assertFormsetError(self.response_form_errors,
     588                                        'my_formset',
     589                                        0,
     590                                        'Some_field',
     591                                        'Some error.',
     592                                        **kwargs)
     593            self.assertIn(prefix + "The formset 'my_formset', "
     594                                   "form 0 in context 0 "
     595                                   "does not contain the field 'Some_field'",
     596                          str(cm.exception))
     597
     598    def test_noerror_field(self):
     599        "An assertion is raised if the field doesn't have any errors"
     600        for prefix, kwargs in self.msg_prefixes:
     601            with self.assertRaises(AssertionError) as cm:
     602                self.assertFormsetError(self.response_form_errors,
     603                                        'my_formset',
     604                                        1,
     605                                        'value',
     606                                        'Some error.',
     607                                        **kwargs)
     608            self.assertIn(prefix + "The field 'value' "
     609                                   "on formset 'my_formset', form 1 "
     610                                   "in context 0 contains no errors",
     611                          str(cm.exception))
     612
     613    def test_unknown_error(self):
     614        "An assertion is raised if the field doesn't contain the specified error"
     615        for prefix, kwargs in self.msg_prefixes:
     616            with self.assertRaises(AssertionError) as cm:
     617                self.assertFormsetError(self.response_form_errors,
     618                                        'my_formset',
     619                                        0,
     620                                        'email',
     621                                        'Some error.',
     622                                        **kwargs)
     623            self.assertIn(prefix + "The field 'email' "
     624                                   "on formset 'my_formset', form 0 "
     625                                   "in context 0 does not contain the error "
     626                                   "'Some error.' (actual errors: "
     627                                   "[u'Enter a valid e-mail address.'])",
     628                          str(cm.exception))
     629
     630    def test_field_error(self):
     631        "No assertion is raised if the field contains the provided error"
     632        for prefix, kwargs in self.msg_prefixes:
     633            self.assertFormsetError(self.response_form_errors,
     634                                'my_formset',
     635                                0,
     636                                'email',
     637                                'Enter a valid e-mail address.',
     638                                **kwargs)
     639
     640    def test_no_nonfield_error(self):
     641        "An assertion is raised if the formsets non-field errors doesn't contain any errors."
     642        for prefix, kwargs in self.msg_prefixes:
     643            with self.assertRaises(AssertionError) as cm:
     644                self.assertFormsetError(self.response_form_errors,
     645                                        'my_formset',
     646                                        1,
     647                                        None,
     648                                        'Some error.',
     649                                        **kwargs)
     650            self.assertIn(prefix + "The formset 'my_formset', form 1 in "
     651                                   "context 0 does not contain any "
     652                                   "non-field errors.",
     653                          str(cm.exception))
     654
     655    def test_unknown_nonfield_error(self):
     656        "An assertion is raised if the formsets non-field errors doesn't contain the provided error."
     657        for prefix, kwargs in self.msg_prefixes:
     658            with self.assertRaises(AssertionError) as cm:
     659                self.assertFormsetError(self.response_form_errors,
     660                                        'my_formset',
     661                                        0,
     662                                        None,
     663                                        'Some error.',
     664                                        **kwargs)
     665            self.assertIn(prefix + "The formset 'my_formset', form 0 in "
     666                                   "context 0 does not contain the non-field error "
     667                                   "'Some error.' (actual errors: "
     668                                   "[u'Non-field error.'])",
     669                          str(cm.exception))
     670
     671    def test_nonfield_error(self):
     672        "No assertion is raised if the formsets non-field errors contains the provided error."
     673        for prefix, kwargs in self.msg_prefixes:
     674            self.assertFormsetError(self.response_form_errors,
     675                                'my_formset',
     676                                0,
     677                                None,
     678                                'Non-field error.',
     679                                **kwargs)
     680
     681    def test_no_nonform_error(self):
     682        "An assertion is raised if the formsets non-form errors doesn't contain any errors."
     683        for prefix, kwargs in self.msg_prefixes:
     684            with self.assertRaises(AssertionError) as cm:
     685                self.assertFormsetError(self.response_form_errors,
     686                                        'my_formset',
     687                                        None,
     688                                        None,
     689                                        'Some error.',
     690                                        **kwargs)
     691            self.assertIn(prefix + "The formset 'my_formset' in context 0 "
     692                                   "does not contain any non-form errors.",
     693                          str(cm.exception))
     694
     695    def test_unknown_nonform_error(self):
     696        "An assertion is raised if the formsets non-form errors doesn't contain the provided error."
     697        for prefix, kwargs in self.msg_prefixes:
     698            with self.assertRaises(AssertionError) as cm:
     699                self.assertFormsetError(self.response_nonform_errors,
     700                                        'my_formset',
     701                                        None,
     702                                        None,
     703                                        'Some error.',
     704                                        **kwargs)
     705            self.assertIn(prefix + "The formset 'my_formset' in context 0 "
     706                                   "does not contain the non-form error "
     707                                   "'Some error.' (actual errors: [u'Forms "
     708                                   "in a set must have distinct E-mail "
     709                                   "addresses.'])",
     710                          str(cm.exception))
     711
     712    def test_nonform_error(self):
     713        "No assertion is raised if the formsets non-form errors contains the provided error."
     714        for prefix, kwargs in self.msg_prefixes:
     715            self.assertFormsetError(self.response_nonform_errors,
     716                                    'my_formset',
     717                                    None,
     718                                    None,
     719                                    'Forms in a set must have distinct E-mail '
     720                                    'addresses.',
     721                                    **kwargs)
     722
    526723class LoginTests(TestCase):
    527724    fixtures = ['testdata']
    528725
Back to Top