summaryrefslogtreecommitdiff
path: root/tests/forms_tests/widget_tests/test_multiwidget.py
diff options
context:
space:
mode:
authorPreston Timmons <prestontimmons@gmail.com>2015-08-30 21:13:42 -0500
committerPreston Timmons <prestontimmons@gmail.com>2015-08-31 23:03:55 -0500
commit4c30fa905d9d47b3a2ee82095b1fe56cc2ec2ab5 (patch)
tree2bb04d4ecef539e4ebefbd6d750dfd240ddd7f0c /tests/forms_tests/widget_tests/test_multiwidget.py
parent5153a3bfdcec82324d67ff79862384288cf6afe6 (diff)
Rewrote form widget tests as proper unittests.
This is preparation for landing the template-based widget rendering patch and goes a long way to making these tests more useful for future development. The old doctest heritage is strong here.
Diffstat (limited to 'tests/forms_tests/widget_tests/test_multiwidget.py')
-rw-r--r--tests/forms_tests/widget_tests/test_multiwidget.py163
1 files changed, 163 insertions, 0 deletions
diff --git a/tests/forms_tests/widget_tests/test_multiwidget.py b/tests/forms_tests/widget_tests/test_multiwidget.py
new file mode 100644
index 0000000000..bb6f8bfc4f
--- /dev/null
+++ b/tests/forms_tests/widget_tests/test_multiwidget.py
@@ -0,0 +1,163 @@
+import copy
+from datetime import datetime
+
+from django.forms import (
+ CharField, FileInput, MultipleChoiceField, MultiValueField, MultiWidget,
+ RadioSelect, SelectMultiple, SplitDateTimeField, SplitDateTimeWidget,
+ TextInput,
+)
+
+from .base import WidgetTest
+
+
+class MyMultiWidget(MultiWidget):
+ def decompress(self, value):
+ if value:
+ return value.split('__')
+ return ['', '']
+
+
+class ComplexMultiWidget(MultiWidget):
+ def __init__(self, attrs=None):
+ widgets = (
+ TextInput(),
+ SelectMultiple(choices=WidgetTest.beatles),
+ SplitDateTimeWidget(),
+ )
+ super(ComplexMultiWidget, self).__init__(widgets, attrs)
+
+ def decompress(self, value):
+ if value:
+ data = value.split(',')
+ return [
+ data[0], list(data[1]), datetime.strptime(data[2], "%Y-%m-%d %H:%M:%S")
+ ]
+ return [None, None, None]
+
+ def format_output(self, rendered_widgets):
+ return '\n'.join(rendered_widgets)
+
+
+class ComplexField(MultiValueField):
+ def __init__(self, required=True, widget=None, label=None, initial=None):
+ fields = (
+ CharField(),
+ MultipleChoiceField(choices=WidgetTest.beatles),
+ SplitDateTimeField(),
+ )
+ super(ComplexField, self).__init__(
+ fields, required, widget, label, initial,
+ )
+
+ def compress(self, data_list):
+ if data_list:
+ return '%s,%s,%s' % (
+ data_list[0], ''.join(data_list[1]), data_list[2],
+ )
+ return None
+
+
+class DeepCopyWidget(MultiWidget):
+ """
+ Used to test MultiWidget.__deepcopy__().
+ """
+ def __init__(self, choices=[]):
+ widgets = [
+ RadioSelect(choices=choices),
+ TextInput,
+ ]
+ super(DeepCopyWidget, self).__init__(widgets)
+
+ def _set_choices(self, choices):
+ """
+ When choices are set for this widget, we want to pass those along to
+ the Select widget.
+ """
+ self.widgets[0].choices = choices
+
+ def _get_choices(self):
+ """
+ The choices for this widget are the Select widget's choices.
+ """
+ return self.widgets[0].choices
+ choices = property(_get_choices, _set_choices)
+
+
+class MultiWidgetTest(WidgetTest):
+
+ def test_text_inputs(self):
+ widget = MyMultiWidget(
+ widgets=(
+ TextInput(attrs={'class': 'big'}),
+ TextInput(attrs={'class': 'small'}),
+ )
+ )
+ self.check_html(widget, 'name', ['john', 'lennon'], html=(
+ '<input type="text" class="big" value="john" name="name_0" />'
+ '<input type="text" class="small" value="lennon" name="name_1" />'
+ ))
+ self.check_html(widget, 'name', 'john__lennon', html=(
+ '<input type="text" class="big" value="john" name="name_0" />'
+ '<input type="text" class="small" value="lennon" name="name_1" />'
+ ))
+ self.check_html(widget, 'name', 'john__lennon', attrs={'id': 'foo'}, html=(
+ '<input id="foo_0" type="text" class="big" value="john" name="name_0" />'
+ '<input id="foo_1" type="text" class="small" value="lennon" name="name_1" />'
+ ))
+
+ def test_constructor_attrs(self):
+ widget = MyMultiWidget(
+ widgets=(
+ TextInput(attrs={'class': 'big'}),
+ TextInput(attrs={'class': 'small'}),
+ ),
+ attrs={'id': 'bar'},
+ )
+ self.check_html(widget, 'name', ['john', 'lennon'], html=(
+ '<input id="bar_0" type="text" class="big" value="john" name="name_0" />'
+ '<input id="bar_1" type="text" class="small" value="lennon" name="name_1" />'
+ ))
+
+ def test_needs_multipart_true(self):
+ """
+ needs_multipart_form should be True if any widgets need it.
+ """
+ widget = MyMultiWidget(widgets=(TextInput(), FileInput()))
+ self.assertTrue(widget.needs_multipart_form)
+
+ def test_needs_multipart_false(self):
+ """
+ needs_multipart_form should be False if no widgets need it.
+ """
+ widget = MyMultiWidget(widgets=(TextInput(), TextInput()))
+ self.assertFalse(widget.needs_multipart_form)
+
+ def test_nested_multiwidget(self):
+ """
+ MultiWidgets can be composed of other MultiWidgets.
+ """
+ widget = ComplexMultiWidget()
+ self.check_html(widget, 'name', 'some text,JP,2007-04-25 06:24:00', html=(
+ """
+ <input type="text" name="name_0" value="some text" />
+ <select multiple="multiple" name="name_1">
+ <option value="J" selected="selected">John</option>
+ <option value="P" selected="selected">Paul</option>
+ <option value="G">George</option>
+ <option value="R">Ringo</option>
+ </select>
+ <input type="text" name="name_2_0" value="2007-04-25" />
+ <input type="text" name="name_2_1" value="06:24:00" />
+ """
+ ))
+
+ def test_deepcopy(self):
+ """
+ MultiWidget should define __deepcopy__() (#12048).
+ """
+ w1 = DeepCopyWidget(choices=[1, 2, 3])
+ w2 = copy.deepcopy(w1)
+ w2.choices = [4, 5, 6]
+ # w2 ought to be independent of w1, since MultiWidget ought
+ # to make a copy of its sub-widgets when it is copied.
+ self.assertEqual(w1.choices, [1, 2, 3])