summaryrefslogtreecommitdiff
path: root/tests/forms_tests/field_tests
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/field_tests
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/field_tests')
-rw-r--r--tests/forms_tests/field_tests/__init__.py0
-rw-r--r--tests/forms_tests/field_tests/test_datefield.py111
-rw-r--r--tests/forms_tests/field_tests/test_multivaluefield.py162
3 files changed, 273 insertions, 0 deletions
diff --git a/tests/forms_tests/field_tests/__init__.py b/tests/forms_tests/field_tests/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/forms_tests/field_tests/__init__.py
diff --git a/tests/forms_tests/field_tests/test_datefield.py b/tests/forms_tests/field_tests/test_datefield.py
new file mode 100644
index 0000000000..6b66cb2d52
--- /dev/null
+++ b/tests/forms_tests/field_tests/test_datefield.py
@@ -0,0 +1,111 @@
+from datetime import date
+
+from django.forms import DateField, Form, HiddenInput, SelectDateWidget
+from django.test import SimpleTestCase, override_settings
+from django.utils import translation
+
+
+class GetDate(Form):
+ mydate = DateField(widget=SelectDateWidget)
+
+
+class DateFieldTest(SimpleTestCase):
+
+ def test_form_field(self):
+ a = GetDate({'mydate_month': '4', 'mydate_day': '1', 'mydate_year': '2008'})
+ self.assertTrue(a.is_valid())
+ self.assertEqual(a.cleaned_data['mydate'], date(2008, 4, 1))
+
+ # As with any widget that implements get_value_from_datadict(), we must
+ # accept the input from the "as_hidden" rendering as well.
+ self.assertHTMLEqual(
+ a['mydate'].as_hidden(),
+ '<input type="hidden" name="mydate" value="2008-4-1" id="id_mydate" />',
+ )
+
+ b = GetDate({'mydate': '2008-4-1'})
+ self.assertTrue(b.is_valid())
+ self.assertEqual(b.cleaned_data['mydate'], date(2008, 4, 1))
+
+ # Invalid dates shouldn't be allowed
+ c = GetDate({'mydate_month': '2', 'mydate_day': '31', 'mydate_year': '2010'})
+ self.assertFalse(c.is_valid())
+ self.assertEqual(c.errors, {'mydate': ['Enter a valid date.']})
+
+ # label tag is correctly associated with month dropdown
+ d = GetDate({'mydate_month': '1', 'mydate_day': '1', 'mydate_year': '2010'})
+ self.assertIn('<label for="id_mydate_month">', d.as_p())
+
+ @override_settings(USE_L10N=True)
+ @translation.override('nl')
+ def test_l10n_date_changed(self):
+ """
+ Ensure that DateField.has_changed() with SelectDateWidget works
+ correctly with a localized date format (#17165).
+ """
+ # With Field.show_hidden_initial=False
+ b = GetDate({
+ 'mydate_year': '2008',
+ 'mydate_month': '4',
+ 'mydate_day': '1',
+ }, initial={'mydate': date(2008, 4, 1)})
+ self.assertFalse(b.has_changed())
+
+ b = GetDate({
+ 'mydate_year': '2008',
+ 'mydate_month': '4',
+ 'mydate_day': '2',
+ }, initial={'mydate': date(2008, 4, 1)})
+ self.assertTrue(b.has_changed())
+
+ # With Field.show_hidden_initial=True
+ class GetDateShowHiddenInitial(Form):
+ mydate = DateField(widget=SelectDateWidget, show_hidden_initial=True)
+
+ b = GetDateShowHiddenInitial({
+ 'mydate_year': '2008',
+ 'mydate_month': '4',
+ 'mydate_day': '1',
+ 'initial-mydate': HiddenInput()._format_value(date(2008, 4, 1)),
+ }, initial={'mydate': date(2008, 4, 1)})
+ self.assertFalse(b.has_changed())
+
+ b = GetDateShowHiddenInitial({
+ 'mydate_year': '2008',
+ 'mydate_month': '4',
+ 'mydate_day': '22',
+ 'initial-mydate': HiddenInput()._format_value(date(2008, 4, 1)),
+ }, initial={'mydate': date(2008, 4, 1)})
+ self.assertTrue(b.has_changed())
+
+ b = GetDateShowHiddenInitial({
+ 'mydate_year': '2008',
+ 'mydate_month': '4',
+ 'mydate_day': '22',
+ 'initial-mydate': HiddenInput()._format_value(date(2008, 4, 1)),
+ }, initial={'mydate': date(2008, 4, 22)})
+ self.assertTrue(b.has_changed())
+
+ b = GetDateShowHiddenInitial({
+ 'mydate_year': '2008',
+ 'mydate_month': '4',
+ 'mydate_day': '22',
+ 'initial-mydate': HiddenInput()._format_value(date(2008, 4, 22)),
+ }, initial={'mydate': date(2008, 4, 1)})
+ self.assertFalse(b.has_changed())
+
+ @override_settings(USE_L10N=True)
+ @translation.override('nl')
+ def test_l10n_invalid_date_in(self):
+ # Invalid dates shouldn't be allowed
+ a = GetDate({'mydate_month': '2', 'mydate_day': '31', 'mydate_year': '2010'})
+ self.assertFalse(a.is_valid())
+ # 'Geef een geldige datum op.' = 'Enter a valid date.'
+ self.assertEqual(a.errors, {'mydate': ['Geef een geldige datum op.']})
+
+ @override_settings(USE_L10N=True)
+ @translation.override('nl')
+ def test_form_label_association(self):
+ # label tag is correctly associated with first rendered dropdown
+ a = GetDate({'mydate_month': '1', 'mydate_day': '1', 'mydate_year': '2010'})
+ self.assertIn('<label for="id_mydate_day">', a.as_p())
diff --git a/tests/forms_tests/field_tests/test_multivaluefield.py b/tests/forms_tests/field_tests/test_multivaluefield.py
new file mode 100644
index 0000000000..258d67bdcd
--- /dev/null
+++ b/tests/forms_tests/field_tests/test_multivaluefield.py
@@ -0,0 +1,162 @@
+from datetime import datetime
+
+from django.forms import (
+ CharField, Form, MultipleChoiceField, MultiValueField, MultiWidget,
+ SelectMultiple, SplitDateTimeField, SplitDateTimeWidget, TextInput,
+ ValidationError,
+)
+from django.test import SimpleTestCase
+
+beatles = (('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))
+
+
+class ComplexMultiWidget(MultiWidget):
+ def __init__(self, attrs=None):
+ widgets = (
+ TextInput(),
+ SelectMultiple(choices=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=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 ComplexFieldForm(Form):
+ field1 = ComplexField(widget=ComplexMultiWidget())
+
+
+class MultiValueFieldTest(SimpleTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.field = ComplexField(widget=ComplexMultiWidget())
+ super(MultiValueFieldTest, cls).setUpClass()
+
+ def test_clean(self):
+ self.assertEqual(
+ self.field.clean(['some text', ['J', 'P'], ['2007-04-25', '6:24:00']]),
+ 'some text,JP,2007-04-25 06:24:00',
+ )
+
+ def test_bad_choice(self):
+ msg = "'Select a valid choice. X is not one of the available choices.'"
+ with self.assertRaisesMessage(ValidationError, msg):
+ self.field.clean(['some text', ['X'], ['2007-04-25', '6:24:00']])
+
+ def test_no_value(self):
+ """
+ If insufficient data is provided, None is substituted.
+ """
+ msg = "'This field is required.'"
+ with self.assertRaisesMessage(ValidationError, msg):
+ self.field.clean(['some text', ['JP']])
+
+ def test_has_changed_no_initial(self):
+ self.assertTrue(self.field.has_changed(
+ None, ['some text', ['J', 'P'], ['2007-04-25', '6:24:00']],
+ ))
+
+ def test_has_changed_same(self):
+ self.assertFalse(self.field.has_changed(
+ 'some text,JP,2007-04-25 06:24:00',
+ ['some text', ['J', 'P'], ['2007-04-25', '6:24:00']],
+ ))
+
+ def test_has_changed_first_widget(self):
+ """
+ Test when the first widget's data has changed.
+ """
+ self.assertTrue(self.field.has_changed(
+ 'some text,JP,2007-04-25 06:24:00',
+ ['other text', ['J', 'P'], ['2007-04-25', '6:24:00']],
+ ))
+
+ def test_has_changed_last_widget(self):
+ """
+ Test when the last widget's data has changed. This ensures that it is
+ not short circuiting while testing the widgets.
+ """
+ self.assertTrue(self.field.has_changed(
+ 'some text,JP,2007-04-25 06:24:00',
+ ['some text', ['J', 'P'], ['2009-04-25', '11:44:00']],
+ ))
+
+ def test_form_as_table(self):
+ form = ComplexFieldForm()
+ self.assertHTMLEqual(
+ form.as_table(),
+ """
+ <tr><th><label for="id_field1_0">Field1:</label></th>
+ <td><input type="text" name="field1_0" id="id_field1_0" />
+ <select multiple="multiple" name="field1_1" id="id_field1_1">
+ <option value="J">John</option>
+ <option value="P">Paul</option>
+ <option value="G">George</option>
+ <option value="R">Ringo</option>
+ </select>
+ <input type="text" name="field1_2_0" id="id_field1_2_0" />
+ <input type="text" name="field1_2_1" id="id_field1_2_1" /></td></tr>
+ """,
+ )
+
+ def test_form_as_table_data(self):
+ form = ComplexFieldForm({
+ 'field1_0': 'some text',
+ 'field1_1': ['J', 'P'],
+ 'field1_2_0': '2007-04-25',
+ 'field1_2_1': '06:24:00',
+ })
+ self.assertHTMLEqual(
+ form.as_table(),
+ """
+ <tr><th><label for="id_field1_0">Field1:</label></th>
+ <td><input type="text" name="field1_0" value="some text" id="id_field1_0" />
+ <select multiple="multiple" name="field1_1" id="id_field1_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="field1_2_0" value="2007-04-25" id="id_field1_2_0" />
+ <input type="text" name="field1_2_1" value="06:24:00" id="id_field1_2_1" /></td></tr>
+ """,
+ )
+
+ def test_form_cleaned_data(self):
+ form = ComplexFieldForm({
+ 'field1_0': 'some text',
+ 'field1_1': ['J', 'P'],
+ 'field1_2_0': '2007-04-25',
+ 'field1_2_1': '06:24:00',
+ })
+ form.is_valid()
+ self.assertEqual(
+ form.cleaned_data['field1'], 'some text,JP,2007-04-25 06:24:00',
+ )