Browse Source

Add tests for admin form template tags/filters

rafalp 6 years ago
parent
commit
e59b811212

+ 3 - 2
misago/admin/templatetags/misago_admin_form.py

@@ -26,7 +26,8 @@ def form_input(field):
 def render_attrs(widget, class_name=None):
 def render_attrs(widget, class_name=None):
     rendered_attrs = []
     rendered_attrs = []
     for attr, value in widget['attrs'].items():
     for attr, value in widget['attrs'].items():
-        rendered_attrs.append((attr, value))
+        if value not in (True, False, None):
+            rendered_attrs.append((attr, value))
     if not widget["attrs"].get("class") and class_name:
     if not widget["attrs"].get("class") and class_name:
         rendered_attrs.append(("class", class_name))
         rendered_attrs.append(("class", class_name))
     return format_html_join(" ", '{}="{}"', rendered_attrs)
     return format_html_join(" ", '{}="{}"', rendered_attrs)
@@ -58,7 +59,7 @@ def is_multiple_choice_field(field):
 
 
 
 
 @register.filter
 @register.filter
-def is_textarea(field):
+def is_textarea_field(field):
     return isinstance(field.field.widget, forms.Textarea)
     return isinstance(field.field.widget, forms.Textarea)
 
 
 
 

+ 164 - 6
misago/admin/tests/test_admin_form_templatetags.py

@@ -2,9 +2,27 @@ from django import forms
 from django.template import Context, Template, TemplateSyntaxError
 from django.template import Context, Template, TemplateSyntaxError
 from django.test import TestCase
 from django.test import TestCase
 
 
+from misago.admin.templatetags.misago_admin_form import (
+    is_radio_select_field, is_select_field, is_multiple_choice_field, is_textarea_field,
+    render_attrs, render_bool_attrs
+)
+from misago.admin.forms import YesNoSwitch
+
 
 
 class TestForm(forms.Form):
 class TestForm(forms.Form):
-    text_field = forms.CharField(label="Hello!", max_length=255)
+    text_field = forms.CharField(label="Hello!", max_length=255, help_text="I am a help text.")
+    textarea_field = forms.CharField(label="Message", max_length=255, widget=forms.Textarea())
+    select_field = forms.ChoiceField(label="Choice", choices=(("y", "Yes"), ("n", "No")))
+    checkbox_select_field = forms.MultipleChoiceField(
+        label="Color",
+        choices=(("r", "Red"), ("g", "Green"), ("b", "Blue")),
+        widget=forms.CheckboxSelectMultiple,
+    )
+    multiple_select_field = forms.MultipleChoiceField(
+        label="Rank",
+        choices=(("r", "Red"), ("g", "Green"), ("b", "Blue")),
+    )
+    yesno_field = YesNoSwitch(label="Switch")
 
 
 
 
 def render(template_str):
 def render(template_str):
@@ -14,22 +32,22 @@ def render(template_str):
     return template.render(context).strip()
     return template.render(context).strip()
 
 
 
 
-class FormRowTests(TestCase):
-    def test_tag_renders_row_with_field(self):
+class FormRowTagTests(TestCase):
+    def test_row_with_field_input_is_rendered(self):
         html = render("{% form_row form.text_field %}")
         html = render("{% form_row form.text_field %}")
         self.assertIn('id_text_field', html)
         self.assertIn('id_text_field', html)
 
 
-    def test_tag_with_label_class_option_renders_row_including_css_class(self):
+    def test_row_with_field_input_and_label_css_class_is_rendered(self):
         html = render('{% form_row form.text_field label_class="col-md-3" %}')
         html = render('{% form_row form.text_field label_class="col-md-3" %}')
         self.assertIn('id_text_field', html)
         self.assertIn('id_text_field', html)
         self.assertIn('col-md-3', html)
         self.assertIn('col-md-3', html)
 
 
-    def test_tag_with_field_class_option_renders_row_including_css_class(self):
+    def test_row_with_field_input_and_field_css_class_is_rendered(self):
         html = render('{% form_row form.text_field field_class="col-md-9" %}')
         html = render('{% form_row form.text_field field_class="col-md-9" %}')
         self.assertIn('id_text_field', html)
         self.assertIn('id_text_field', html)
         self.assertIn('col-md-9', html)
         self.assertIn('col-md-9', html)
 
 
