Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Introduced an own base test case to re-implement a few things added i…

…n newer Django versions.
  • Loading branch information...
commit 0d7dbfecfcb536380e7339920a0cfa98569a618e 1 parent 60e5564
@jezdez jezdez authored
View
63 floppyforms/templatetags/floppyforms.py
@@ -1,12 +1,13 @@
+from __future__ import with_statement
+import re
from collections import defaultdict
from contextlib import contextmanager
from django.conf import settings
from django.forms.forms import BoundField
from django.forms.util import ErrorList
-from django.template.base import (Library, Node, Variable,
- TemplateSyntaxError, VariableDoesNotExist)
-from django.template.defaulttags import token_kwargs
+from django.template import (Library, Node, Variable,
+ TemplateSyntaxError, VariableDoesNotExist)
from django.template.loader import get_template
try:
@@ -14,6 +15,62 @@
except ImportError:
empty = None # noqa
+try:
+ from django.template.base import token_kwargs
+except ImportError:
+ # Regex for token keyword arguments
+ kwarg_re = re.compile(r"(?:(\w+)=)?(.+)")
+
+ def token_kwargs(bits, parser, support_legacy=False):
+ """
+ A utility method for parsing token keyword arguments.
+
+ :param bits: A list containing remainder of the token (split by spaces)
+ that is to be checked for arguments. Valid arguments will be removed
+ from this list.
+
+ :param support_legacy: If set to true ``True``, the legacy format
+ ``1 as foo`` will be accepted. Otherwise, only the standard ``foo=1``
+ format is allowed.
+
+ :returns: A dictionary of the arguments retrieved from the ``bits`` token
+ list.
+
+ There is no requirement for all remaining token ``bits`` to be keyword
+ arguments, so the dictionary will be returned as soon as an invalid
+ argument format is reached.
+ """
+ if not bits:
+ return {}
+ match = kwarg_re.match(bits[0])
+ kwarg_format = match and match.group(1)
+ if not kwarg_format:
+ if not support_legacy:
+ return {}
+ if len(bits) < 3 or bits[1] != 'as':
+ return {}
+
+ kwargs = {}
+ while bits:
+ if kwarg_format:
+ match = kwarg_re.match(bits[0])
+ if not match or not match.group(1):
+ return kwargs
+ key, value = match.groups()
+ del bits[:1]
+ else:
+ if len(bits) < 3 or bits[1] != 'as':
+ return kwargs
+ key, value = bits[2], bits[0]
+ del bits[:3]
+ kwargs[key] = parser.compile_filter(value)
+ if bits and not kwarg_format:
+ if bits[0] != 'and':
+ return kwargs
+ del bits[:1]
+ return kwargs
+
+
register = Library()
View
116 floppyforms/tests/base.py
@@ -0,0 +1,116 @@
+from copy import copy
+
+import django
+from django.test import TestCase
+from django.test.signals import template_rendered
+from django.test.utils import ContextList
+
+
+class _AssertTemplateUsedContext(object):
+ def __init__(self, test_case, template_name):
+ self.test_case = test_case
+ self.template_name = template_name
+ self.rendered_templates = []
+ self.rendered_template_names = []
+ self.context = ContextList()
+
+ def on_template_render(self, sender, signal, template, context, **kwargs):
+ self.rendered_templates.append(template)
+ self.rendered_template_names.append(template.name)
+ self.context.append(copy(context))
+
+ def test(self):
+ return self.template_name in self.rendered_template_names
+
+ def message(self):
+ return u'%s was not rendered.' % self.template_name
+
+ def __enter__(self):
+ template_rendered.connect(self.on_template_render)
+ return self
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ template_rendered.disconnect(self.on_template_render)
+ if exc_type is not None:
+ return
+
+ if not self.test():
+ message = self.message()
+ if len(self.rendered_templates) == 0:
+ message += u' No template was rendered.'
+ else:
+ message += u' Following templates were rendered: %s' % (
+ ', '.join(self.rendered_template_names))
+ self.test_case.fail(message)
+
+
+class _AssertTemplateNotUsedContext(_AssertTemplateUsedContext):
+ def test(self):
+ return self.template_name not in self.rendered_template_names
+
+ def message(self):
+ return u'%s was rendered.' % self.template_name
+
+
+class TemplatesTestCase(object):
+ def assertTemplateUsed(self, response=None, template_name=None, msg_prefix=''):
+ """
+ Asserts that the template with the provided name was used in rendering
+ the response. Also usable as context manager.
+ """
+ if response is None and template_name is None:
+ raise TypeError(u'response and/or template_name argument must be provided')
+
+ if msg_prefix:
+ msg_prefix += ": "
+
+ # Use assertTemplateUsed as context manager.
+ if not hasattr(response, 'templates') or (response is None and template_name):
+ if response:
+ template_name = response
+ response = None
+ context = _AssertTemplateUsedContext(self, template_name)
+ return context
+
+ template_names = [t.name for t in response.templates]
+ if not template_names:
+ self.fail(msg_prefix + "No templates used to render the response")
+ self.assertTrue(template_name in template_names,
+ msg_prefix + "Template '%s' was not a template used to render"
+ " the response. Actual template(s) used: %s" %
+ (template_name, u', '.join(template_names)))
+
+ def assertTemplateNotUsed(self, response=None, template_name=None, msg_prefix=''):
+ """
+ Asserts that the template with the provided name was NOT used in
+ rendering the response. Also usable as context manager.
+ """
+ if response is None and template_name is None:
+ raise TypeError(u'response and/or template_name argument must be provided')
+
+ if msg_prefix:
+ msg_prefix += ": "
+
+ # Use assertTemplateUsed as context manager.
+ if not hasattr(response, 'templates') or (response is None and template_name):
+ if response:
+ template_name = response
+ response = None
+ context = _AssertTemplateNotUsedContext(self, template_name)
+ return context
+
+ template_names = [t.name for t in response.templates]
+ self.assertFalse(template_name in template_names,
+ msg_prefix + "Template '%s' was used unexpectedly in rendering"
+ " the response" % template_name)
+
+
+if django.VERSION[:2] < (1, 4):
+ from django_tools.unittest_utils.unittest_base import BaseTestCase
+
+ class FloppyFormsTestCase(TemplatesTestCase, BaseTestCase, TestCase):
+ pass
+
+else:
+ class FloppyFormsTestCase(TemplatesTestCase, TestCase):
+ pass
View
9 floppyforms/tests/layouts.py
@@ -1,9 +1,10 @@
+from __future__ import with_statement
from django.core.exceptions import ValidationError
from django.template import Context, Template
-from django.test import TestCase
from django.utils.translation import ugettext_lazy as _
import floppyforms as forms
+from .base import FloppyFormsTestCase
def render(template, context=None):
@@ -42,7 +43,7 @@ def clean(self):
raise ValidationError(u'Please correct the errors below.')
-class PLayoutTests(TestCase):
+class PLayoutTests(FloppyFormsTestCase):
def test_default_layout_is_same_as_p_layout(self):
form = RegistrationForm()
default = render('{% form form %}', {'form': form})
@@ -144,7 +145,7 @@ def test_layout_with_custom_help_text(self):
""")
-class TableLayoutTests(TestCase):
+class TableLayoutTests(FloppyFormsTestCase):
def test_layout(self):
form = RegistrationForm()
with self.assertTemplateUsed('floppyforms/layouts/table.html'):
@@ -229,7 +230,7 @@ def test_layout_with_custom_help_text(self):
""")
-class UlLayoutTests(TestCase):
+class UlLayoutTests(FloppyFormsTestCase):
def test_layout(self):
form = RegistrationForm()
with self.assertTemplateUsed('floppyforms/layouts/ul.html'):
View
6 floppyforms/tests/rendering.py
@@ -1,9 +1,9 @@
-from django.test import TestCase
-
import floppyforms as forms
from floppyforms import widgets
from floppyforms.templatetags.floppyforms import ConfigFilter, FormConfig
+from .base import FloppyFormsTestCase
+
class AgeField(forms.IntegerField):
pass
@@ -18,7 +18,7 @@ class RegistrationForm(forms.Form):
comment = forms.CharField(widget=widgets.Textarea)
-class FormConfigTests(TestCase):
+class FormConfigTests(FloppyFormsTestCase):
def test_default_retrieve(self):
"""
Test if FormConfig returns the correct default values if no
View
11 floppyforms/tests/templatetags.py
@@ -1,9 +1,10 @@
+from __future__ import with_statement
from django.template import Context, Template, TemplateSyntaxError
-from django.test import TestCase
import floppyforms as forms
from floppyforms.templatetags.floppyforms import (FormConfig, ConfigFilter,
FormNode, RowModifier, FieldModifier)
+from .base import FloppyFormsTestCase
def render(template, context=None, config=None):
@@ -39,7 +40,7 @@ class PersonForm(forms.Form):
age = forms.IntegerField()
-class FormConfigNodeTests(TestCase):
+class FormConfigNodeTests(FloppyFormsTestCase):
def test_enforce_form_tag(self):
render('{% form myform using %}{% formconfig row using "my_row_template.html" %}{% endform %}')
with self.assertRaises(TemplateSyntaxError):
@@ -213,7 +214,7 @@ def test_field_config_for_field_type(self):
'field.html')
-class FormTagTests(TestCase):
+class FormTagTests(FloppyFormsTestCase):
def test_valid_syntax(self):
render('{% form myform %}')
render('{% form myform using "myform_layout.html" %}')
@@ -382,7 +383,7 @@ def test_form_list_as_argument(self):
""")
-class FormRowTagTests(TestCase):
+class FormRowTagTests(FloppyFormsTestCase):
def test_valid_syntax(self):
render('{% formrow myform.field %}')
render('{% formrow myform.field using "myrow_layout.html" %}')
@@ -539,7 +540,7 @@ def test_field_list_as_argument(self):
""")
-class FormFieldTagTests(TestCase):
+class FormFieldTagTests(FloppyFormsTestCase):
def test_valid_syntax(self):
render('{% formfield myform.name %}')
View
10 floppyforms/tests/tests.py
@@ -1,5 +1,5 @@
-from .gis import GisTests
-from .layouts import *
-from .rendering import *
-from .templatetags import *
-from .widgets import *
+from floppyforms.tests.gis import GisTests
+from floppyforms.tests.layouts import *
+from floppyforms.tests.rendering import *
+from floppyforms.tests.templatetags import *
+from floppyforms.tests.widgets import *
View
32 tox.ini
@@ -1,9 +1,9 @@
[tox]
envlist =
- py25-1.2, py25-1.3,
- py26-1.2, py26-1.3, py26-trunk,
- py27-1.2, py27-1.3, py27-trunk,
- pypy-1.2, pypy-1.3, pypy-trunk,
+ py25-1.3,
+ py26-1.3, py26-trunk,
+ py27-1.3, py27-trunk,
+ pypy-1.3, pypy-trunk,
docs
[testenv]
@@ -16,55 +16,39 @@ deps =
commands =
sphinx-build -W -b html -d {envtmpdir}/doctrees . {envtmpdir}/html
-[testenv:py25-1.2]
-basepython = python2.5
-deps =
- Django==1.2.7
-
[testenv:py25-1.3]
basepython = python2.5
deps =
Django==1.3.1
-
-[testenv:py26-1.2]
-basepython = python2.6
-deps =
- Django==1.2.7
+ django-tools
[testenv:py26-1.3]
basepython = python2.6
deps =
Django==1.3.1
+ django-tools
[testenv:py26-trunk]
basepython = python2.6
deps =
https://github.com/django/django/tarball/master#egg=Django
-[testenv:py27-1.2]
-basepython = python2.7
-deps =
- Django==1.2.7
-
[testenv:py27-1.3]
basepython = python2.7
deps =
Django==1.3.1
+ django-tools
[testenv:py27-trunk]
basepython = python2.7
deps =
https://github.com/django/django/tarball/master#egg=Django
-[testenv:pypy-1.2]
-basepython = pypy
-deps =
- Django==1.2.7
-
[testenv:pypy-1.3]
basepython = pypy
deps =
Django==1.3.1
+ django-tools
[testenv:pypy-trunk]
basepython = pypy
Please sign in to comment.
Something went wrong with that request. Please try again.