summaryrefslogtreecommitdiff
path: root/tests/forms_tests
diff options
context:
space:
mode:
authorNick Pope <nick@nickpope.me.uk>2023-08-31 02:57:40 +0100
committerGitHub <noreply@github.com>2023-08-30 22:57:40 -0300
commit500e01073adda32d5149624ee9a5cb7aa3d3583f (patch)
treef9416872a811aa39646deaf002414e0a7841b6d1 /tests/forms_tests
parent68a8996bdfce2d191decd7b1c1a2b9fdea8e4b2f (diff)
Fixed #31262 -- Added support for mappings on model fields and ChoiceField's choices.
Diffstat (limited to 'tests/forms_tests')
-rw-r--r--tests/forms_tests/field_tests/test_choicefield.py51
-rw-r--r--tests/forms_tests/widget_tests/test_choicewidget.py19
-rw-r--r--tests/forms_tests/widget_tests/test_radioselect.py18
-rw-r--r--tests/forms_tests/widget_tests/test_select.py142
4 files changed, 147 insertions, 83 deletions
diff --git a/tests/forms_tests/field_tests/test_choicefield.py b/tests/forms_tests/field_tests/test_choicefield.py
index e7893abe57..ebc6c14bea 100644
--- a/tests/forms_tests/field_tests/test_choicefield.py
+++ b/tests/forms_tests/field_tests/test_choicefield.py
@@ -65,6 +65,51 @@ class ChoiceFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
f = ChoiceField(choices=choices)
self.assertEqual("J", f.clean("J"))
+ def test_choicefield_callable_mapping(self):
+ def choices():
+ return {"J": "John", "P": "Paul"}
+
+ f = ChoiceField(choices=choices)
+ self.assertEqual("J", f.clean("J"))
+
+ def test_choicefield_callable_grouped_mapping(self):
+ def choices():
+ return {
+ "Numbers": {"1": "One", "2": "Two"},
+ "Letters": {"3": "A", "4": "B"},
+ }
+
+ f = ChoiceField(choices=choices)
+ for i in ("1", "2", "3", "4"):
+ with self.subTest(i):
+ self.assertEqual(i, f.clean(i))
+
+ def test_choicefield_mapping(self):
+ f = ChoiceField(choices={"J": "John", "P": "Paul"})
+ self.assertEqual("J", f.clean("J"))
+
+ def test_choicefield_grouped_mapping(self):
+ f = ChoiceField(
+ choices={
+ "Numbers": (("1", "One"), ("2", "Two")),
+ "Letters": (("3", "A"), ("4", "B")),
+ }
+ )
+ for i in ("1", "2", "3", "4"):
+ with self.subTest(i):
+ self.assertEqual(i, f.clean(i))
+
+ def test_choicefield_grouped_mapping_inner_dict(self):
+ f = ChoiceField(
+ choices={
+ "Numbers": {"1": "One", "2": "Two"},
+ "Letters": {"3": "A", "4": "B"},
+ }
+ )
+ for i in ("1", "2", "3", "4"):
+ with self.subTest(i):
+ self.assertEqual(i, f.clean(i))
+
def test_choicefield_callable_may_evaluate_to_different_values(self):
choices = []
@@ -76,11 +121,13 @@ class ChoiceFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
choices = [("J", "John")]
form = ChoiceFieldForm()
- self.assertEqual([("J", "John")], list(form.fields["choicefield"].choices))
+ self.assertEqual(choices, list(form.fields["choicefield"].choices))
+ self.assertEqual(choices, list(form.fields["choicefield"].widget.choices))
choices = [("P", "Paul")]
form = ChoiceFieldForm()
- self.assertEqual([("P", "Paul")], list(form.fields["choicefield"].choices))
+ self.assertEqual(choices, list(form.fields["choicefield"].choices))
+ self.assertEqual(choices, list(form.fields["choicefield"].widget.choices))
def test_choicefield_disabled(self):
f = ChoiceField(choices=[("J", "John"), ("P", "Paul")], disabled=True)
diff --git a/tests/forms_tests/widget_tests/test_choicewidget.py b/tests/forms_tests/widget_tests/test_choicewidget.py
index 129178f207..abd1961b32 100644
--- a/tests/forms_tests/widget_tests/test_choicewidget.py
+++ b/tests/forms_tests/widget_tests/test_choicewidget.py
@@ -9,13 +9,26 @@ class ChoiceWidgetTest(WidgetTest):
widget = ChoiceWidget
@property
- def nested_widget(self):
- return self.widget(
+ def nested_widgets(self):
+ nested_widget = self.widget(
choices=(
("outer1", "Outer 1"),
('Group "1"', (("inner1", "Inner 1"), ("inner2", "Inner 2"))),
- )
+ ),
+ )
+ nested_widget_dict = self.widget(
+ choices={
+ "outer1": "Outer 1",
+ 'Group "1"': {"inner1": "Inner 1", "inner2": "Inner 2"},
+ },
+ )
+ nested_widget_dict_tuple = self.widget(
+ choices={
+ "outer1": "Outer 1",
+ 'Group "1"': (("inner1", "Inner 1"), ("inner2", "Inner 2")),
+ },
)
+ return (nested_widget, nested_widget_dict, nested_widget_dict_tuple)
def test_deepcopy(self):
"""
diff --git a/tests/forms_tests/widget_tests/test_radioselect.py b/tests/forms_tests/widget_tests/test_radioselect.py
index 5e5cea9d35..be336151ef 100644
--- a/tests/forms_tests/widget_tests/test_radioselect.py
+++ b/tests/forms_tests/widget_tests/test_radioselect.py
@@ -13,7 +13,6 @@ class RadioSelectTest(ChoiceWidgetTest):
widget = RadioSelect
def test_render(self):
- choices = BLANK_CHOICE_DASH + self.beatles
html = """
<div>
<div>
@@ -33,7 +32,10 @@ class RadioSelectTest(ChoiceWidgetTest):
</div>
</div>
"""
- self.check_html(self.widget(choices=choices), "beatle", "J", html=html)
+ beatles_with_blank = BLANK_CHOICE_DASH + self.beatles
+ for choices in (beatles_with_blank, dict(beatles_with_blank)):
+ with self.subTest(choices):
+ self.check_html(self.widget(choices=choices), "beatle", "J", html=html)
def test_nested_choices(self):
nested_choices = (
@@ -312,7 +314,9 @@ class RadioSelectTest(ChoiceWidgetTest):
</div>
</div>
"""
- self.check_html(self.nested_widget, "nestchoice", None, html=html)
+ for widget in self.nested_widgets:
+ with self.subTest(widget):
+ self.check_html(widget, "nestchoice", None, html=html)
def test_choices_select_outer(self):
html = """
@@ -334,7 +338,9 @@ class RadioSelectTest(ChoiceWidgetTest):
</div>
</div>
"""
- self.check_html(self.nested_widget, "nestchoice", "outer1", html=html)
+ for widget in self.nested_widgets:
+ with self.subTest(widget):
+ self.check_html(widget, "nestchoice", "outer1", html=html)
def test_choices_select_inner(self):
html = """
@@ -356,7 +362,9 @@ class RadioSelectTest(ChoiceWidgetTest):
</div>
</div>
"""
- self.check_html(self.nested_widget, "nestchoice", "inner2", html=html)
+ for widget in self.nested_widgets:
+ with self.subTest(widget):
+ self.check_html(widget, "nestchoice", "inner2", html=html)
def test_render_attrs(self):
"""
diff --git a/tests/forms_tests/widget_tests/test_select.py b/tests/forms_tests/widget_tests/test_select.py
index 60a0b72880..6164d0b6b3 100644
--- a/tests/forms_tests/widget_tests/test_select.py
+++ b/tests/forms_tests/widget_tests/test_select.py
@@ -11,19 +11,17 @@ class SelectTest(ChoiceWidgetTest):
widget = Select
def test_render(self):
- self.check_html(
- self.widget(choices=self.beatles),
- "beatle",
- "J",
- html=(
- """<select name="beatle">
- <option value="J" selected>John</option>
- <option value="P">Paul</option>
- <option value="G">George</option>
- <option value="R">Ringo</option>
- </select>"""
- ),
- )
+ html = """
+ <select name="beatle">
+ <option value="J" selected>John</option>
+ <option value="P">Paul</option>
+ <option value="G">George</option>
+ <option value="R">Ringo</option>
+ </select>
+ """
+ for choices in (self.beatles, dict(self.beatles)):
+ with self.subTest(choices):
+ self.check_html(self.widget(choices=choices), "beatle", "J", html=html)
def test_render_none(self):
"""
@@ -237,52 +235,46 @@ class SelectTest(ChoiceWidgetTest):
"""
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 &quot;1&quot;">
- <option value="inner1">Inner 1</option>
- <option value="inner2">Inner 2</option>
- </optgroup>
- </select>"""
- ),
- )
+ html = """
+ <select name="nestchoice">
+ <option value="outer1">Outer 1</option>
+ <optgroup label="Group &quot;1&quot;">
+ <option value="inner1">Inner 1</option>
+ <option value="inner2">Inner 2</option>
+ </optgroup>
+ </select>
+ """
+ for widget in self.nested_widgets:
+ with self.subTest(widget):
+ self.check_html(widget, "nestchoice", None, html=html)
def test_choices_select_outer(self):
- self.check_html(
- self.nested_widget,
- "nestchoice",
- "outer1",
- html=(
- """<select name="nestchoice">
- <option value="outer1" selected>Outer 1</option>
- <optgroup label="Group &quot;1&quot;">
- <option value="inner1">Inner 1</option>
- <option value="inner2">Inner 2</option>
- </optgroup>
- </select>"""
- ),
- )
+ html = """
+ <select name="nestchoice">
+ <option value="outer1" selected>Outer 1</option>
+ <optgroup label="Group &quot;1&quot;">
+ <option value="inner1">Inner 1</option>
+ <option value="inner2">Inner 2</option>
+ </optgroup>
+ </select>
+ """
+ for widget in self.nested_widgets:
+ with self.subTest(widget):
+ self.check_html(widget, "nestchoice", "outer1", html=html)
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 &quot;1&quot;">
- <option value="inner1" selected>Inner 1</option>
- <option value="inner2">Inner 2</option>
- </optgroup>
- </select>"""
- ),
- )
+ html = """
+ <select name="nestchoice">
+ <option value="outer1">Outer 1</option>
+ <optgroup label="Group &quot;1&quot;">
+ <option value="inner1" selected>Inner 1</option>
+ <option value="inner2">Inner 2</option>
+ </optgroup>
+ </select>
+ """
+ for widget in self.nested_widgets:
+ with self.subTest(widget):
+ self.check_html(widget, "nestchoice", "inner1", html=html)
@override_settings(USE_THOUSAND_SEPARATOR=True)
def test_doesnt_localize_option_value(self):
@@ -312,24 +304,7 @@ class SelectTest(ChoiceWidgetTest):
"""
self.check_html(self.widget(choices=choices), "time", None, html=html)
- def test_optgroups(self):
- choices = [
- (
- "Audio",
- [
- ("vinyl", "Vinyl"),
- ("cd", "CD"),
- ],
- ),
- (
- "Video",
- [
- ("vhs", "VHS Tape"),
- ("dvd", "DVD"),
- ],
- ),
- ("unknown", "Unknown"),
- ]
+ def _test_optgroups(self, choices):
groups = list(
self.widget(choices=choices).optgroups(
"name",
@@ -418,6 +393,27 @@ class SelectTest(ChoiceWidgetTest):
)
self.assertEqual(index, 2)
+ def test_optgroups(self):
+ choices_dict = {
+ "Audio": [
+ ("vinyl", "Vinyl"),
+ ("cd", "CD"),
+ ],
+ "Video": [
+ ("vhs", "VHS Tape"),
+ ("dvd", "DVD"),
+ ],
+ "unknown": "Unknown",
+ }
+ choices_list = list(choices_dict.items())
+ choices_nested_dict = {
+ k: dict(v) if isinstance(v, list) else v for k, v in choices_dict.items()
+ }
+
+ for choices in (choices_dict, choices_list, choices_nested_dict):
+ with self.subTest(choices):
+ self._test_optgroups(choices)
+
def test_doesnt_render_required_when_impossible_to_select_empty_field(self):
widget = self.widget(choices=[("J", "John"), ("P", "Paul")])
self.assertIs(widget.use_required_attribute(initial=None), False)