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 .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'))
@override_settings(USE_L10N=True)
@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 (#17401).
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 datetime_safe).
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(USE_L10N=False, DATE_INPUT_FORMATS=['%d.%m.%Y'])
def test_custom_input_format(self):
w = SelectDateWidget(years=('0001', '1899', '2009', '2010'))
for values, expected 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)
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),
]
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, USE_L10N=True)
def test_years_rendered_without_separator(self):
widget = SelectDateWidget(years=(2007,))
self.check_html(widget, 'mydate', '', html=(
"""
"""
))