This question is similar to Testing a custom Django template filter, but unlike in that example, the filter is actually defined in a module in the templatetags
directory as described in https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/#writing-custom-template-filters. Here is the filter code in templatetags/label_with_classes.py
:
from django import template
register = template.Library()
@register.filter(is_safe=True)
def label_with_classes(bound_field):
classes = f"{'active' if bound_field.value() else ''} {'invalid' if bound_field.errors else ''}"
return bound_field.label_tag(attrs={'class': classes})
Here is my first stab at a test for it:
from ..templatetags.label_with_classes import label_with_classes
from django.test import SimpleTestCase
from django.template import Context, Template
from ..forms.sessions import SessionForm
class CustomFilterTest(SimpleTestCase):
def test_1(self):
form = SessionForm(data={})
self.assertFalse(form.is_valid())
self.assertEqual(
form.errors,
{'session_number': ['This field is required.'],
'family': ['This field is required.'],
'session_type': ['This field is required.']})
template = Template('{{ form.session_number|label_with_classes }}')
context = Context({'form': form})
output = template.render(context)
The problem is that I get an error that the filter was not found:
django.template.exceptions.TemplateSyntaxError: Invalid filter: 'label_with_classes'
This is because the test case doesn't mimic the behavior of registering the filter and loading it in the template. It seems like in the Django source code, for example https://github.com/django/django/blob/master/tests/template_tests/filter_tests/test_join.py, there is an elaborate setup
decorator which provides the test class with a self.engine
whose render_to_string
method has the required filters already installed.
Do I basically have to copy the Django source code to write an integration-style test for my custom filter? Or is there a simpler way (besides just testing it as a function)?
I suspect you need to load your template module:
...
template = Template("""{% load label_with_classes %}
{{ form.session_number|label_with_classes }}""")
...
See the relevant documentation.