-    def test_tag_with_label_and_control_options_renders_row_including_both_css_classes(self):
+    def test_row_with_field_input_and_label_andfield_css_classes_is_rendered(self):
         html = render('{% form_row form.text_field "col-md-3" "col-md-9" %}')
         html = render('{% form_row form.text_field "col-md-3" "col-md-9" %}')
         self.assertIn('id_text_field', html)
         self.assertIn('id_text_field', html)
         self.assertIn('col-md-3', html)
         self.assertIn('col-md-3', html)
@@ -38,3 +56,143 @@ class FormRowTests(TestCase):
     def test_tag_without_field_raises_exception(self):
     def test_tag_without_field_raises_exception(self):
         with self.assertRaises(TemplateSyntaxError):
         with self.assertRaises(TemplateSyntaxError):
             render('{% form_row %}')
             render('{% form_row %}')
+
+    def test_field_label_is_rendered(self):
+        html = render("{% form_row form.text_field %}")
+        self.assertIn("Hello!", html)
+
+    def test_field_help_text_is_rendered(self):
+        html = render("{% form_row form.text_field %}")
+        self.assertIn("I am a help text.", html)
+
+
+class IsRadioSelectFieldFilterTests(TestCase):
+    def test_for_field_with_radio_select_widget_filter_returns_true(self):
+        form = TestForm()
+        self.assertTrue(is_radio_select_field(form['yesno_field']))
+
+    def test_for_field_without_radio_select_widget_filter_returns_false(self):
+        form = TestForm()
+        self.assertFalse(is_radio_select_field(form['text_field']))
+
+
+class IsSelectFieldFilerTests(TestCase):
+    def test_for_field_with_select_widget_filter_returns_true(self):
+        form = TestForm()
+        self.assertTrue(is_select_field(form['select_field']))
+
+    def teste_for_field_without_select_widget_filter_returns_false(self):
+        form = TestForm()
+        self.assertFalse(is_select_field(form['text_field']))
+
+
+class IsMultipleChoiceFieldFilerTests(TestCase):
+    def test_for_field_with_checkbox_select_widget_filter_returns_true(self):
+        form = TestForm()
+        self.assertTrue(is_multiple_choice_field(form['checkbox_select_field']))
+
+    def test_for_field_without_checkbox_select_widget_filter_returns_false(self):
+        form = TestForm()
+        self.assertFalse(is_multiple_choice_field(form['text_field']))
+
+    def test_for_field_with_multiple_select_widget_filter_returns_true(self):
+        form = TestForm()
+        self.assertTrue(is_multiple_choice_field(form['multiple_select_field']))
+
+    def test_for_field_without_multiple_select_widget_filter_returns_false(self):
+        form = TestForm()
+        self.assertFalse(is_multiple_choice_field(form['text_field']))
+
+
+class IsTextareaFieldFilterTests(TestCase):
+    def test_for_field_with_textarea_widget_filter_returns_true(self):
+        form = TestForm()
+        self.assertTrue(is_textarea_field(form['textarea_field']))
+
+    def test_for_field_without_textarea_widget_filter_returns_false(self):
+        form = TestForm()
+        self.assertFalse(is_textarea_field(form['text_field']))
+
+
+class RenderAttrsTagTests(TestCase):
+    def test_specified_class_name_is_rendered(self):
+        result = render_attrs({"attrs": {}}, class_name="form-control")
+        self.assertEqual(result, 'class="form-control"')
+
+    def test_specified_class_name_overrided_by_class_attr(self):
+        result = render_attrs({"attrs": {"class": "custom"}}, class_name="form-control")
+        self.assertEqual(result, 'class="custom"')
+
+    def test_attr_with_string_value_is_rendered(self):
+        result = render_attrs({"attrs": {"name": "lorem"}})
+        self.assertEqual(result, 'name="lorem"')
+
+    def test_attr_with_int_value_is_rendered(self):
+        result = render_attrs({"attrs": {"cols": 5}})
+        self.assertEqual(result, 'cols="5"')
+
+    def test_attr_with_boolean_true_value_is_not_rendered(self):
+        result = render_attrs({"attrs": {"selected": True}})
+        self.assertEqual(result, "")
+
+    def test_attr_with_boolean_false_value_is_not_rendered(self):
+        result = render_attrs({"attrs": {"selected": False}})
+        self.assertEqual(result, "")
+
+    def test_attr_with_none_value_is_not_rendered(self):
+        result = render_attrs({"attrs": {"selected": None}})
+        self.assertEqual(result, "")
+
+    def test_attr_name_is_escaped(self):
+        result = render_attrs({"attrs": {'"': 'test'}})
+        self.assertEqual(result, '"="test"')
+
+    def test_attr_value_is_escaped(self):
+        result = render_attrs({"attrs": {"name": '"'}})
+        self.assertEqual(result, 'name="""')
+
+    def test_multiple_valid_attrs_are_rendered(self):
+        result = render_attrs({"attrs": {"name": "lorem", "cols": 5}})
+        self.assertEqual(result, 'name="lorem" cols="5"')
+
+    def test_empty_attr_dict_is_not_rendered(self):
+        result = render_attrs({"attrs": {}})
+        self.assertEqual(result, "")
+
+
+class RenderBoolAttrsTagTests(TestCase):
+    def test_attr_with_boolean_true_value_is_rendered(self):
+        result = render_bool_attrs({"bool": True})
+        self.assertEqual(result, "bool")
+
+    def test_attr_with_string_value_is_not_rendered(self):
+        result = render_bool_attrs({"name": "hello"})
+        self.assertEqual(result, "")
+
+    def test_attr_with_int_value_is_not_rendered(self):
+        result = render_bool_attrs({"col": 13})
+        self.assertEqual(result, "")
+
+    def test_attr_with_boolean_false_value_is_not_rendered(self):
+        result = render_bool_attrs({"selected": False})
+        self.assertEqual(result, "")
+
+    def test_attr_with_none_value_is_not_rendered(self):
+        result = render_bool_attrs({"selected": None})
+        self.assertEqual(result, "")
+
+    def test_attr_with_false_int_value_is_not_rendered(self):
+        result = render_bool_attrs({"selected": 0})
+        self.assertEqual(result, "")
+
+    def test_multiple_attrs_with_boolean_true_value_are_rendered(self):
+        result = render_bool_attrs({"selected": True, "required": True})
+        self.assertEqual(result, "selected required")
+
+    def test_only_attrs_with_boolean_true_value_are_rendered(self):
+        result = render_bool_attrs({"bool": True, "string": "hello", "int": 123})
+        self.assertEqual(result, "bool")
+
+    def test_empty_attr_dict_is_not_rendered(self):
+        result = render_bool_attrs({})
+        self.assertEqual(result, "")

