import sys from datetime import date from django.forms import DateField, Form, SelectDateWidget from django.test import override_settings from django.utils import translation from django.utils.dates import MONTHS_AP from django.utils.version import PYPY from .base import WidgetTest class SelectDateWidgetTest(WidgetTest): maxDiff = None widget = SelectDateWidget( years=( "2007", "2008", "2009", "2010", "2011", "2012", "2013", "2014", "2015", "2016", ), ) def test_render_empty(self): self.check_html( self.widget, "mydate", "", html=( """ """ ), ) def test_render_none(self): """ Rendering the None or '' values should yield the same output. """ self.assertHTMLEqual( self.widget.render("mydate", None), self.widget.render("mydate", ""), ) def test_render_string(self): self.check_html( self.widget, "mydate", "2010-04-15", html=( """ """ ), ) def test_render_datetime(self): self.assertHTMLEqual( self.widget.render("mydate", date(2010, 4, 15)), self.widget.render("mydate", "2010-04-15"), ) def test_render_invalid_date(self): """ Invalid dates should still render the failed date. """ self.check_html( self.widget, "mydate", "2010-02-31", html=( """ """ ), ) def test_custom_months(self): widget = SelectDateWidget(months=MONTHS_AP, years=("2013",)) self.check_html( widget, "mydate", "", html=( """ """ ), ) def test_selectdate_required(self): class GetNotRequiredDate(Form): mydate = DateField(widget=SelectDateWidget, required=False) class GetRequiredDate(Form): mydate = DateField(widget=SelectDateWidget, required=True) self.assertFalse(GetNotRequiredDate().fields["mydate"].widget.is_required) self.assertTrue(GetRequiredDate().fields["mydate"].widget.is_required) def test_selectdate_empty_label(self): w = SelectDateWidget(years=("2014",), empty_label="empty_label") # Rendering the default state with empty_label set as string. self.assertInHTML( '', w.render("mydate", ""), count=3, ) w = SelectDateWidget( years=("2014",), empty_label=("empty_year", "empty_month", "empty_day") ) # Rendering the default state with empty_label tuple. self.assertHTMLEqual( w.render("mydate", ""), """ """, ) with self.assertRaisesMessage( ValueError, "empty_label list/tuple must have 3 elements." ): SelectDateWidget(years=("2014",), empty_label=("not enough", "values")) @translation.override("nl") def test_l10n(self): w = SelectDateWidget( years=( "2007", "2008", "2009", "2010", "2011", "2012", "2013", "2014", "2015", "2016", ) ) self.assertEqual( w.value_from_datadict( {"date_year": "2010", "date_month": "8", "date_day": "13"}, {}, "date" ), "13-08-2010", ) self.assertHTMLEqual( w.render("date", "13-08-2010"), """ """, ) # Even with an invalid date, the widget should reflect the entered # value. self.assertEqual(w.render("mydate", "2010-02-30").count("selected"), 3) # Years before 1900 should work. w = SelectDateWidget(years=("1899",)) self.assertEqual( w.value_from_datadict( {"date_year": "1899", "date_month": "8", "date_day": "13"}, {}, "date" ), "13-08-1899", ) # And years before 1000 (demonstrating the need for # sanitize_strftime_format). w = SelectDateWidget(years=("0001",)) self.assertEqual( w.value_from_datadict( {"date_year": "0001", "date_month": "8", "date_day": "13"}, {}, "date" ), "13-08-0001", ) @override_settings(DATE_INPUT_FORMATS=["%d.%m.%Y"]) def test_custom_input_format(self): w = SelectDateWidget(years=("0001", "1899", "2009", "2010")) with translation.override(None): for values, expected_value in ( (("0001", "8", "13"), "13.08.0001"), (("1899", "7", "11"), "11.07.1899"), (("2009", "3", "7"), "07.03.2009"), ): with self.subTest(values=values): data = { "field_%s" % field: value for field, value in zip(("year", "month", "day"), values) } self.assertEqual( w.value_from_datadict(data, {}, "field"), expected_value ) expected_dict = { field: int(value) for field, value in zip(("year", "month", "day"), values) } self.assertEqual(w.format_value(expected_value), expected_dict) def test_format_value(self): valid_formats = [ "2000-1-1", "2000-10-15", "2000-01-01", "2000-01-0", "2000-0-01", "2000-0-0", "0-01-01", "0-01-0", "0-0-01", "0-0-0", ] for value in valid_formats: year, month, day = (int(x) or "" for x in value.split("-")) with self.subTest(value=value): self.assertEqual( self.widget.format_value(value), {"day": day, "month": month, "year": year}, ) invalid_formats = [ "2000-01-001", "2000-001-01", "2-01-01", "20-01-01", "200-01-01", "20000-01-01", ] for value in invalid_formats: with self.subTest(value=value): self.assertEqual( self.widget.format_value(value), {"day": None, "month": None, "year": None}, ) def test_value_from_datadict(self): tests = [ (("2000", "12", "1"), "2000-12-01"), (("", "12", "1"), "0-12-1"), (("2000", "", "1"), "2000-0-1"), (("2000", "12", ""), "2000-12-0"), (("", "", "", ""), None), ((None, "12", "1"), None), (("2000", None, "1"), None), (("2000", "12", None), None), ( (str(sys.maxsize + 1), "12", "1"), # PyPy does not raise OverflowError. f"{sys.maxsize + 1}-12-1" if PYPY else "0-0-0", ), ] for values, expected in tests: with self.subTest(values=values): data = {} for field_name, value in zip(("year", "month", "day"), values): if value is not None: data["field_%s" % field_name] = value self.assertEqual( self.widget.value_from_datadict(data, {}, "field"), expected ) def test_value_omitted_from_data(self): self.assertIs(self.widget.value_omitted_from_data({}, {}, "field"), True) self.assertIs( self.widget.value_omitted_from_data({"field_month": "12"}, {}, "field"), False, ) self.assertIs( self.widget.value_omitted_from_data({"field_year": "2000"}, {}, "field"), False, ) self.assertIs( self.widget.value_omitted_from_data({"field_day": "1"}, {}, "field"), False ) data = {"field_day": "1", "field_month": "12", "field_year": "2000"} self.assertIs(self.widget.value_omitted_from_data(data, {}, "field"), False) @override_settings(USE_THOUSAND_SEPARATOR=True) def test_years_rendered_without_separator(self): widget = SelectDateWidget(years=(2007,)) self.check_html( widget, "mydate", "", html=( """ """ ), ) def test_fieldset(self): class TestForm(Form): template_name = "forms_tests/use_fieldset.html" field = DateField(widget=self.widget) form = TestForm() self.assertIs(self.widget.use_fieldset, True) self.assertHTMLEqual( '
", form.render(), )