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/field_tests | |
| 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/field_tests')
| -rw-r--r-- | tests/forms_tests/field_tests/__init__.py | 0 | ||||
| -rw-r--r-- | tests/forms_tests/field_tests/test_datefield.py | 111 | ||||
| -rw-r--r-- | tests/forms_tests/field_tests/test_multivaluefield.py | 162 |
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', + ) |
