diff options
| author | Preston Timmons <prestontimmons@gmail.com> | 2015-08-30 21:13:42 -0500 |
|---|---|---|
| committer | Preston Timmons <prestontimmons@gmail.com> | 2015-08-31 23:03:55 -0500 |
| commit | 4c30fa905d9d47b3a2ee82095b1fe56cc2ec2ab5 (patch) | |
| tree | 2bb04d4ecef539e4ebefbd6d750dfd240ddd7f0c /tests/forms_tests/widget_tests/test_multiwidget.py | |
| parent | 5153a3bfdcec82324d67ff79862384288cf6afe6 (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.py | 163 |
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]) |
