Skip to content

Commit

Permalink
Introduced an own base test case to re-implement a few things added i…
Browse files Browse the repository at this point in the history
…n newer Django versions.
  • Loading branch information
jezdez committed Mar 3, 2012
1 parent 60e5564 commit 0d7dbfe
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 44 deletions.
63 changes: 60 additions & 3 deletions floppyforms/templatetags/floppyforms.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,76 @@
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:
from django.utils.functional import empty
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()


Expand Down
116 changes: 116 additions & 0 deletions floppyforms/tests/base.py
Original file line number Diff line number Diff line change
@@ -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
9 changes: 5 additions & 4 deletions floppyforms/tests/layouts.py
Original file line number Diff line number Diff line change
@@ -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):
Expand Down Expand Up @@ -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})
Expand Down Expand Up @@ -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'):
Expand Down Expand Up @@ -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'):
Expand Down
6 changes: 3 additions & 3 deletions floppyforms/tests/rendering.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down
11 changes: 6 additions & 5 deletions floppyforms/tests/templatetags.py
Original file line number Diff line number Diff line change
@@ -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):
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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" %}')
Expand Down Expand Up @@ -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" %}')
Expand Down Expand Up @@ -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 %}')

Expand Down
10 changes: 5 additions & 5 deletions floppyforms/tests/tests.py
Original file line number Diff line number Diff line change
@@ -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 *
32 changes: 8 additions & 24 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -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]
Expand All @@ -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
Expand Down

0 comments on commit 0d7dbfe

Please sign in to comment.