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_select.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_select.py')
| -rw-r--r-- | tests/forms_tests/widget_tests/test_select.py | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/tests/forms_tests/widget_tests/test_select.py b/tests/forms_tests/widget_tests/test_select.py new file mode 100644 index 0000000000..86ef355c62 --- /dev/null +++ b/tests/forms_tests/widget_tests/test_select.py @@ -0,0 +1,250 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import copy + +from django.forms import Select +from django.utils.safestring import mark_safe + +from .base import WidgetTest + + +class SelectTest(WidgetTest): + widget = Select() + nested_widget = Select(choices=( + ('outer1', 'Outer 1'), + ('Group "1"', (('inner1', 'Inner 1'), ('inner2', 'Inner 2'))), + )) + + def test_render(self): + self.check_html(self.widget, 'beatle', 'J', choices=self.beatles, html=( + """<select name="beatle"> + <option value="J" selected="selected">John</option> + <option value="P">Paul</option> + <option value="G">George</option> + <option value="R">Ringo</option> + </select>""" + )) + + def test_render_none(self): + """ + If the value is None, none of the options are selected. + """ + self.check_html(self.widget, 'beatle', None, choices=self.beatles, html=( + """<select name="beatle"> + <option value="J">John</option> + <option value="P">Paul</option> + <option value="G">George</option> + <option value="R">Ringo</option> + </select>""" + )) + + def test_render_label_value(self): + """ + If the value corresponds to a label (but not to an option value), none + of the options are selected. + """ + self.check_html(self.widget, 'beatle', 'John', choices=self.beatles, html=( + """<select name="beatle"> + <option value="J">John</option> + <option value="P">Paul</option> + <option value="G">George</option> + <option value="R">Ringo</option> + </select>""" + )) + + def test_render_selected(self): + """ + Only one option can be selected (#8103). + """ + choices = [('0', '0'), ('1', '1'), ('2', '2'), ('3', '3'), ('0', 'extra')] + + self.check_html(self.widget, 'choices', '0', choices=choices, html=( + """<select name="choices"> + <option value="0" selected="selected">0</option> + <option value="1">1</option> + <option value="2">2</option> + <option value="3">3</option> + <option value="0">extra</option> + </select>""" + )) + + def test_constructor_attrs(self): + """ + Select options shouldn't inherit the parent widget attrs. + """ + widget = Select( + attrs={'class': 'super', 'id': 'super'}, + choices=[(1, 1), (2, 2), (3, 3)], + ) + self.check_html(widget, 'num', 2, html=( + """<select name="num" class="super" id="super"> + <option value="1">1</option> + <option value="2" selected="selected">2</option> + <option value="3">3</option> + </select>""" + )) + + def test_compare_to_str(self): + """ + The value is compared to its str(). + """ + self.check_html( + self.widget, 'num', 2, + choices=[('1', '1'), ('2', '2'), ('3', '3')], + html=( + """<select name="num"> + <option value="1">1</option> + <option value="2" selected="selected">2</option> + <option value="3">3</option> + </select>""" + ), + ) + self.check_html( + self.widget, 'num', '2', + choices=[(1, 1), (2, 2), (3, 3)], + html=( + """<select name="num"> + <option value="1">1</option> + <option value="2" selected="selected">2</option> + <option value="3">3</option> + </select>""" + ), + ) + self.check_html( + self.widget, 'num', 2, + choices=[(1, 1), (2, 2), (3, 3)], + html=( + """<select name="num"> + <option value="1">1</option> + <option value="2" selected="selected">2</option> + <option value="3">3</option> + </select>""" + ), + ) + + def test_choices_constuctor(self): + widget = Select(choices=[(1, 1), (2, 2), (3, 3)]) + self.check_html(widget, 'num', 2, html=( + """<select name="num"> + <option value="1">1</option> + <option value="2" selected="selected">2</option> + <option value="3">3</option> + </select>""" + )) + + def test_choices_constructor_generator(self): + """ + If choices is passed to the constructor and is a generator, it can be + iterated over multiple times without getting consumed. + """ + def get_choices(): + for i in range(5): + yield (i, i) + + widget = Select(choices=get_choices()) + self.check_html(widget, 'num', 2, html=( + """<select name="num"> + <option value="0">0</option> + <option value="1">1</option> + <option value="2" selected="selected">2</option> + <option value="3">3</option> + <option value="4">4</option> + </select>""" + )) + self.check_html(widget, 'num', 3, html=( + """<select name="num"> + <option value="0">0</option> + <option value="1">1</option> + <option value="2">2</option> + <option value="3" selected="selected">3</option> + <option value="4">4</option> + </select>""" + )) + + def test_choices_constuctor_and_render(self): + """ + If 'choices' is passed to both the constructor and render(), then + they'll both be in the output. + """ + widget = Select(choices=[(1, 1), (2, 2), (3, 3)]) + self.check_html(widget, 'num', 2, choices=[(4, 4), (5, 5)], html=( + """<select name="num"> + <option value="1">1</option> + <option value="2" selected="selected">2</option> + <option value="3">3</option> + <option value="4">4</option> + <option value="5">5</option> + </select>""" + )) + + def test_choices_escaping(self): + choices = (('bad', 'you & me'), ('good', mark_safe('you > me'))) + self.check_html(self.widget, 'escape', None, choices=choices, html=( + """<select name="escape"> + <option value="bad">you & me</option> + <option value="good">you > me</option> + </select>""" + )) + + def test_choices_unicode(self): + self.check_html( + self.widget, 'email', 'ŠĐĆŽćžšđ', + choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')], + html=( + """<select name="email"> + <option value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" selected="selected"> + \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111 + </option> + <option value="\u0107\u017e\u0161\u0111">abc\u0107\u017e\u0161\u0111</option> + </select>""" + ), + ) + + def test_choices_optgroup(self): + """ + Choices can be nested one level in order to create HTML optgroups. + """ + self.check_html(self.nested_widget, 'nestchoice', None, html=( + """<select name="nestchoice"> + <option value="outer1">Outer 1</option> + <optgroup label="Group "1""> + <option value="inner1">Inner 1</option> + <option value="inner2">Inner 2</option> + </optgroup> + </select>""" + )) + + def test_choices_select_outer(self): + self.check_html(self.nested_widget, 'nestchoice', 'outer1', html=( + """<select name="nestchoice"> + <option value="outer1" selected="selected">Outer 1</option> + <optgroup label="Group "1""> + <option value="inner1">Inner 1</option> + <option value="inner2">Inner 2</option> + </optgroup> + </select>""" + )) + + def test_choices_select_inner(self): + self.check_html(self.nested_widget, 'nestchoice', 'inner1', html=( + """<select name="nestchoice"> + <option value="outer1">Outer 1</option> + <optgroup label="Group "1""> + <option value="inner1" selected="selected">Inner 1</option> + <option value="inner2">Inner 2</option> + </optgroup> + </select>""" + )) + + def test_deepcopy(self): + """ + __deepcopy__() should copy all attributes properly (#25085). + """ + widget = Select() + obj = copy.deepcopy(widget) + self.assertIsNot(widget, obj) + self.assertEqual(widget.choices, obj.choices) + self.assertIsNot(widget.choices, obj.choices) + self.assertEqual(widget.attrs, obj.attrs) + self.assertIsNot(widget.attrs, obj.attrs) |
