Fixed #33348 -- Changed SimpleTestCase.assertFormError()/assertFormsetErrors() to take form/formset.
Instead of taking a response object and a context name for the form/formset, the two methods now take the object directly.
This commit is contained in:
parent
1a7d75cf77
commit
50e1e7ef8e
|
@ -441,9 +441,8 @@ class InlineAdminFormSet:
|
||||||
def forms(self):
|
def forms(self):
|
||||||
return self.formset.forms
|
return self.formset.forms
|
||||||
|
|
||||||
@property
|
|
||||||
def non_form_errors(self):
|
def non_form_errors(self):
|
||||||
return self.formset.non_form_errors
|
return self.formset.non_form_errors()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_bound(self):
|
def is_bound(self):
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import difflib
|
import difflib
|
||||||
|
import inspect
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import posixpath
|
import posixpath
|
||||||
|
@ -42,6 +43,7 @@ from django.db import DEFAULT_DB_ALIAS, connection, connections, transaction
|
||||||
from django.forms.fields import CharField
|
from django.forms.fields import CharField
|
||||||
from django.http import QueryDict
|
from django.http import QueryDict
|
||||||
from django.http.request import split_domain_port, validate_host
|
from django.http.request import split_domain_port, validate_host
|
||||||
|
from django.http.response import HttpResponseBase
|
||||||
from django.test.client import AsyncClient, Client
|
from django.test.client import AsyncClient, Client
|
||||||
from django.test.html import HTMLParseError, parse_html
|
from django.test.html import HTMLParseError, parse_html
|
||||||
from django.test.signals import template_rendered
|
from django.test.signals import template_rendered
|
||||||
|
@ -165,6 +167,127 @@ class _DatabaseFailure:
|
||||||
raise DatabaseOperationForbidden(self.message)
|
raise DatabaseOperationForbidden(self.message)
|
||||||
|
|
||||||
|
|
||||||
|
# RemovedInDjango50Warning
|
||||||
|
class _AssertFormErrorDeprecationHelper:
|
||||||
|
@staticmethod
|
||||||
|
def assertFormError(self, response, form, field, errors, msg_prefix=""):
|
||||||
|
"""
|
||||||
|
Search through all the rendered contexts of the `response` for a form named
|
||||||
|
`form` then dispatch to the new assertFormError() using that instance.
|
||||||
|
If multiple contexts contain the form, they're all checked in order and any
|
||||||
|
failure will abort (this matches the old behavior).
|
||||||
|
"""
|
||||||
|
warning_msg = (
|
||||||
|
f"Passing response to assertFormError() is deprecated. Use the form object "
|
||||||
|
f"directly: assertFormError(response.context[{form!r}], {field!r}, ...)"
|
||||||
|
)
|
||||||
|
warnings.warn(warning_msg, RemovedInDjango50Warning, stacklevel=2)
|
||||||
|
|
||||||
|
full_msg_prefix = f"{msg_prefix}: " if msg_prefix else ""
|
||||||
|
contexts = to_list(response.context) if response.context is not None else []
|
||||||
|
if not contexts:
|
||||||
|
self.fail(
|
||||||
|
f"{full_msg_prefix}Response did not use any contexts to render the "
|
||||||
|
f"response"
|
||||||
|
)
|
||||||
|
# Search all contexts for the error.
|
||||||
|
found_form = False
|
||||||
|
for i, context in enumerate(contexts):
|
||||||
|
if form not in context:
|
||||||
|
continue
|
||||||
|
found_form = True
|
||||||
|
self.assertFormError(context[form], field, errors, msg_prefix=msg_prefix)
|
||||||
|
if not found_form:
|
||||||
|
self.fail(
|
||||||
|
f"{full_msg_prefix}The form '{form}' was not used to render the "
|
||||||
|
f"response"
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def assertFormsetError(
|
||||||
|
self, response, formset, form_index, field, errors, msg_prefix=""
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Search for a formset named "formset" in the "response" and dispatch to
|
||||||
|
the new assertFormsetError() using that instance. If the name is found
|
||||||
|
in multiple contexts they're all checked in order and any failure will
|
||||||
|
abort the test.
|
||||||
|
"""
|
||||||
|
warning_msg = (
|
||||||
|
f"Passing response to assertFormsetError() is deprecated. Use the formset "
|
||||||
|
f"object directly: assertFormsetError(response.context[{formset!r}], "
|
||||||
|
f"{form_index!r}, ...)"
|
||||||
|
)
|
||||||
|
warnings.warn(warning_msg, RemovedInDjango50Warning, stacklevel=2)
|
||||||
|
|
||||||
|
full_msg_prefix = f"{msg_prefix}: " if msg_prefix else ""
|
||||||
|
contexts = to_list(response.context) if response.context is not None else []
|
||||||
|
if not contexts:
|
||||||
|
self.fail(
|
||||||
|
f"{full_msg_prefix}Response did not use any contexts to render the "
|
||||||
|
f"response"
|
||||||
|
)
|
||||||
|
found_formset = False
|
||||||
|
for i, context in enumerate(contexts):
|
||||||
|
if formset not in context or not hasattr(context[formset], "forms"):
|
||||||
|
continue
|
||||||
|
found_formset = True
|
||||||
|
self.assertFormsetError(
|
||||||
|
context[formset], form_index, field, errors, msg_prefix
|
||||||
|
)
|
||||||
|
if not found_formset:
|
||||||
|
self.fail(
|
||||||
|
f"{full_msg_prefix}The formset '{formset}' was not used to render the "
|
||||||
|
f"response"
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def patch_signature(cls, new_method):
|
||||||
|
"""
|
||||||
|
Replace the decorated method with a new one that inspects the passed
|
||||||
|
args/kwargs and dispatch to the old implementation (with deprecation
|
||||||
|
warning) when it detects the old signature.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@wraps(new_method)
|
||||||
|
def patched_method(self, *args, **kwargs):
|
||||||
|
old_method = getattr(cls, new_method.__name__)
|
||||||
|
old_signature = inspect.signature(old_method)
|
||||||
|
try:
|
||||||
|
old_bound_args = old_signature.bind(self, *args, **kwargs)
|
||||||
|
except TypeError:
|
||||||
|
# If old signature doesn't match then either:
|
||||||
|
# 1) new signature will match
|
||||||
|
# 2) or a TypeError will be raised showing the user information
|
||||||
|
# about the new signature.
|
||||||
|
return new_method(self, *args, **kwargs)
|
||||||
|
|
||||||
|
new_signature = inspect.signature(new_method)
|
||||||
|
try:
|
||||||
|
new_bound_args = new_signature.bind(self, *args, **kwargs)
|
||||||
|
except TypeError:
|
||||||
|
# Old signature matches but not the new one (because of
|
||||||
|
# previous try/except).
|
||||||
|
return old_method(self, *args, **kwargs)
|
||||||
|
|
||||||
|
# If both signatures match, decide on which method to call by
|
||||||
|
# inspecting the first arg (arg[0] = self).
|
||||||
|
assert old_bound_args.args[1] == new_bound_args.args[1]
|
||||||
|
if hasattr(
|
||||||
|
old_bound_args.args[1], "context"
|
||||||
|
): # Looks like a response object => old method.
|
||||||
|
return old_method(self, *args, **kwargs)
|
||||||
|
elif isinstance(old_bound_args.args[1], HttpResponseBase):
|
||||||
|
raise ValueError(
|
||||||
|
f"{old_method.__name__}() is only usable on responses fetched "
|
||||||
|
f"using the Django test Client."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return new_method(self, *args, **kwargs)
|
||||||
|
|
||||||
|
return patched_method
|
||||||
|
|
||||||
|
|
||||||
class SimpleTestCase(unittest.TestCase):
|
class SimpleTestCase(unittest.TestCase):
|
||||||
|
|
||||||
# The class we'll use for the test client self.client.
|
# The class we'll use for the test client self.client.
|
||||||
|
@ -585,22 +708,19 @@ class SimpleTestCase(unittest.TestCase):
|
||||||
|
|
||||||
self.assertEqual(field_errors, errors, msg_prefix + failure_message)
|
self.assertEqual(field_errors, errors, msg_prefix + failure_message)
|
||||||
|
|
||||||
def assertFormError(self, response, form, field, errors, msg_prefix=""):
|
# RemovedInDjango50Warning: When the deprecation ends, remove the
|
||||||
|
# decorator.
|
||||||
|
@_AssertFormErrorDeprecationHelper.patch_signature
|
||||||
|
def assertFormError(self, form, field, errors, msg_prefix=""):
|
||||||
"""
|
"""
|
||||||
Assert that a form used to render the response has a specific field
|
Assert that a field named "field" on the given form object has specific
|
||||||
error.
|
errors.
|
||||||
|
|
||||||
|
errors can be either a single error message or a list of errors
|
||||||
|
messages. Using errors=[] test that the field has no errors.
|
||||||
|
|
||||||
|
You can pass field=None to check the form's non-field errors.
|
||||||
"""
|
"""
|
||||||
self._check_test_client_response(response, "context", "assertFormError")
|
|
||||||
if msg_prefix:
|
|
||||||
msg_prefix += ": "
|
|
||||||
|
|
||||||
# Put context(s) into a list to simplify processing.
|
|
||||||
contexts = [] if response.context is None else to_list(response.context)
|
|
||||||
if not contexts:
|
|
||||||
self.fail(
|
|
||||||
msg_prefix + "Response did not use any contexts to render the response"
|
|
||||||
)
|
|
||||||
|
|
||||||
if errors is None:
|
if errors is None:
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"Passing errors=None to assertFormError() is deprecated, use "
|
"Passing errors=None to assertFormError() is deprecated, use "
|
||||||
|
@ -609,47 +729,25 @@ class SimpleTestCase(unittest.TestCase):
|
||||||
stacklevel=2,
|
stacklevel=2,
|
||||||
)
|
)
|
||||||
errors = []
|
errors = []
|
||||||
# Put error(s) into a list to simplify processing.
|
|
||||||
errors = to_list(errors)
|
|
||||||
|
|
||||||
# Search all contexts for the error.
|
|
||||||
found_form = False
|
|
||||||
for i, context in enumerate(contexts):
|
|
||||||
if form in context:
|
|
||||||
found_form = True
|
|
||||||
self._assert_form_error(
|
|
||||||
context[form], field, errors, msg_prefix, "form %r" % context[form]
|
|
||||||
)
|
|
||||||
if not found_form:
|
|
||||||
self.fail(
|
|
||||||
msg_prefix + "The form '%s' was not used to render the response" % form
|
|
||||||
)
|
|
||||||
|
|
||||||
def assertFormsetError(
|
|
||||||
self, response, formset, form_index, field, errors, msg_prefix=""
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Assert that a formset used to render the response has a specific error.
|
|
||||||
|
|
||||||
For field errors, specify the ``form_index`` and the ``field``.
|
|
||||||
For non-field errors, specify the ``form_index`` and the ``field`` as
|
|
||||||
None.
|
|
||||||
For non-form errors, specify ``form_index`` as None and the ``field``
|
|
||||||
as None.
|
|
||||||
"""
|
|
||||||
self._check_test_client_response(response, "context", "assertFormsetError")
|
|
||||||
# Add punctuation to msg_prefix
|
|
||||||
if msg_prefix:
|
if msg_prefix:
|
||||||
msg_prefix += ": "
|
msg_prefix += ": "
|
||||||
|
errors = to_list(errors)
|
||||||
|
self._assert_form_error(form, field, errors, msg_prefix, f"form {form!r}")
|
||||||
|
|
||||||
# Put context(s) into a list to simplify processing.
|
# RemovedInDjango50Warning: When the deprecation ends, remove the
|
||||||
contexts = [] if response.context is None else to_list(response.context)
|
# decorator.
|
||||||
if not contexts:
|
@_AssertFormErrorDeprecationHelper.patch_signature
|
||||||
self.fail(
|
def assertFormsetError(self, formset, form_index, field, errors, msg_prefix=""):
|
||||||
msg_prefix + "Response did not use any contexts to "
|
"""
|
||||||
"render the response"
|
Similar to assertFormError() but for formsets.
|
||||||
)
|
|
||||||
|
|
||||||
|
Use form_index=None to check the formset's non-form errors (in that
|
||||||
|
case, you must also use field=None).
|
||||||
|
Otherwise use an integer to check the formset's n-th form for errors.
|
||||||
|
|
||||||
|
Other parameters are the same as assertFormError().
|
||||||
|
"""
|
||||||
if errors is None:
|
if errors is None:
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"Passing errors=None to assertFormsetError() is deprecated, "
|
"Passing errors=None to assertFormsetError() is deprecated, "
|
||||||
|
@ -662,50 +760,31 @@ class SimpleTestCase(unittest.TestCase):
|
||||||
if form_index is None and field is not None:
|
if form_index is None and field is not None:
|
||||||
raise ValueError("You must use field=None with form_index=None.")
|
raise ValueError("You must use field=None with form_index=None.")
|
||||||
|
|
||||||
# Put error(s) into a list to simplify processing.
|
if msg_prefix:
|
||||||
|
msg_prefix += ": "
|
||||||
errors = to_list(errors)
|
errors = to_list(errors)
|
||||||
|
|
||||||
# Search all contexts for the error.
|
if not formset.is_bound:
|
||||||
found_formset = False
|
|
||||||
for i, context in enumerate(contexts):
|
|
||||||
if formset not in context or not hasattr(context[formset], "forms"):
|
|
||||||
continue
|
|
||||||
formset_repr = repr(context[formset])
|
|
||||||
if not context[formset].is_bound:
|
|
||||||
self.fail(
|
|
||||||
f"{msg_prefix}The formset {formset_repr} is not bound, it will "
|
|
||||||
f"never have any errors."
|
|
||||||
)
|
|
||||||
found_formset = True
|
|
||||||
if form_index is not None:
|
|
||||||
form_count = context[formset].total_form_count()
|
|
||||||
if form_index >= form_count:
|
|
||||||
form_or_forms = "forms" if form_count > 1 else "form"
|
|
||||||
self.fail(
|
|
||||||
f"{msg_prefix}The formset {formset_repr} only has "
|
|
||||||
f"{form_count} {form_or_forms}."
|
|
||||||
)
|
|
||||||
if form_index is not None:
|
|
||||||
form_repr = f"form {form_index} of formset {formset_repr}"
|
|
||||||
self._assert_form_error(
|
|
||||||
context[formset].forms[form_index],
|
|
||||||
field,
|
|
||||||
errors,
|
|
||||||
msg_prefix,
|
|
||||||
form_repr,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
failure_message = (
|
|
||||||
f"{msg_prefix}The non-form errors of formset {formset_repr} don't "
|
|
||||||
f"match."
|
|
||||||
)
|
|
||||||
self.assertEqual(
|
|
||||||
context[formset].non_form_errors(), errors, failure_message
|
|
||||||
)
|
|
||||||
if not found_formset:
|
|
||||||
self.fail(
|
self.fail(
|
||||||
msg_prefix
|
f"{msg_prefix}The formset {formset!r} is not bound, it will never have "
|
||||||
+ "The formset '%s' was not used to render the response" % formset
|
f"any errors."
|
||||||
|
)
|
||||||
|
if form_index is not None and form_index >= formset.total_form_count():
|
||||||
|
form_count = formset.total_form_count()
|
||||||
|
form_or_forms = "forms" if form_count > 1 else "form"
|
||||||
|
self.fail(
|
||||||
|
f"{msg_prefix}The formset {formset!r} only has {form_count} "
|
||||||
|
f"{form_or_forms}."
|
||||||
|
)
|
||||||
|
if form_index is not None:
|
||||||
|
form_repr = f"form {form_index} of formset {formset!r}"
|
||||||
|
self._assert_form_error(
|
||||||
|
formset.forms[form_index], field, errors, msg_prefix, form_repr
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
failure_message = f"The non-form errors of formset {formset!r} don't match."
|
||||||
|
self.assertEqual(
|
||||||
|
formset.non_form_errors(), errors, msg_prefix + failure_message
|
||||||
)
|
)
|
||||||
|
|
||||||
def _get_template_used(self, response, template_name, msg_prefix, method_name):
|
def _get_template_used(self, response, template_name, msg_prefix, method_name):
|
||||||
|
|
|
@ -97,6 +97,10 @@ details on these changes.
|
||||||
* The ``django.utils.timezone.utc`` alias to ``datetime.timezone.utc`` will be
|
* The ``django.utils.timezone.utc`` alias to ``datetime.timezone.utc`` will be
|
||||||
removed.
|
removed.
|
||||||
|
|
||||||
|
* Passing a response object and a form/formset name to
|
||||||
|
``SimpleTestCase.assertFormError()`` and ``assertFormsetError()`` will no
|
||||||
|
longer be allowed.
|
||||||
|
|
||||||
.. _deprecation-removed-in-4.1:
|
.. _deprecation-removed-in-4.1:
|
||||||
|
|
||||||
4.1
|
4.1
|
||||||
|
|
|
@ -327,6 +327,10 @@ Tests
|
||||||
* A nested atomic block marked as durable in :class:`django.test.TestCase` now
|
* A nested atomic block marked as durable in :class:`django.test.TestCase` now
|
||||||
raises a ``RuntimeError``, the same as outside of tests.
|
raises a ``RuntimeError``, the same as outside of tests.
|
||||||
|
|
||||||
|
* :meth:`.SimpleTestCase.assertFormError` and
|
||||||
|
:meth:`~.SimpleTestCase.assertFormsetError` now support passing a
|
||||||
|
form/formset object directly.
|
||||||
|
|
||||||
URLs
|
URLs
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
|
@ -449,6 +453,9 @@ Miscellaneous
|
||||||
|
|
||||||
* The admin log out UI now uses ``POST`` requests.
|
* The admin log out UI now uses ``POST`` requests.
|
||||||
|
|
||||||
|
* The undocumented ``InlineAdminFormSet.non_form_errors`` property is replaced
|
||||||
|
by the ``non_form_errors()`` method. This is consistent with ``BaseFormSet``.
|
||||||
|
|
||||||
.. _deprecated-features-4.1:
|
.. _deprecated-features-4.1:
|
||||||
|
|
||||||
Features deprecated in 4.1
|
Features deprecated in 4.1
|
||||||
|
@ -552,6 +559,15 @@ Miscellaneous
|
||||||
* The :data:`django.utils.timezone.utc` alias to :attr:`datetime.timezone.utc`
|
* The :data:`django.utils.timezone.utc` alias to :attr:`datetime.timezone.utc`
|
||||||
is deprecated. Use :attr:`datetime.timezone.utc` directly.
|
is deprecated. Use :attr:`datetime.timezone.utc` directly.
|
||||||
|
|
||||||
|
* Passing a response object and a form/formset name to
|
||||||
|
``SimpleTestCase.assertFormError()`` and ``assertFormsetError()`` is
|
||||||
|
deprecated. Use::
|
||||||
|
|
||||||
|
assertFormError(response.context['form_name'], …)
|
||||||
|
assertFormsetError(response.context['formset_name'], …)
|
||||||
|
|
||||||
|
or pass the form/formset object directly instead.
|
||||||
|
|
||||||
Features removed in 4.1
|
Features removed in 4.1
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
|
|
|
@ -1473,47 +1473,65 @@ your test suite.
|
||||||
|
|
||||||
self.assertFieldOutput(EmailField, {'a@a.com': 'a@a.com'}, {'aaa': ['Enter a valid email address.']})
|
self.assertFieldOutput(EmailField, {'a@a.com': 'a@a.com'}, {'aaa': ['Enter a valid email address.']})
|
||||||
|
|
||||||
.. method:: SimpleTestCase.assertFormError(response, form, field, errors, msg_prefix='')
|
.. method:: SimpleTestCase.assertFormError(form, field, errors, msg_prefix='')
|
||||||
|
|
||||||
Asserts that a field on a form raises the provided list of errors when
|
Asserts that a field on a form raises the provided list of errors.
|
||||||
rendered on the form.
|
|
||||||
|
|
||||||
``response`` must be a response instance returned by the
|
``form`` is a ``Form`` instance. The form must be
|
||||||
:class:`test client <django.test.Response>`.
|
:ref:`bound <ref-forms-api-bound-unbound>` but not necessarily
|
||||||
|
validated (``assertFormError()`` will automatically call ``full_clean()``
|
||||||
|
on the form).
|
||||||
|
|
||||||
``form`` is the name the ``Form`` instance was given in the template
|
``field`` is the name of the field on the form to check. To check the form's
|
||||||
context of the response.
|
:meth:`non-field errors <django.forms.Form.non_field_errors>`, use
|
||||||
|
``field=None``.
|
||||||
|
|
||||||
``field`` is the name of the field on the form to check. If ``field``
|
``errors`` is a list of all the error strings that the field is expected to
|
||||||
has a value of ``None``, non-field errors (errors you can access via
|
have. You can also pass a single error string if you only expect one error
|
||||||
:meth:`form.non_field_errors() <django.forms.Form.non_field_errors>`) will
|
which means that ``errors='error message'`` is the same as
|
||||||
be checked.
|
``errors=['error message']``.
|
||||||
|
|
||||||
``errors`` is an error string, or a list of error strings, that are
|
.. versionchanged:: 4.1
|
||||||
expected as a result of form validation.
|
|
||||||
|
|
||||||
.. method:: SimpleTestCase.assertFormsetError(response, formset, form_index, field, errors, msg_prefix='')
|
In older versions, using an empty error list with ``assertFormError()``
|
||||||
|
would always pass, regardless of whether the field had any errors or
|
||||||
|
not. Starting from Django 4.1, using ``errors=[]`` will only pass if
|
||||||
|
the field actually has no errors.
|
||||||
|
|
||||||
|
Django 4.1 also changed the behavior of ``assertFormError()`` when a
|
||||||
|
field has multiple errors. In older versions, if a field had multiple
|
||||||
|
errors and you checked for only some of them, the test would pass.
|
||||||
|
Starting from Django 4.1, the error list must be an exact match to the
|
||||||
|
field's actual errors.
|
||||||
|
|
||||||
|
.. deprecated:: 4.1
|
||||||
|
|
||||||
|
Support for passing a response object and a form name to
|
||||||
|
``assertFormError()`` is deprecated and will be removed in Django 5.0.
|
||||||
|
Use the form instance directly instead.
|
||||||
|
|
||||||
|
.. method:: SimpleTestCase.assertFormsetError(formset, form_index, field, errors, msg_prefix='')
|
||||||
|
|
||||||
Asserts that the ``formset`` raises the provided list of errors when
|
Asserts that the ``formset`` raises the provided list of errors when
|
||||||
rendered.
|
rendered.
|
||||||
|
|
||||||
``response`` must be a response instance returned by the
|
``formset`` is a ``Formset`` instance. The formset must be bound but not
|
||||||
:class:`test client <django.test.Response>`.
|
necessarily validated (``assertFormsetError()`` will automatically call the
|
||||||
|
``full_clean()`` on the formset).
|
||||||
|
|
||||||
``formset`` is the name the ``Formset`` instance was given in the template
|
``form_index`` is the number of the form within the ``Formset`` (starting
|
||||||
context of the response.
|
from 0). Use ``form_index=None`` to check the formset's non-form errors,
|
||||||
|
i.e. the errors you get when calling ``formset.non_form_errors()``. In that
|
||||||
|
case you must also use ``field=None``.
|
||||||
|
|
||||||
``form_index`` is the number of the form within the ``Formset``. If
|
``field`` and ``errors`` have the same meaning as the parameters to
|
||||||
``form_index`` has a value of ``None``, non-form errors (errors you can
|
``assertFormError()``.
|
||||||
access via ``formset.non_form_errors()``) will be checked.
|
|
||||||
|
|
||||||
``field`` is the name of the field on the form to check. If ``field``
|
.. deprecated:: 4.1
|
||||||
has a value of ``None``, non-field errors (errors you can access via
|
|
||||||
:meth:`form.non_field_errors() <django.forms.Form.non_field_errors>`) will
|
|
||||||
be checked.
|
|
||||||
|
|
||||||
``errors`` is an error string, or a list of error strings, that are
|
Support for passing a response object and a formset name to
|
||||||
expected as a result of form validation.
|
``assertFormsetError()`` is deprecated and will be removed in Django
|
||||||
|
5.0. Use the formset instance directly instead.
|
||||||
|
|
||||||
.. method:: SimpleTestCase.assertContains(response, text, count=None, status_code=200, msg_prefix='', html=False)
|
.. method:: SimpleTestCase.assertContains(response, text, count=None, status_code=200, msg_prefix='', html=False)
|
||||||
|
|
||||||
|
|
|
@ -2128,7 +2128,9 @@ class AdminViewPermissionsTest(TestCase):
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
login = self.client.post(login_url, self.no_username_login)
|
login = self.client.post(login_url, self.no_username_login)
|
||||||
self.assertEqual(login.status_code, 200)
|
self.assertEqual(login.status_code, 200)
|
||||||
self.assertFormError(login, "form", "username", ["This field is required."])
|
self.assertFormError(
|
||||||
|
login.context["form"], "username", ["This field is required."]
|
||||||
|
)
|
||||||
|
|
||||||
def test_login_redirect_for_direct_get(self):
|
def test_login_redirect_for_direct_get(self):
|
||||||
"""
|
"""
|
||||||
|
@ -6711,10 +6713,9 @@ class UserAdminTest(TestCase):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertFormError(response, "adminform", "password1", [])
|
self.assertFormError(response.context["adminform"], "password1", [])
|
||||||
self.assertFormError(
|
self.assertFormError(
|
||||||
response,
|
response.context["adminform"],
|
||||||
"adminform",
|
|
||||||
"password2",
|
"password2",
|
||||||
["The two password fields didn’t match."],
|
["The two password fields didn’t match."],
|
||||||
)
|
)
|
||||||
|
@ -7836,12 +7837,13 @@ class AdminViewOnSiteTests(TestCase):
|
||||||
reverse("admin:admin_views_parentwithdependentchildren_add"), post_data
|
reverse("admin:admin_views_parentwithdependentchildren_add"), post_data
|
||||||
)
|
)
|
||||||
self.assertFormError(
|
self.assertFormError(
|
||||||
response, "adminform", "some_required_info", ["This field is required."]
|
response.context["adminform"],
|
||||||
|
"some_required_info",
|
||||||
|
["This field is required."],
|
||||||
)
|
)
|
||||||
self.assertFormError(response, "adminform", None, [])
|
self.assertFormError(response.context["adminform"], None, [])
|
||||||
self.assertFormsetError(
|
self.assertFormsetError(
|
||||||
response,
|
response.context["inline_admin_formset"],
|
||||||
"inline_admin_formset",
|
|
||||||
0,
|
0,
|
||||||
None,
|
None,
|
||||||
[
|
[
|
||||||
|
@ -7849,7 +7851,9 @@ class AdminViewOnSiteTests(TestCase):
|
||||||
"contrived test case"
|
"contrived test case"
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
self.assertFormsetError(response, "inline_admin_formset", None, None, [])
|
self.assertFormsetError(
|
||||||
|
response.context["inline_admin_formset"], None, None, []
|
||||||
|
)
|
||||||
|
|
||||||
def test_change_view_form_and_formsets_run_validation(self):
|
def test_change_view_form_and_formsets_run_validation(self):
|
||||||
"""
|
"""
|
||||||
|
@ -7879,11 +7883,12 @@ class AdminViewOnSiteTests(TestCase):
|
||||||
post_data,
|
post_data,
|
||||||
)
|
)
|
||||||
self.assertFormError(
|
self.assertFormError(
|
||||||
response, "adminform", "some_required_info", ["This field is required."]
|
response.context["adminform"],
|
||||||
|
"some_required_info",
|
||||||
|
["This field is required."],
|
||||||
)
|
)
|
||||||
self.assertFormsetError(
|
self.assertFormsetError(
|
||||||
response,
|
response.context["inline_admin_formset"],
|
||||||
"inline_admin_formset",
|
|
||||||
0,
|
0,
|
||||||
None,
|
None,
|
||||||
[
|
[
|
||||||
|
|
|
@ -437,10 +437,10 @@ class ClientTest(TestCase):
|
||||||
response = self.client.post("/form_view/", post_data)
|
response = self.client.post("/form_view/", post_data)
|
||||||
self.assertContains(response, "This field is required.", 3)
|
self.assertContains(response, "This field is required.", 3)
|
||||||
self.assertTemplateUsed(response, "Invalid POST Template")
|
self.assertTemplateUsed(response, "Invalid POST Template")
|
||||||
|
form = response.context["form"]
|
||||||
self.assertFormError(response, "form", "email", "This field is required.")
|
self.assertFormError(form, "email", "This field is required.")
|
||||||
self.assertFormError(response, "form", "single", "This field is required.")
|
self.assertFormError(form, "single", "This field is required.")
|
||||||
self.assertFormError(response, "form", "multi", "This field is required.")
|
self.assertFormError(form, "multi", "This field is required.")
|
||||||
|
|
||||||
def test_form_error(self):
|
def test_form_error(self):
|
||||||
"POST erroneous data to a form"
|
"POST erroneous data to a form"
|
||||||
|
@ -455,7 +455,9 @@ class ClientTest(TestCase):
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertTemplateUsed(response, "Invalid POST Template")
|
self.assertTemplateUsed(response, "Invalid POST Template")
|
||||||
|
|
||||||
self.assertFormError(response, "form", "email", "Enter a valid email address.")
|
self.assertFormError(
|
||||||
|
response.context["form"], "email", "Enter a valid email address."
|
||||||
|
)
|
||||||
|
|
||||||
def test_valid_form_with_template(self):
|
def test_valid_form_with_template(self):
|
||||||
"POST valid data to a form using multiple templates"
|
"POST valid data to a form using multiple templates"
|
||||||
|
@ -480,10 +482,10 @@ class ClientTest(TestCase):
|
||||||
self.assertTemplateUsed(response, "form_view.html")
|
self.assertTemplateUsed(response, "form_view.html")
|
||||||
self.assertTemplateUsed(response, "base.html")
|
self.assertTemplateUsed(response, "base.html")
|
||||||
self.assertTemplateNotUsed(response, "Invalid POST Template")
|
self.assertTemplateNotUsed(response, "Invalid POST Template")
|
||||||
|
form = response.context["form"]
|
||||||
self.assertFormError(response, "form", "email", "This field is required.")
|
self.assertFormError(form, "email", "This field is required.")
|
||||||
self.assertFormError(response, "form", "single", "This field is required.")
|
self.assertFormError(form, "single", "This field is required.")
|
||||||
self.assertFormError(response, "form", "multi", "This field is required.")
|
self.assertFormError(form, "multi", "This field is required.")
|
||||||
|
|
||||||
def test_form_error_with_template(self):
|
def test_form_error_with_template(self):
|
||||||
"POST erroneous data to a form using multiple templates"
|
"POST erroneous data to a form using multiple templates"
|
||||||
|
@ -500,7 +502,9 @@ class ClientTest(TestCase):
|
||||||
self.assertTemplateUsed(response, "base.html")
|
self.assertTemplateUsed(response, "base.html")
|
||||||
self.assertTemplateNotUsed(response, "Invalid POST Template")
|
self.assertTemplateNotUsed(response, "Invalid POST Template")
|
||||||
|
|
||||||
self.assertFormError(response, "form", "email", "Enter a valid email address.")
|
self.assertFormError(
|
||||||
|
response.context["form"], "email", "Enter a valid email address."
|
||||||
|
)
|
||||||
|
|
||||||
def test_unknown_page(self):
|
def test_unknown_page(self):
|
||||||
"GET an invalid URL"
|
"GET an invalid URL"
|
||||||
|
|
|
@ -1373,6 +1373,7 @@ class TestFormset(formset_factory(TestForm)):
|
||||||
|
|
||||||
|
|
||||||
class AssertFormErrorTests(SimpleTestCase):
|
class AssertFormErrorTests(SimpleTestCase):
|
||||||
|
@ignore_warnings(category=RemovedInDjango50Warning)
|
||||||
def test_non_client_response(self):
|
def test_non_client_response(self):
|
||||||
msg = (
|
msg = (
|
||||||
"assertFormError() is only usable on responses fetched using the "
|
"assertFormError() is only usable on responses fetched using the "
|
||||||
|
@ -1380,8 +1381,9 @@ class AssertFormErrorTests(SimpleTestCase):
|
||||||
)
|
)
|
||||||
response = HttpResponse()
|
response = HttpResponse()
|
||||||
with self.assertRaisesMessage(ValueError, msg):
|
with self.assertRaisesMessage(ValueError, msg):
|
||||||
self.assertFormError(response, "formset", 0, "field", "invalid value")
|
self.assertFormError(response, "form", "field", "invalid value")
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango50Warning)
|
||||||
def test_response_with_no_context(self):
|
def test_response_with_no_context(self):
|
||||||
msg = "Response did not use any contexts to render the response"
|
msg = "Response did not use any contexts to render the response"
|
||||||
response = mock.Mock(context=[])
|
response = mock.Mock(context=[])
|
||||||
|
@ -1397,6 +1399,7 @@ class AssertFormErrorTests(SimpleTestCase):
|
||||||
msg_prefix=msg_prefix,
|
msg_prefix=msg_prefix,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango50Warning)
|
||||||
def test_form_not_in_context(self):
|
def test_form_not_in_context(self):
|
||||||
msg = "The form 'form' was not used to render the response"
|
msg = "The form 'form' was not used to render the response"
|
||||||
response = mock.Mock(context=[{}])
|
response = mock.Mock(context=[{}])
|
||||||
|
@ -1408,18 +1411,32 @@ class AssertFormErrorTests(SimpleTestCase):
|
||||||
response, "form", "field", "invalid value", msg_prefix=msg_prefix
|
response, "form", "field", "invalid value", msg_prefix=msg_prefix
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_single_error(self):
|
||||||
|
self.assertFormError(TestForm.invalid(), "field", "invalid value")
|
||||||
|
|
||||||
|
def test_error_list(self):
|
||||||
|
self.assertFormError(TestForm.invalid(), "field", ["invalid value"])
|
||||||
|
|
||||||
|
def test_empty_errors_valid_form(self):
|
||||||
|
self.assertFormError(TestForm.valid(), "field", [])
|
||||||
|
|
||||||
|
def test_empty_errors_valid_form_non_field_errors(self):
|
||||||
|
self.assertFormError(TestForm.valid(), None, [])
|
||||||
|
|
||||||
def test_field_not_in_form(self):
|
def test_field_not_in_form(self):
|
||||||
msg = (
|
msg = (
|
||||||
"The form <TestForm bound=True, valid=False, fields=(field)> does not "
|
"The form <TestForm bound=True, valid=False, fields=(field)> does not "
|
||||||
"contain the field 'other_field'."
|
"contain the field 'other_field'."
|
||||||
)
|
)
|
||||||
response = mock.Mock(context=[{"form": TestForm.invalid()}])
|
|
||||||
with self.assertRaisesMessage(AssertionError, msg):
|
with self.assertRaisesMessage(AssertionError, msg):
|
||||||
self.assertFormError(response, "form", "other_field", "invalid value")
|
self.assertFormError(TestForm.invalid(), "other_field", "invalid value")
|
||||||
msg_prefix = "Custom prefix"
|
msg_prefix = "Custom prefix"
|
||||||
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
||||||
self.assertFormError(
|
self.assertFormError(
|
||||||
response, "form", "other_field", "invalid value", msg_prefix=msg_prefix
|
TestForm.invalid(),
|
||||||
|
"other_field",
|
||||||
|
"invalid value",
|
||||||
|
msg_prefix=msg_prefix,
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_field_with_no_errors(self):
|
def test_field_with_no_errors(self):
|
||||||
|
@ -1427,14 +1444,13 @@ class AssertFormErrorTests(SimpleTestCase):
|
||||||
"The errors of field 'field' on form <TestForm bound=True, valid=True, "
|
"The errors of field 'field' on form <TestForm bound=True, valid=True, "
|
||||||
"fields=(field)> don't match."
|
"fields=(field)> don't match."
|
||||||
)
|
)
|
||||||
response = mock.Mock(context=[{"form": TestForm.valid()}])
|
|
||||||
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
||||||
self.assertFormError(response, "form", "field", "invalid value")
|
self.assertFormError(TestForm.valid(), "field", "invalid value")
|
||||||
self.assertIn("[] != ['invalid value']", str(ctx.exception))
|
self.assertIn("[] != ['invalid value']", str(ctx.exception))
|
||||||
msg_prefix = "Custom prefix"
|
msg_prefix = "Custom prefix"
|
||||||
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
||||||
self.assertFormError(
|
self.assertFormError(
|
||||||
response, "form", "field", "invalid value", msg_prefix=msg_prefix
|
TestForm.valid(), "field", "invalid value", msg_prefix=msg_prefix
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_field_with_different_error(self):
|
def test_field_with_different_error(self):
|
||||||
|
@ -1442,99 +1458,62 @@ class AssertFormErrorTests(SimpleTestCase):
|
||||||
"The errors of field 'field' on form <TestForm bound=True, valid=False, "
|
"The errors of field 'field' on form <TestForm bound=True, valid=False, "
|
||||||
"fields=(field)> don't match."
|
"fields=(field)> don't match."
|
||||||
)
|
)
|
||||||
response = mock.Mock(context=[{"form": TestForm.invalid()}])
|
|
||||||
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
||||||
self.assertFormError(response, "form", "field", "other error")
|
self.assertFormError(TestForm.invalid(), "field", "other error")
|
||||||
self.assertIn("['invalid value'] != ['other error']", str(ctx.exception))
|
self.assertIn("['invalid value'] != ['other error']", str(ctx.exception))
|
||||||
msg_prefix = "Custom prefix"
|
msg_prefix = "Custom prefix"
|
||||||
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
||||||
self.assertFormError(
|
self.assertFormError(
|
||||||
response, "form", "field", "other error", msg_prefix=msg_prefix
|
TestForm.invalid(), "field", "other error", msg_prefix=msg_prefix
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_basic_positive_assertion(self):
|
def test_unbound_form(self):
|
||||||
response = mock.Mock(context=[{"form": TestForm.invalid()}])
|
|
||||||
self.assertFormError(response, "form", "field", "invalid value")
|
|
||||||
|
|
||||||
def test_basic_positive_assertion_multicontext(self):
|
|
||||||
response = mock.Mock(context=[{}, {"form": TestForm.invalid()}])
|
|
||||||
self.assertFormError(response, "form", "field", "invalid value")
|
|
||||||
|
|
||||||
def test_empty_errors_unbound_form(self):
|
|
||||||
msg = (
|
msg = (
|
||||||
"The form <TestForm bound=False, valid=Unknown, fields=(field)> is not "
|
"The form <TestForm bound=False, valid=Unknown, fields=(field)> is not "
|
||||||
"bound, it will never have any errors."
|
"bound, it will never have any errors."
|
||||||
)
|
)
|
||||||
response = mock.Mock(context=[{"form": TestForm()}])
|
|
||||||
with self.assertRaisesMessage(AssertionError, msg):
|
with self.assertRaisesMessage(AssertionError, msg):
|
||||||
self.assertFormError(response, "form", "field", [])
|
self.assertFormError(TestForm(), "field", [])
|
||||||
msg_prefix = "Custom prefix"
|
msg_prefix = "Custom prefix"
|
||||||
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
||||||
self.assertFormError(response, "form", "field", [], msg_prefix=msg_prefix)
|
self.assertFormError(TestForm(), "field", [], msg_prefix=msg_prefix)
|
||||||
|
|
||||||
def test_empty_errors_valid_form(self):
|
|
||||||
response = mock.Mock(context=[{"form": TestForm.valid()}])
|
|
||||||
self.assertFormError(response, "form", "field", [])
|
|
||||||
|
|
||||||
def test_empty_errors_invalid_form(self):
|
def test_empty_errors_invalid_form(self):
|
||||||
msg = (
|
msg = (
|
||||||
"The errors of field 'field' on form <TestForm bound=True, valid=False, "
|
"The errors of field 'field' on form <TestForm bound=True, valid=False, "
|
||||||
"fields=(field)> don't match."
|
"fields=(field)> don't match."
|
||||||
)
|
)
|
||||||
response = mock.Mock(context=[{"form": TestForm.invalid()}])
|
|
||||||
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
||||||
self.assertFormError(response, "form", "field", [])
|
self.assertFormError(TestForm.invalid(), "field", [])
|
||||||
self.assertIn("['invalid value'] != []", str(ctx.exception))
|
self.assertIn("['invalid value'] != []", str(ctx.exception))
|
||||||
|
|
||||||
def test_non_field_errors(self):
|
def test_non_field_errors(self):
|
||||||
response = mock.Mock(context=[{"form": TestForm.invalid(nonfield=True)}])
|
self.assertFormError(TestForm.invalid(nonfield=True), None, "non-field error")
|
||||||
self.assertFormError(response, "form", None, "non-field error")
|
|
||||||
|
|
||||||
def test_different_non_field_errors(self):
|
def test_different_non_field_errors(self):
|
||||||
response = mock.Mock(context=[{"form": TestForm.invalid(nonfield=True)}])
|
|
||||||
msg = (
|
msg = (
|
||||||
"The non-field errors of form <TestForm bound=True, valid=False, "
|
"The non-field errors of form <TestForm bound=True, valid=False, "
|
||||||
"fields=(field)> don't match."
|
"fields=(field)> don't match."
|
||||||
)
|
)
|
||||||
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
||||||
self.assertFormError(response, "form", None, "other non-field error")
|
self.assertFormError(
|
||||||
|
TestForm.invalid(nonfield=True), None, "other non-field error"
|
||||||
|
)
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
"['non-field error'] != ['other non-field error']", str(ctx.exception)
|
"['non-field error'] != ['other non-field error']", str(ctx.exception)
|
||||||
)
|
)
|
||||||
msg_prefix = "Custom prefix"
|
msg_prefix = "Custom prefix"
|
||||||
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
||||||
self.assertFormError(
|
self.assertFormError(
|
||||||
response, "form", None, "other non-field error", msg_prefix=msg_prefix
|
TestForm.invalid(nonfield=True),
|
||||||
|
None,
|
||||||
|
"other non-field error",
|
||||||
|
msg_prefix=msg_prefix,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango50Warning)
|
|
||||||
def test_errors_none(self):
|
|
||||||
msg = (
|
|
||||||
"The errors of field 'field' on form <TestForm bound=True, valid=False, "
|
|
||||||
"fields=(field)> don't match."
|
|
||||||
)
|
|
||||||
response = mock.Mock(context=[{"form": TestForm.invalid()}])
|
|
||||||
with self.assertRaisesMessage(AssertionError, msg):
|
|
||||||
self.assertFormError(response, "form", "field", None)
|
|
||||||
|
|
||||||
def test_errors_none_warning(self):
|
|
||||||
response = mock.Mock(context=[{"form": TestForm.valid()}])
|
|
||||||
msg = (
|
|
||||||
"Passing errors=None to assertFormError() is deprecated, use "
|
|
||||||
"errors=[] instead."
|
|
||||||
)
|
|
||||||
with self.assertWarnsMessage(RemovedInDjango50Warning, msg):
|
|
||||||
self.assertFormError(response, "form", "field", None)
|
|
||||||
|
|
||||||
|
|
||||||
class AssertFormsetErrorTests(SimpleTestCase):
|
class AssertFormsetErrorTests(SimpleTestCase):
|
||||||
def _get_formset_data(self, field_value):
|
@ignore_warnings(category=RemovedInDjango50Warning)
|
||||||
return {
|
|
||||||
"form-TOTAL_FORMS": "1",
|
|
||||||
"form-INITIAL_FORMS": "0",
|
|
||||||
"form-0-field": field_value,
|
|
||||||
}
|
|
||||||
|
|
||||||
def test_non_client_response(self):
|
def test_non_client_response(self):
|
||||||
msg = (
|
msg = (
|
||||||
"assertFormsetError() is only usable on responses fetched using "
|
"assertFormsetError() is only usable on responses fetched using "
|
||||||
|
@ -1544,12 +1523,14 @@ class AssertFormsetErrorTests(SimpleTestCase):
|
||||||
with self.assertRaisesMessage(ValueError, msg):
|
with self.assertRaisesMessage(ValueError, msg):
|
||||||
self.assertFormsetError(response, "formset", 0, "field", "invalid value")
|
self.assertFormsetError(response, "formset", 0, "field", "invalid value")
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango50Warning)
|
||||||
def test_response_with_no_context(self):
|
def test_response_with_no_context(self):
|
||||||
msg = "Response did not use any contexts to render the response"
|
msg = "Response did not use any contexts to render the response"
|
||||||
response = mock.Mock(context=[])
|
response = mock.Mock(context=[])
|
||||||
with self.assertRaisesMessage(AssertionError, msg):
|
with self.assertRaisesMessage(AssertionError, msg):
|
||||||
self.assertFormsetError(response, "formset", 0, "field", "invalid value")
|
self.assertFormsetError(response, "formset", 0, "field", "invalid value")
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango50Warning)
|
||||||
def test_formset_not_in_context(self):
|
def test_formset_not_in_context(self):
|
||||||
msg = "The formset 'formset' was not used to render the response"
|
msg = "The formset 'formset' was not used to render the response"
|
||||||
response = mock.Mock(context=[{}])
|
response = mock.Mock(context=[{}])
|
||||||
|
@ -1561,25 +1542,41 @@ class AssertFormsetErrorTests(SimpleTestCase):
|
||||||
response, "formset", 0, "field", "invalid value", msg_prefix=msg_prefix
|
response, "formset", 0, "field", "invalid value", msg_prefix=msg_prefix
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_single_error(self):
|
||||||
|
self.assertFormsetError(TestFormset.invalid(), 0, "field", "invalid value")
|
||||||
|
|
||||||
|
def test_error_list(self):
|
||||||
|
self.assertFormsetError(TestFormset.invalid(), 0, "field", ["invalid value"])
|
||||||
|
|
||||||
|
def test_empty_errors_valid_formset(self):
|
||||||
|
self.assertFormsetError(TestFormset.valid(), 0, "field", [])
|
||||||
|
|
||||||
|
def test_multiple_forms(self):
|
||||||
|
formset = TestFormset(
|
||||||
|
{
|
||||||
|
"form-TOTAL_FORMS": "2",
|
||||||
|
"form-INITIAL_FORMS": "0",
|
||||||
|
"form-0-field": "valid",
|
||||||
|
"form-1-field": "invalid",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
formset.full_clean()
|
||||||
|
self.assertFormsetError(formset, 0, "field", [])
|
||||||
|
self.assertFormsetError(formset, 1, "field", ["invalid value"])
|
||||||
|
|
||||||
def test_field_not_in_form(self):
|
def test_field_not_in_form(self):
|
||||||
msg = (
|
msg = (
|
||||||
"The form 0 of formset <TestFormset: bound=True valid=False total_forms=1> "
|
"The form 0 of formset <TestFormset: bound=True valid=False total_forms=1> "
|
||||||
"does not contain the field 'other_field'."
|
"does not contain the field 'other_field'."
|
||||||
)
|
)
|
||||||
response = mock.Mock(context=[{"formset": TestFormset.invalid()}])
|
|
||||||
with self.assertRaisesMessage(AssertionError, msg):
|
with self.assertRaisesMessage(AssertionError, msg):
|
||||||
self.assertFormsetError(
|
self.assertFormsetError(
|
||||||
response,
|
TestFormset.invalid(), 0, "other_field", "invalid value"
|
||||||
"formset",
|
|
||||||
0,
|
|
||||||
"other_field",
|
|
||||||
"invalid value",
|
|
||||||
)
|
)
|
||||||
msg_prefix = "Custom prefix"
|
msg_prefix = "Custom prefix"
|
||||||
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
||||||
self.assertFormsetError(
|
self.assertFormsetError(
|
||||||
response,
|
TestFormset.invalid(),
|
||||||
"formset",
|
|
||||||
0,
|
0,
|
||||||
"other_field",
|
"other_field",
|
||||||
"invalid value",
|
"invalid value",
|
||||||
|
@ -1591,14 +1588,13 @@ class AssertFormsetErrorTests(SimpleTestCase):
|
||||||
"The errors of field 'field' on form 0 of formset <TestFormset: bound=True "
|
"The errors of field 'field' on form 0 of formset <TestFormset: bound=True "
|
||||||
"valid=True total_forms=1> don't match."
|
"valid=True total_forms=1> don't match."
|
||||||
)
|
)
|
||||||
response = mock.Mock(context=[{"formset": TestFormset.valid()}])
|
|
||||||
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
||||||
self.assertFormsetError(response, "formset", 0, "field", "invalid value")
|
self.assertFormsetError(TestFormset.valid(), 0, "field", "invalid value")
|
||||||
self.assertIn("[] != ['invalid value']", str(ctx.exception))
|
self.assertIn("[] != ['invalid value']", str(ctx.exception))
|
||||||
msg_prefix = "Custom prefix"
|
msg_prefix = "Custom prefix"
|
||||||
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
||||||
self.assertFormsetError(
|
self.assertFormsetError(
|
||||||
response, "formset", 0, "field", "invalid value", msg_prefix=msg_prefix
|
TestFormset.valid(), 0, "field", "invalid value", msg_prefix=msg_prefix
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_field_with_different_error(self):
|
def test_field_with_different_error(self):
|
||||||
|
@ -1606,67 +1602,45 @@ class AssertFormsetErrorTests(SimpleTestCase):
|
||||||
"The errors of field 'field' on form 0 of formset <TestFormset: bound=True "
|
"The errors of field 'field' on form 0 of formset <TestFormset: bound=True "
|
||||||
"valid=False total_forms=1> don't match."
|
"valid=False total_forms=1> don't match."
|
||||||
)
|
)
|
||||||
response = mock.Mock(context=[{"formset": TestFormset.invalid()}])
|
|
||||||
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
||||||
self.assertFormsetError(response, "formset", 0, "field", "other error")
|
self.assertFormsetError(TestFormset.invalid(), 0, "field", "other error")
|
||||||
self.assertIn("['invalid value'] != ['other error']", str(ctx.exception))
|
self.assertIn("['invalid value'] != ['other error']", str(ctx.exception))
|
||||||
msg_prefix = "Custom prefix"
|
msg_prefix = "Custom prefix"
|
||||||
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
||||||
self.assertFormsetError(
|
self.assertFormsetError(
|
||||||
response, "formset", 0, "field", "other error", msg_prefix=msg_prefix
|
TestFormset.invalid(), 0, "field", "other error", msg_prefix=msg_prefix
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_basic_positive_assertion(self):
|
def test_unbound_formset(self):
|
||||||
response = mock.Mock(context=[{"formset": TestFormset.invalid()}])
|
|
||||||
self.assertFormsetError(response, "formset", 0, "field", "invalid value")
|
|
||||||
|
|
||||||
def test_basic_positive_assertion_multicontext(self):
|
|
||||||
response = mock.Mock(context=[{}, {"formset": TestFormset.invalid()}])
|
|
||||||
self.assertFormsetError(response, "formset", 0, "field", "invalid value")
|
|
||||||
|
|
||||||
def test_empty_errors_unbound_formset(self):
|
|
||||||
msg = (
|
msg = (
|
||||||
"The formset <TestFormset: bound=False valid=Unknown total_forms=1> is not "
|
"The formset <TestFormset: bound=False valid=Unknown total_forms=1> is not "
|
||||||
"bound, it will never have any errors."
|
"bound, it will never have any errors."
|
||||||
)
|
)
|
||||||
response = mock.Mock(context=[{"formset": TestFormset()}])
|
|
||||||
with self.assertRaisesMessage(AssertionError, msg):
|
with self.assertRaisesMessage(AssertionError, msg):
|
||||||
self.assertFormsetError(response, "formset", 0, "field", [])
|
self.assertFormsetError(TestFormset(), 0, "field", [])
|
||||||
|
|
||||||
def test_empty_errors_valid_formset(self):
|
|
||||||
response = mock.Mock(context=[{}, {"formset": TestFormset.valid()}])
|
|
||||||
self.assertFormsetError(response, "formset", 0, "field", [])
|
|
||||||
|
|
||||||
def test_empty_errors_invalid_formset(self):
|
def test_empty_errors_invalid_formset(self):
|
||||||
msg = (
|
msg = (
|
||||||
"The errors of field 'field' on form 0 of formset <TestFormset: bound=True "
|
"The errors of field 'field' on form 0 of formset <TestFormset: bound=True "
|
||||||
"valid=False total_forms=1> don't match."
|
"valid=False total_forms=1> don't match."
|
||||||
)
|
)
|
||||||
response = mock.Mock(context=[{}, {"formset": TestFormset.invalid()}])
|
|
||||||
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
||||||
self.assertFormsetError(response, "formset", 0, "field", [])
|
self.assertFormsetError(TestFormset.invalid(), 0, "field", [])
|
||||||
self.assertIn("['invalid value'] != []", str(ctx.exception))
|
self.assertIn("['invalid value'] != []", str(ctx.exception))
|
||||||
|
|
||||||
def test_non_field_errors(self):
|
def test_non_field_errors(self):
|
||||||
response = mock.Mock(
|
self.assertFormsetError(
|
||||||
context=[
|
TestFormset.invalid(nonfield=True), 0, None, "non-field error"
|
||||||
{},
|
|
||||||
{"formset": TestFormset.invalid(nonfield=True)},
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
self.assertFormsetError(response, "formset", 0, None, "non-field error")
|
|
||||||
|
|
||||||
def test_different_non_field_errors(self):
|
def test_different_non_field_errors(self):
|
||||||
response = mock.Mock(
|
|
||||||
context=[{}, {"formset": TestFormset.invalid(nonfield=True)}],
|
|
||||||
)
|
|
||||||
msg = (
|
msg = (
|
||||||
"The non-field errors of form 0 of formset <TestFormset: bound=True "
|
"The non-field errors of form 0 of formset <TestFormset: bound=True "
|
||||||
"valid=False total_forms=1> don't match."
|
"valid=False total_forms=1> don't match."
|
||||||
)
|
)
|
||||||
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
||||||
self.assertFormsetError(
|
self.assertFormsetError(
|
||||||
response, "formset", 0, None, "other non-field error"
|
TestFormset.invalid(nonfield=True), 0, None, "other non-field error"
|
||||||
)
|
)
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
"['non-field error'] != ['other non-field error']", str(ctx.exception)
|
"['non-field error'] != ['other non-field error']", str(ctx.exception)
|
||||||
|
@ -1674,8 +1648,7 @@ class AssertFormsetErrorTests(SimpleTestCase):
|
||||||
msg_prefix = "Custom prefix"
|
msg_prefix = "Custom prefix"
|
||||||
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
||||||
self.assertFormsetError(
|
self.assertFormsetError(
|
||||||
response,
|
TestFormset.invalid(nonfield=True),
|
||||||
"formset",
|
|
||||||
0,
|
0,
|
||||||
None,
|
None,
|
||||||
"other non-field error",
|
"other non-field error",
|
||||||
|
@ -1683,80 +1656,74 @@ class AssertFormsetErrorTests(SimpleTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_no_non_field_errors(self):
|
def test_no_non_field_errors(self):
|
||||||
response = mock.Mock(context=[{}, {"formset": TestFormset.invalid()}])
|
|
||||||
msg = (
|
msg = (
|
||||||
"The non-field errors of form 0 of formset <TestFormset: bound=True "
|
"The non-field errors of form 0 of formset <TestFormset: bound=True "
|
||||||
"valid=False total_forms=1> don't match."
|
"valid=False total_forms=1> don't match."
|
||||||
)
|
)
|
||||||
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
||||||
self.assertFormsetError(response, "formset", 0, None, "non-field error")
|
self.assertFormsetError(TestFormset.invalid(), 0, None, "non-field error")
|
||||||
self.assertIn("[] != ['non-field error']", str(ctx.exception))
|
self.assertIn("[] != ['non-field error']", str(ctx.exception))
|
||||||
msg_prefix = "Custom prefix"
|
msg_prefix = "Custom prefix"
|
||||||
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
||||||
self.assertFormsetError(
|
self.assertFormsetError(
|
||||||
response, "formset", 0, None, "non-field error", msg_prefix=msg_prefix
|
TestFormset.invalid(), 0, None, "non-field error", msg_prefix=msg_prefix
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_non_form_errors(self):
|
def test_non_form_errors(self):
|
||||||
response = mock.Mock(
|
self.assertFormsetError(TestFormset.invalid(nonform=True), None, None, "error")
|
||||||
context=[
|
|
||||||
{},
|
|
||||||
{"formset": TestFormset.invalid(nonform=True)},
|
|
||||||
]
|
|
||||||
)
|
|
||||||
self.assertFormsetError(response, "formset", None, None, "error")
|
|
||||||
|
|
||||||
def test_different_non_form_errors(self):
|
def test_different_non_form_errors(self):
|
||||||
response = mock.Mock(
|
|
||||||
context=[{}, {"formset": TestFormset.invalid(nonform=True)}],
|
|
||||||
)
|
|
||||||
msg = (
|
msg = (
|
||||||
"The non-form errors of formset <TestFormset: bound=True valid=False "
|
"The non-form errors of formset <TestFormset: bound=True valid=False "
|
||||||
"total_forms=0> don't match."
|
"total_forms=0> don't match."
|
||||||
)
|
)
|
||||||
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
||||||
self.assertFormsetError(response, "formset", None, None, "other error")
|
self.assertFormsetError(
|
||||||
|
TestFormset.invalid(nonform=True), None, None, "other error"
|
||||||
|
)
|
||||||
self.assertIn("['error'] != ['other error']", str(ctx.exception))
|
self.assertIn("['error'] != ['other error']", str(ctx.exception))
|
||||||
msg_prefix = "Custom prefix"
|
msg_prefix = "Custom prefix"
|
||||||
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
||||||
self.assertFormsetError(
|
self.assertFormsetError(
|
||||||
response, "formset", None, None, "other error", msg_prefix=msg_prefix
|
TestFormset.invalid(nonform=True),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
"other error",
|
||||||
|
msg_prefix=msg_prefix,
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_no_non_form_errors(self):
|
def test_no_non_form_errors(self):
|
||||||
response = mock.Mock(context=[{}, {"formset": TestFormset.invalid()}])
|
|
||||||
msg = (
|
msg = (
|
||||||
"The non-form errors of formset <TestFormset: bound=True valid=False "
|
"The non-form errors of formset <TestFormset: bound=True valid=False "
|
||||||
"total_forms=1> don't match."
|
"total_forms=1> don't match."
|
||||||
)
|
)
|
||||||
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
with self.assertRaisesMessage(AssertionError, msg) as ctx:
|
||||||
self.assertFormsetError(response, "formset", None, None, "error")
|
self.assertFormsetError(TestFormset.invalid(), None, None, "error")
|
||||||
self.assertIn("[] != ['error']", str(ctx.exception))
|
self.assertIn("[] != ['error']", str(ctx.exception))
|
||||||
msg_prefix = "Custom prefix"
|
msg_prefix = "Custom prefix"
|
||||||
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
|
||||||
self.assertFormsetError(
|
self.assertFormsetError(
|
||||||
response, "formset", None, None, "error", msg_prefix=msg_prefix
|
TestFormset.invalid(),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
"error",
|
||||||
|
msg_prefix=msg_prefix,
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_non_form_errors_with_field(self):
|
def test_non_form_errors_with_field(self):
|
||||||
response = mock.Mock(
|
|
||||||
context=[
|
|
||||||
{},
|
|
||||||
{"formset": TestFormset.invalid(nonform=True)},
|
|
||||||
]
|
|
||||||
)
|
|
||||||
msg = "You must use field=None with form_index=None."
|
msg = "You must use field=None with form_index=None."
|
||||||
with self.assertRaisesMessage(ValueError, msg):
|
with self.assertRaisesMessage(ValueError, msg):
|
||||||
self.assertFormsetError(response, "formset", None, "field", "error")
|
self.assertFormsetError(
|
||||||
|
TestFormset.invalid(nonform=True), None, "field", "error"
|
||||||
|
)
|
||||||
|
|
||||||
def test_form_index_too_big(self):
|
def test_form_index_too_big(self):
|
||||||
msg = (
|
msg = (
|
||||||
"The formset <TestFormset: bound=True valid=False total_forms=1> only has "
|
"The formset <TestFormset: bound=True valid=False total_forms=1> only has "
|
||||||
"1 form."
|
"1 form."
|
||||||
)
|
)
|
||||||
response = mock.Mock(context=[{}, {"formset": TestFormset.invalid()}])
|
|
||||||
with self.assertRaisesMessage(AssertionError, msg):
|
with self.assertRaisesMessage(AssertionError, msg):
|
||||||
self.assertFormsetError(response, "formset", 2, "field", "error")
|
self.assertFormsetError(TestFormset.invalid(), 2, "field", "error")
|
||||||
|
|
||||||
def test_form_index_too_big_plural(self):
|
def test_form_index_too_big_plural(self):
|
||||||
formset = TestFormset(
|
formset = TestFormset(
|
||||||
|
@ -1772,40 +1739,221 @@ class AssertFormsetErrorTests(SimpleTestCase):
|
||||||
"The formset <TestFormset: bound=True valid=True total_forms=2> only has 2 "
|
"The formset <TestFormset: bound=True valid=True total_forms=2> only has 2 "
|
||||||
"forms."
|
"forms."
|
||||||
)
|
)
|
||||||
response = mock.Mock(context=[{}, {"formset": formset}])
|
|
||||||
with self.assertRaisesMessage(AssertionError, msg):
|
with self.assertRaisesMessage(AssertionError, msg):
|
||||||
self.assertFormsetError(response, "formset", 2, "field", "error")
|
self.assertFormsetError(formset, 2, "field", "error")
|
||||||
|
|
||||||
def test_formset_named_form(self):
|
|
||||||
formset = TestFormset.invalid()
|
# RemovedInDjango50Warning
|
||||||
# The mocked context emulates the template-based rendering of the
|
class AssertFormErrorDeprecationTests(SimpleTestCase):
|
||||||
# formset.
|
"""
|
||||||
response = mock.Mock(
|
Exhaustively test all possible combinations of args/kwargs for the old
|
||||||
context=[
|
signature.
|
||||||
{"form": formset},
|
"""
|
||||||
{"form": formset.management_form},
|
|
||||||
]
|
|
||||||
)
|
|
||||||
self.assertFormsetError(response, "form", 0, "field", "invalid value")
|
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango50Warning)
|
@ignore_warnings(category=RemovedInDjango50Warning)
|
||||||
def test_errors_none(self):
|
def test_assert_form_error_errors_none(self):
|
||||||
|
msg = (
|
||||||
|
"The errors of field 'field' on form <TestForm bound=True, valid=False, "
|
||||||
|
"fields=(field)> don't match."
|
||||||
|
)
|
||||||
|
with self.assertRaisesMessage(AssertionError, msg):
|
||||||
|
self.assertFormError(TestForm.invalid(), "field", None)
|
||||||
|
|
||||||
|
def test_assert_form_error_errors_none_warning(self):
|
||||||
|
msg = (
|
||||||
|
"Passing errors=None to assertFormError() is deprecated, use "
|
||||||
|
"errors=[] instead."
|
||||||
|
)
|
||||||
|
with self.assertWarnsMessage(RemovedInDjango50Warning, msg):
|
||||||
|
self.assertFormError(TestForm.valid(), "field", None)
|
||||||
|
|
||||||
|
def _assert_form_error_old_api_cases(self, form, field, errors, msg_prefix):
|
||||||
|
response = mock.Mock(context=[{"form": TestForm.invalid()}])
|
||||||
|
return (
|
||||||
|
((response, form, field, errors), {}),
|
||||||
|
((response, form, field, errors, msg_prefix), {}),
|
||||||
|
((response, form, field, errors), {"msg_prefix": msg_prefix}),
|
||||||
|
((response, form, field), {"errors": errors}),
|
||||||
|
((response, form, field), {"errors": errors, "msg_prefix": msg_prefix}),
|
||||||
|
((response, form), {"field": field, "errors": errors}),
|
||||||
|
(
|
||||||
|
(response, form),
|
||||||
|
{"field": field, "errors": errors, "msg_prefix": msg_prefix},
|
||||||
|
),
|
||||||
|
((response,), {"form": form, "field": field, "errors": errors}),
|
||||||
|
(
|
||||||
|
(response,),
|
||||||
|
{
|
||||||
|
"form": form,
|
||||||
|
"field": field,
|
||||||
|
"errors": errors,
|
||||||
|
"msg_prefix": msg_prefix,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
(),
|
||||||
|
{"response": response, "form": form, "field": field, "errors": errors},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
(),
|
||||||
|
{
|
||||||
|
"response": response,
|
||||||
|
"form": form,
|
||||||
|
"field": field,
|
||||||
|
"errors": errors,
|
||||||
|
"msg_prefix": msg_prefix,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_assert_form_error_old_api(self):
|
||||||
|
deprecation_msg = (
|
||||||
|
"Passing response to assertFormError() is deprecated. Use the form object "
|
||||||
|
"directly: assertFormError(response.context['form'], 'field', ...)"
|
||||||
|
)
|
||||||
|
for args, kwargs in self._assert_form_error_old_api_cases(
|
||||||
|
form="form",
|
||||||
|
field="field",
|
||||||
|
errors=["invalid value"],
|
||||||
|
msg_prefix="Custom prefix",
|
||||||
|
):
|
||||||
|
with self.subTest(args=args, kwargs=kwargs):
|
||||||
|
with self.assertWarnsMessage(RemovedInDjango50Warning, deprecation_msg):
|
||||||
|
self.assertFormError(*args, **kwargs)
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango50Warning)
|
||||||
|
def test_assert_form_error_old_api_assertion_error(self):
|
||||||
|
for args, kwargs in self._assert_form_error_old_api_cases(
|
||||||
|
form="form",
|
||||||
|
field="field",
|
||||||
|
errors=["other error"],
|
||||||
|
msg_prefix="Custom prefix",
|
||||||
|
):
|
||||||
|
with self.subTest(args=args, kwargs=kwargs):
|
||||||
|
with self.assertRaises(AssertionError):
|
||||||
|
self.assertFormError(*args, **kwargs)
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango50Warning)
|
||||||
|
def test_assert_formset_error_errors_none(self):
|
||||||
msg = (
|
msg = (
|
||||||
"The errors of field 'field' on form 0 of formset <TestFormset: bound=True "
|
"The errors of field 'field' on form 0 of formset <TestFormset: bound=True "
|
||||||
"valid=False total_forms=1> don't match."
|
"valid=False total_forms=1> don't match."
|
||||||
)
|
)
|
||||||
response = mock.Mock(context=[{"formset": TestFormset.invalid()}])
|
|
||||||
with self.assertRaisesMessage(AssertionError, msg):
|
with self.assertRaisesMessage(AssertionError, msg):
|
||||||
self.assertFormsetError(response, "formset", 0, "field", None)
|
self.assertFormsetError(TestFormset.invalid(), 0, "field", None)
|
||||||
|
|
||||||
def test_errors_none_warning(self):
|
def test_assert_formset_error_errors_none_warning(self):
|
||||||
response = mock.Mock(context=[{"formset": TestFormset.valid()}])
|
|
||||||
msg = (
|
msg = (
|
||||||
"Passing errors=None to assertFormsetError() is deprecated, use "
|
"Passing errors=None to assertFormsetError() is deprecated, use "
|
||||||
"errors=[] instead."
|
"errors=[] instead."
|
||||||
)
|
)
|
||||||
with self.assertWarnsMessage(RemovedInDjango50Warning, msg):
|
with self.assertWarnsMessage(RemovedInDjango50Warning, msg):
|
||||||
self.assertFormsetError(response, "formset", 0, "field", None)
|
self.assertFormsetError(TestFormset.valid(), 0, "field", None)
|
||||||
|
|
||||||
|
def _assert_formset_error_old_api_cases(
|
||||||
|
self, formset, form_index, field, errors, msg_prefix
|
||||||
|
):
|
||||||
|
response = mock.Mock(context=[{"formset": TestFormset.invalid()}])
|
||||||
|
return (
|
||||||
|
((response, formset, form_index, field, errors), {}),
|
||||||
|
((response, formset, form_index, field, errors, msg_prefix), {}),
|
||||||
|
(
|
||||||
|
(response, formset, form_index, field, errors),
|
||||||
|
{"msg_prefix": msg_prefix},
|
||||||
|
),
|
||||||
|
((response, formset, form_index, field), {"errors": errors}),
|
||||||
|
(
|
||||||
|
(response, formset, form_index, field),
|
||||||
|
{"errors": errors, "msg_prefix": msg_prefix},
|
||||||
|
),
|
||||||
|
((response, formset, form_index), {"field": field, "errors": errors}),
|
||||||
|
(
|
||||||
|
(response, formset, form_index),
|
||||||
|
{"field": field, "errors": errors, "msg_prefix": msg_prefix},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
(response, formset),
|
||||||
|
{"form_index": form_index, "field": field, "errors": errors},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
(response, formset),
|
||||||
|
{
|
||||||
|
"form_index": form_index,
|
||||||
|
"field": field,
|
||||||
|
"errors": errors,
|
||||||
|
"msg_prefix": msg_prefix,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
(response,),
|
||||||
|
{
|
||||||
|
"formset": formset,
|
||||||
|
"form_index": form_index,
|
||||||
|
"field": field,
|
||||||
|
"errors": errors,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
(response,),
|
||||||
|
{
|
||||||
|
"formset": formset,
|
||||||
|
"form_index": form_index,
|
||||||
|
"field": field,
|
||||||
|
"errors": errors,
|
||||||
|
"msg_prefix": msg_prefix,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
(),
|
||||||
|
{
|
||||||
|
"response": response,
|
||||||
|
"formset": formset,
|
||||||
|
"form_index": form_index,
|
||||||
|
"field": field,
|
||||||
|
"errors": errors,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
(),
|
||||||
|
{
|
||||||
|
"response": response,
|
||||||
|
"formset": formset,
|
||||||
|
"form_index": form_index,
|
||||||
|
"field": field,
|
||||||
|
"errors": errors,
|
||||||
|
"msg_prefix": msg_prefix,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_assert_formset_error_old_api(self):
|
||||||
|
deprecation_msg = (
|
||||||
|
"Passing response to assertFormsetError() is deprecated. Use the formset "
|
||||||
|
"object directly: assertFormsetError(response.context['formset'], 0, ...)"
|
||||||
|
)
|
||||||
|
for args, kwargs in self._assert_formset_error_old_api_cases(
|
||||||
|
formset="formset",
|
||||||
|
form_index=0,
|
||||||
|
field="field",
|
||||||
|
errors=["invalid value"],
|
||||||
|
msg_prefix="Custom prefix",
|
||||||
|
):
|
||||||
|
with self.subTest(args=args, kwargs=kwargs):
|
||||||
|
with self.assertWarnsMessage(RemovedInDjango50Warning, deprecation_msg):
|
||||||
|
self.assertFormsetError(*args, **kwargs)
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango50Warning)
|
||||||
|
def test_assert_formset_error_old_api_assertion_error(self):
|
||||||
|
for args, kwargs in self._assert_formset_error_old_api_cases(
|
||||||
|
formset="formset",
|
||||||
|
form_index=0,
|
||||||
|
field="field",
|
||||||
|
errors=["other error"],
|
||||||
|
msg_prefix="Custom prefix",
|
||||||
|
):
|
||||||
|
with self.subTest(args=args, kwargs=kwargs):
|
||||||
|
with self.assertRaises(AssertionError):
|
||||||
|
self.assertFormsetError(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class FirstUrls:
|
class FirstUrls:
|
||||||
|
|
Loading…
Reference in New Issue