+ 1 - 1
misago/templates/misago/admin/form/input.html

@@ -5,7 +5,7 @@
   {% include "misago/admin/form/select.html" %}
   {% include "misago/admin/form/select.html" %}
 {% elif field|is_multiple_choice_field %}
 {% elif field|is_multiple_choice_field %}
   {% include "misago/admin/form/multiple_choice.html" %}
   {% include "misago/admin/form/multiple_choice.html" %}
-{% elif field|is_textarea %}
+{% elif field|is_textarea_field %}
   <textarea {% render_attrs widget class_name="form-control" %} id="{{ field.id_for_label }}" name="{{ widget.name }}" {% render_bool_attrs widget %}>{% if widget.value is not None %}{{ widget.value }}{% endif %}</textarea>
   <textarea {% render_attrs widget class_name="form-control" %} id="{{ field.id_for_label }}" name="{{ widget.name }}" {% render_bool_attrs widget %}>{% if widget.value is not None %}{{ widget.value }}{% endif %}</textarea>
 {% else %}
 {% else %}
   <input {% render_attrs widget class_name="form-control" %} id="{{ field.id_for_label }}" name="{{ widget.name }}" type="{{ widget.type }}"{% if widget.value is not None %} value="{{ widget.value }}"{% endif %} {% render_bool_attrs widget %}>
   <input {% render_attrs widget class_name="form-control" %} id="{{ field.id_for_label }}" name="{{ widget.name }}" type="{{ widget.type }}"{% if widget.value is not None %} value="{{ widget.value }}"{% endif %} {% render_bool_attrs widget %}>

+ 1 - 1
misago/templates/misago/admin/form/select.html

@@ -1,5 +1,5 @@
 {% load misago_admin_form %}
 {% load misago_admin_form %}
-<select class="form-control" id="{{ field.id_for_label }}" name="{{ widget.name }}" {% render_bool_attrs widget %}>
+<select {% render_attrs widget class_name="form-control" %} id="{{ field.id_for_label }}" name="{{ widget.name }}" {% render_bool_attrs widget %}>
   {% for option in field|get_options %}
   {% for option in field|get_options %}
     <option{% if option.value is not None %} value="{{ option.value }}"{% endif %} {% render_bool_attrs option.attrs %}>
     <option{% if option.value is not None %} value="{{ option.value }}"{% endif %} {% render_bool_attrs option.attrs %}>
       {{ option.label }}
       {{ option.label }}