Kaydet (Commit) 4c30fa90 authored tarafından Preston Timmons's avatar Preston Timmons

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.
üst 5153a3bf
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())
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',
)
from django.test import SimpleTestCase
class WidgetTest(SimpleTestCase):
beatles = (('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))
def check_html(self, widget, name, value, html='', attrs=None, **kwargs):
output = widget.render(name, value, attrs=attrs, **kwargs)
self.assertHTMLEqual(output, html)
from django.forms import CheckboxInput
from .base import WidgetTest
class CheckboxInputTest(WidgetTest):
widget = CheckboxInput()
def test_render_empty(self):
self.check_html(self.widget, 'is_cool', '', html='<input type="checkbox" name="is_cool" />')
def test_render_none(self):
self.check_html(self.widget, 'is_cool', None, html='<input type="checkbox" name="is_cool" />')
def test_render_false(self):
self.check_html(self.widget, 'is_cool', False, html='<input type="checkbox" name="is_cool" />')
def test_render_true(self):
self.check_html(
self.widget, 'is_cool', True,
html='<input checked="checked" type="checkbox" name="is_cool" />'
)
def test_render_value(self):
"""
Using any value that's not in ('', None, False, True) will check the
checkbox and set the 'value' attribute.
"""
self.check_html(
self.widget, 'is_cool', 'foo',
html='<input checked="checked" type="checkbox" name="is_cool" value="foo" />',
)
def test_render_int(self):
"""
Integers are handled by value, not as booleans (#17114).
"""
self.check_html(
self.widget, 'is_cool', 0,
html='<input checked="checked" type="checkbox" name="is_cool" value="0" />',
)
self.check_html(
self.widget, 'is_cool', 1,
html='<input checked="checked" type="checkbox" name="is_cool" value="1" />',
)
def test_render_check_test(self):
"""
You can pass 'check_test' to the constructor. This is a callable that
takes the value and returns True if the box should be checked.
"""
widget = CheckboxInput(check_test=lambda value: value.startswith('hello'))
self.check_html(widget, 'greeting', '', html=(
'<input type="checkbox" name="greeting" />'
))
self.check_html(widget, 'greeting', 'hello', html=(
'<input checked="checked" type="checkbox" name="greeting" value="hello" />'
))
self.check_html(widget, 'greeting', 'hello there', html=(
'<input checked="checked" type="checkbox" name="greeting" value="hello there" />'
))
self.check_html(widget, 'greeting', 'hello & goodbye', html=(
'<input checked="checked" type="checkbox" name="greeting" value="hello &amp; goodbye" />'
))
def test_render_check_exception(self):
"""
Calling check_test() shouldn't swallow exceptions (#17888).
"""
widget = CheckboxInput(
check_test=lambda value: value.startswith('hello'),
)
with self.assertRaises(AttributeError):
widget.render('greeting', True)
def test_value_from_datadict(self):
"""
The CheckboxInput widget will return False if the key is not found in
the data dictionary (because HTML form submission doesn't send any
result for unchecked checkboxes).
"""
self.assertFalse(self.widget.value_from_datadict({}, {}, 'testing'))
def test_value_from_datadict_string_int(self):
value = self.widget.value_from_datadict({'testing': '0'}, {}, 'testing')
self.assertEqual(value, True)
from django.forms import CheckboxSelectMultiple
from .base import WidgetTest
class CheckboxSelectMultipleTest(WidgetTest):
widget = CheckboxSelectMultiple()
def test_render_value(self):
self.check_html(self.widget, 'beatles', ['J'], choices=self.beatles, html=(
"""<ul>
<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li>
<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li>
<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li>
<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li>
</ul>"""
))
def test_render_value_multiple(self):
self.check_html(self.widget, 'beatles', ['J', 'P'], choices=self.beatles, html=(
"""<ul>
<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li>
<li><label><input checked="checked" type="checkbox" name="beatles" value="P" /> Paul</label></li>
<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li>
<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li>
</ul>"""
))
def test_render_none(self):
"""
If the value is None, none of the options are selected.
"""
self.check_html(self.widget, 'beatles', None, choices=self.beatles, html=(
"""<ul>
<li><label><input type="checkbox" name="beatles" value="J" /> John</label></li>
<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li>
<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li>
<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li>
</ul>"""
))
def test_nested_choices(self):
nested_choices = (
('unknown', 'Unknown'),
('Audio', (('vinyl', 'Vinyl'), ('cd', 'CD'))),
('Video', (('vhs', 'VHS'), ('dvd', 'DVD'))),
)
html = """
<ul id="media">
<li>
<label for="media_0"><input id="media_0" name="nestchoice" type="checkbox" value="unknown" /> Unknown</label>
</li>
<li>Audio<ul id="media_1">
<li>
<label for="media_1_0">
<input checked="checked" id="media_1_0" name="nestchoice" type="checkbox" value="vinyl" /> Vinyl
</label>
</li>
<li>
<label for="media_1_1"><input id="media_1_1" name="nestchoice" type="checkbox" value="cd" /> CD</label>
</li>
</ul></li>
<li>Video<ul id="media_2">
<li>
<label for="media_2_0"><input id="media_2_0" name="nestchoice" type="checkbox" value="vhs" /> VHS</label>
</li>
<li>
<label for="media_2_1">
<input checked="checked" id="media_2_1" name="nestchoice" type="checkbox" value="dvd" /> DVD
</label>
</li>
</ul></li>
</ul>
"""
self.check_html(
self.widget, 'nestchoice', ('vinyl', 'dvd'),
choices=nested_choices, attrs={'id': 'media'}, html=html,
)
def test_separate_ids(self):
"""
Each input gets a separate ID.
"""
choices = [('a', 'A'), ('b', 'B'), ('c', 'C')]
html = """
<ul id="abc">
<li>
<label for="abc_0"><input checked="checked" type="checkbox" name="letters" value="a" id="abc_0" /> A</label>
</li>
<li><label for="abc_1"><input type="checkbox" name="letters" value="b" id="abc_1" /> B</label></li>
<li>
<label for="abc_2"><input checked="checked" type="checkbox" name="letters" value="c" id="abc_2" /> C</label>
</li>
</ul>
"""
self.check_html(self.widget, 'letters', ['a', 'c'], choices=choices, attrs={'id': 'abc'}, html=html)
def test_separate_ids_constructor(self):
"""
Each input gets a separate ID when the ID is passed to the constructor.
"""
widget = CheckboxSelectMultiple(attrs={'id': 'abc'})
choices = [('a', 'A'), ('b', 'B'), ('c', 'C')]
html = """
<ul id="abc">
<li>
<label for="abc_0"><input checked="checked" type="checkbox" name="letters" value="a" id="abc_0" /> A</label>
</li>
<li><label for="abc_1"><input type="checkbox" name="letters" value="b" id="abc_1" /> B</label></li>
<li>
<label for="abc_2"><input checked="checked" type="checkbox" name="letters" value="c" id="abc_2" /> C</label>
</li>
</ul>
"""
self.check_html(widget, 'letters', ['a', 'c'], choices=choices, html=html)
from django.core.files.uploadedfile import SimpleUploadedFile
from django.forms import ClearableFileInput
from django.utils import six
from django.utils.encoding import python_2_unicode_compatible
from .base import WidgetTest
@python_2_unicode_compatible
class FakeFieldFile(object):
"""
Quacks like a FieldFile (has a .url and unicode representation), but
doesn't require us to care about storages etc.
"""
url = 'something'
def __str__(self):
return self.url
class ClearableFileInputTest(WidgetTest):
widget = ClearableFileInput()
def test_clear_input_renders(self):
"""
A ClearableFileInput with is_required False and rendered with an
initial value that is a file renders a clear checkbox.
"""
self.check_html(self.widget, 'myfile', FakeFieldFile(), html=(
"""
Currently: <a href="something">something</a>
<input type="checkbox" name="myfile-clear" id="myfile-clear_id" />
<label for="myfile-clear_id">Clear</label><br />
Change: <input type="file" name="myfile" />
"""
))
def test_html_escaped(self):
"""
A ClearableFileInput should escape name, filename, and URL
when rendering HTML (#15182).
"""
@python_2_unicode_compatible
class StrangeFieldFile(object):
url = "something?chapter=1&sect=2&copy=3&lang=en"
def __str__(self):
return '''something<div onclick="alert('oops')">.jpg'''
widget = ClearableFileInput()
field = StrangeFieldFile()
output = widget.render('my<div>file', field)
self.assertNotIn(field.url, output)
self.assertIn('href="something?chapter=1&amp;sect=2&amp;copy=3&amp;lang=en"', output)
self.assertNotIn(six.text_type(field), output)
self.assertIn('something&lt;div onclick=&quot;alert(&#39;oops&#39;)&quot;&gt;.jpg', output)
self.assertIn('my&lt;div&gt;file', output)
self.assertNotIn('my<div>file', output)
def test_html_does_not_mask_exceptions(self):
"""
A ClearableFileInput should not mask exceptions produced while
checking that it has a value.
"""
@python_2_unicode_compatible
class FailingURLFieldFile(object):
@property
def url(self):
raise RuntimeError('Canary')
def __str__(self):
return 'value'
widget = ClearableFileInput()
field = FailingURLFieldFile()
with self.assertRaisesMessage(RuntimeError, 'Canary'):
widget.render('myfile', field)
def test_clear_input_renders_only_if_not_required(self):
"""
A ClearableFileInput with is_required=False does not render a clear
checkbox.
"""
widget = ClearableFileInput()
widget.is_required = True
self.check_html(widget, 'myfile', FakeFieldFile(), html=(
"""
Currently: <a href="something">something</a> <br />
Change: <input type="file" name="myfile" />
"""
))
def test_clear_input_renders_only_if_initial(self):
"""
A ClearableFileInput instantiated with no initial value does not render
a clear checkbox.
"""
self.check_html(self.widget, 'myfile', None, html='<input type="file" name="myfile" />')
def test_clear_input_checked_returns_false(self):
"""
ClearableFileInput.value_from_datadict returns False if the clear
checkbox is checked, if not required.
"""
value = self.widget.value_from_datadict(
data={'myfile-clear': True},
files={},
name='myfile',
)
self.assertEqual(value, False)
def test_clear_input_checked_returns_false_only_if_not_required(self):
"""
ClearableFileInput.value_from_datadict never returns False if the field
is required.
"""
widget = ClearableFileInput()
widget.is_required = True
field = SimpleUploadedFile('something.txt', b'content')
value = widget.value_from_datadict(
data={'myfile-clear': True},
files={'myfile': field},
name='myfile',
)
self.assertEqual(value, field)
from datetime import date
from django.forms import DateInput
from django.test import override_settings
from django.utils import translation
from .base import WidgetTest
class DateInputTest(WidgetTest):
widget = DateInput()
def test_render_none(self):
self.check_html(self.widget, 'date', None, html='<input type="text" name="date" />')
def test_render_value(self):
d = date(2007, 9, 17)
self.assertEqual(str(d), '2007-09-17')
self.check_html(self.widget, 'date', d, html='<input type="text" name="date" value="2007-09-17" />')
self.check_html(self.widget, 'date', date(2007, 9, 17), html=(
'<input type="text" name="date" value="2007-09-17" />'
))
def test_string(self):
"""
Should be able to initialize from a string value.
"""
self.check_html(self.widget, 'date', '2007-09-17', html=(
'<input type="text" name="date" value="2007-09-17" />'
))
def test_format(self):
"""
Use 'format' to change the way a value is displayed.
"""
d = date(2007, 9, 17)
widget = DateInput(format='%d/%m/%Y', attrs={'type': 'date'})
self.check_html(widget, 'date', d, html='<input type="date" name="date" value="17/09/2007" />')
@override_settings(USE_L10N=True)
@translation.override('de-at')
def test_l10n(self):
self.check_html(
self.widget, 'date', date(2007, 9, 17),
html='<input type="text" name="date" value="17.09.2007" />',
)
from datetime import datetime
from django.forms import DateTimeInput
from django.test import override_settings
from django.utils import translation
from .base import WidgetTest
class DateTimeInputTest(WidgetTest):
widget = DateTimeInput()
def test_render_none(self):
self.check_html(self.widget, 'date', None, '<input type="text" name="date" />')
def test_render_value(self):
"""
The microseconds are trimmed on display, by default.
"""
d = datetime(2007, 9, 17, 12, 51, 34, 482548)
self.assertEqual(str(d), '2007-09-17 12:51:34.482548')
self.check_html(self.widget, 'date', d, html=(
'<input type="text" name="date" value="2007-09-17 12:51:34" />'
))
self.check_html(self.widget, 'date', datetime(2007, 9, 17, 12, 51, 34), html=(
'<input type="text" name="date" value="2007-09-17 12:51:34" />'
))
self.check_html(self.widget, 'date', datetime(2007, 9, 17, 12, 51), html=(
'<input type="text" name="date" value="2007-09-17 12:51:00" />'
))
def test_render_formatted(self):
"""
Use 'format' to change the way a value is displayed.
"""
widget = DateTimeInput(
format='%d/%m/%Y %H:%M', attrs={'type': 'datetime'},
)
d = datetime(2007, 9, 17, 12, 51, 34, 482548)
self.check_html(widget, 'date', d, html='<input type="datetime" name="date" value="17/09/2007 12:51" />')
@override_settings(USE_L10N=True)
@translation.override('de-at')
def test_l10n(self):
d = datetime(2007, 9, 17, 12, 51, 34, 482548)
self.check_html(self.widget, 'date', d, html=(
'<input type="text" name="date" value="17.09.2007 12:51:34" />'
))
@override_settings(USE_L10N=True)
@translation.override('de-at')
def test_locale_aware(self):
d = datetime(2007, 9, 17, 12, 51, 34, 482548)
with self.settings(USE_L10N=False):
self.check_html(
self.widget, 'date', d,
html='<input type="text" name="date" value="2007-09-17 12:51:34" />',
)
with translation.override('es'):
self.check_html(
self.widget, 'date', d,
html='<input type="text" name="date" value="17/09/2007 12:51:34" />',
)
from django.forms import FileInput
from .base import WidgetTest
class FileInputTest(WidgetTest):
widget = FileInput()
def test_render(self):
"""
FileInput widgets never render the value attribute. The old value
isn't useful if a form is updated or an error occurred.
"""
self.check_html(self.widget, 'email', 'test@example.com', html='<input type="file" name="email" />')
self.check_html(self.widget, 'email', '', html='<input type="file" name="email" />')
self.check_html(self.widget, 'email', None, html='<input type="file" name="email" />')
from django.forms import HiddenInput
from .base import WidgetTest
class HiddenInputTest(WidgetTest):
widget = HiddenInput()
def test_render(self):
self.check_html(self.widget, 'email', '', html='<input type="hidden" name="email" />')
from django.forms import MultipleHiddenInput
from .base import WidgetTest
class MultipleHiddenInputTest(WidgetTest):
widget = MultipleHiddenInput()
def test_render_single(self):
self.check_html(
self.widget, 'email', ['test@example.com'],
html='<input type="hidden" name="email" value="test@example.com" />',
)
def test_render_multiple(self):
self.check_html(
self.widget, 'email', ['test@example.com', 'foo@example.com'],
html=(
'<input type="hidden" name="email" value="test@example.com" />\n'
'<input type="hidden" name="email" value="foo@example.com" />'
),
)
def test_render_attrs(self):
self.check_html(
self.widget, 'email', ['test@example.com'], attrs={'class': 'fun'},
html='<input type="hidden" name="email" value="test@example.com" class="fun" />',
)
def test_render_attrs_multiple(self):
self.check_html(
self.widget, 'email', ['test@example.com', 'foo@example.com'], attrs={'class': 'fun'},
html=(
'<input type="hidden" name="email" value="test@example.com" class="fun" />\n'
'<input type="hidden" name="email" value="foo@example.com" class="fun" />'
),
)
def test_render_attrs_constructor(self):
widget = MultipleHiddenInput(attrs={'class': 'fun'})
self.check_html(widget, 'email', [], '')
self.check_html(
widget, 'email', ['foo@example.com'],
html='<input type="hidden" class="fun" value="foo@example.com" name="email" />',
)
self.check_html(
widget, 'email', ['foo@example.com', 'test@example.com'],
html=(
'<input type="hidden" class="fun" value="foo@example.com" name="email" />\n'
'<input type="hidden" class="fun" value="test@example.com" name="email" />'
),
)
self.check_html(
widget, 'email', ['foo@example.com'], attrs={'class': 'special'},
html='<input type="hidden" class="special" value="foo@example.com" name="email" />',
)
def test_render_empty(self):
self.check_html(self.widget, 'email', [], '')
def test_render_none(self):
self.check_html(self.widget, 'email', None, '')
def test_render_increment_id(self):
"""
Each input should get a separate ID.
"""
self.check_html(
self.widget, 'letters', ['a', 'b', 'c'], attrs={'id': 'hideme'},
html=(
'<input type="hidden" name="letters" value="a" id="hideme_0" />\n'
'<input type="hidden" name="letters" value="b" id="hideme_1" />\n'
'<input type="hidden" name="letters" value="c" id="hideme_2" />'
),
)
import copy
from datetime import datetime
from django.forms import (
CharField, FileInput, MultipleChoiceField, MultiValueField, MultiWidget,
RadioSelect, SelectMultiple, SplitDateTimeField, SplitDateTimeWidget,
TextInput,
)
from .base import WidgetTest
class MyMultiWidget(MultiWidget):
def decompress(self, value):
if value:
return value.split('__')
return ['', '']
class ComplexMultiWidget(MultiWidget):
def __init__(self, attrs=None):
widgets = (
TextInput(),
SelectMultiple(choices=WidgetTest.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=WidgetTest.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 DeepCopyWidget(MultiWidget):
"""
Used to test MultiWidget.__deepcopy__().
"""
def __init__(self, choices=[]):
widgets = [
RadioSelect(choices=choices),
TextInput,
]
super(DeepCopyWidget, self).__init__(widgets)
def _set_choices(self, choices):
"""
When choices are set for this widget, we want to pass those along to
the Select widget.
"""
self.widgets[0].choices = choices
def _get_choices(self):
"""
The choices for this widget are the Select widget's choices.
"""
return self.widgets[0].choices
choices = property(_get_choices, _set_choices)
class MultiWidgetTest(WidgetTest):
def test_text_inputs(self):
widget = MyMultiWidget(
widgets=(
TextInput(attrs={'class': 'big'}),
TextInput(attrs={'class': 'small'}),
)
)
self.check_html(widget, 'name', ['john', 'lennon'], html=(
'<input type="text" class="big" value="john" name="name_0" />'
'<input type="text" class="small" value="lennon" name="name_1" />'
))
self.check_html(widget, 'name', 'john__lennon', html=(
'<input type="text" class="big" value="john" name="name_0" />'
'<input type="text" class="small" value="lennon" name="name_1" />'
))
self.check_html(widget, 'name', 'john__lennon', attrs={'id': 'foo'}, html=(
'<input id="foo_0" type="text" class="big" value="john" name="name_0" />'
'<input id="foo_1" type="text" class="small" value="lennon" name="name_1" />'
))
def test_constructor_attrs(self):
widget = MyMultiWidget(
widgets=(
TextInput(attrs={'class': 'big'}),
TextInput(attrs={'class': 'small'}),
),
attrs={'id': 'bar'},
)
self.check_html(widget, 'name', ['john', 'lennon'], html=(
'<input id="bar_0" type="text" class="big" value="john" name="name_0" />'
'<input id="bar_1" type="text" class="small" value="lennon" name="name_1" />'
))
def test_needs_multipart_true(self):
"""
needs_multipart_form should be True if any widgets need it.
"""
widget = MyMultiWidget(widgets=(TextInput(), FileInput()))
self.assertTrue(widget.needs_multipart_form)
def test_needs_multipart_false(self):
"""
needs_multipart_form should be False if no widgets need it.
"""
widget = MyMultiWidget(widgets=(TextInput(), TextInput()))
self.assertFalse(widget.needs_multipart_form)
def test_nested_multiwidget(self):
"""
MultiWidgets can be composed of other MultiWidgets.
"""
widget = ComplexMultiWidget()
self.check_html(widget, 'name', 'some text,JP,2007-04-25 06:24:00', html=(
"""
<input type="text" name="name_0" value="some text" />
<select multiple="multiple" name="name_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="name_2_0" value="2007-04-25" />
<input type="text" name="name_2_1" value="06:24:00" />
"""
))
def test_deepcopy(self):
"""
MultiWidget should define __deepcopy__() (#12048).
"""
w1 = DeepCopyWidget(choices=[1, 2, 3])
w2 = copy.deepcopy(w1)
w2.choices = [4, 5, 6]
# w2 ought to be independent of w1, since MultiWidget ought
# to make a copy of its sub-widgets when it is copied.
self.assertEqual(w1.choices, [1, 2, 3])
from django.forms import NullBooleanSelect
from django.test import override_settings
from django.utils import translation
from .base import WidgetTest
class NullBooleanSelectTest(WidgetTest):
widget = NullBooleanSelect()
def test_render_true(self):
self.check_html(self.widget, 'is_cool', True, html=(
"""<select name="is_cool">
<option value="1">Unknown</option>
<option value="2" selected="selected">Yes</option>
<option value="3">No</option>
</select>"""
))
def test_render_false(self):
self.check_html(self.widget, 'is_cool', False, html=(
"""<select name="is_cool">
<option value="1">Unknown</option>
<option value="2">Yes</option>
<option value="3" selected="selected">No</option>
</select>"""
))
def test_render_none(self):
self.check_html(self.widget, 'is_cool', None, html=(
"""<select name="is_cool">
<option value="1" selected="selected">Unknown</option>
<option value="2">Yes</option>
<option value="3">No</option>
</select>"""
))
def test_render_value(self):
self.check_html(self.widget, 'is_cool', '2', html=(
"""<select name="is_cool">
<option value="1">Unknown</option>
<option value="2" selected="selected">Yes</option>
<option value="3">No</option>
</select>"""
))
@override_settings(USE_L10N=True)
def test_l10n(self):
"""
Ensure that the NullBooleanSelect widget's options are lazily
localized (#17190).
"""
widget = NullBooleanSelect()
with translation.override('de-at'):
self.check_html(widget, 'id_bool', True, html=(
"""
<select name="id_bool">
<option value="1">Unbekannt</option>
<option value="2" selected="selected">Ja</option>
<option value="3">Nein</option>
</select>
"""
))
from django.forms import PasswordInput
from .base import WidgetTest
class PasswordInputTest(WidgetTest):
widget = PasswordInput()
def test_render(self):
self.check_html(self.widget, 'password', '', html='<input type="password" name="password" />')
def test_render_ignore_value(self):
self.check_html(self.widget, 'password', 'secret', html='<input type="password" name="password" />')
def test_render_value_true(self):
"""
The render_value argument lets you specify whether the widget should
render its value. For security reasons, this is off by default.
"""
widget = PasswordInput(render_value=True)
self.check_html(widget, 'password', '', html='<input type="password" name="password" />')
self.check_html(widget, 'password', None, html='<input type="password" name="password" />')
self.check_html(
widget, 'password', 'test@example.com',
html='<input type="password" name="password" value="test@example.com" />',
)
from django.forms import RadioSelect
from .base import WidgetTest
class RadioSelectTest(WidgetTest):
widget = RadioSelect()
def test_render(self):
self.check_html(self.widget, 'beatle', 'J', choices=self.beatles, html=(
"""<ul>
<li><label><input checked="checked" type="radio" name="beatle" value="J" /> John</label></li>
<li><label><input type="radio" name="beatle" value="P" /> Paul</label></li>
<li><label><input type="radio" name="beatle" value="G" /> George</label></li>
<li><label><input type="radio" name="beatle" value="R" /> Ringo</label></li>
</ul>"""
))
def test_nested_choices(self):
nested_choices = (
('unknown', 'Unknown'),
('Audio', (('vinyl', 'Vinyl'), ('cd', 'CD'))),
('Video', (('vhs', 'VHS'), ('dvd', 'DVD'))),
)
html = """
<ul id="media">
<li>
<label for="media_0"><input id="media_0" name="nestchoice" type="radio" value="unknown" /> Unknown</label>
</li>
<li>Audio<ul id="media_1">
<li>
<label for="media_1_0"><input id="media_1_0" name="nestchoice" type="radio" value="vinyl" /> Vinyl</label>
</li>
<li><label for="media_1_1"><input id="media_1_1" name="nestchoice" type="radio" value="cd" /> CD</label></li>
</ul></li>
<li>Video<ul id="media_2">
<li><label for="media_2_0"><input id="media_2_0" name="nestchoice" type="radio" value="vhs" /> VHS</label></li>
<li>
<label for="media_2_1">
<input checked="checked" id="media_2_1" name="nestchoice" type="radio" value="dvd" /> DVD
</label>
</li>
</ul></li>
</ul>
"""
self.check_html(
self.widget, 'nestchoice', 'dvd', choices=nested_choices,
attrs={'id': 'media'}, html=html,
)
def test_constructor_attrs(self):
"""
Attributes provided at instantiation are passed to the constituent
inputs.
"""
widget = RadioSelect(attrs={'id': 'foo'})
html = """
<ul id="foo">
<li>
<label for="foo_0"><input checked="checked" type="radio" id="foo_0" value="J" name="beatle" /> John</label>
</li>
<li><label for="foo_1"><input type="radio" id="foo_1" value="P" name="beatle" /> Paul</label></li>
<li><label for="foo_2"><input type="radio" id="foo_2" value="G" name="beatle" /> George</label></li>
<li><label for="foo_3"><input type="radio" id="foo_3" value="R" name="beatle" /> Ringo</label></li>
</ul>
"""
self.check_html(widget, 'beatle', 'J', choices=self.beatles, html=html)
def test_render_attrs(self):
"""
Attributes provided at render-time are passed to the constituent
inputs.
"""
html = """
<ul id="bar">
<li>
<label for="bar_0"><input checked="checked" type="radio" id="bar_0" value="J" name="beatle" /> John</label>
</li>
<li><label for="bar_1"><input type="radio" id="bar_1" value="P" name="beatle" /> Paul</label></li>
<li><label for="bar_2"><input type="radio" id="bar_2" value="G" name="beatle" /> George</label></li>
<li><label for="bar_3"><input type="radio" id="bar_3" value="R" name="beatle" /> Ringo</label></li>
</ul>
"""
self.check_html(self.widget, 'beatle', 'J', choices=self.beatles, attrs={'id': 'bar'}, html=html)
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import copy
from django.forms import Select
from django.utils.safestring import mark_safe
from .base import WidgetTest
class SelectTest(WidgetTest):
widget = Select()
nested_widget = Select(choices=(
('outer1', 'Outer 1'),
('Group "1"', (('inner1', 'Inner 1'), ('inner2', 'Inner 2'))),
))
def test_render(self):
self.check_html(self.widget, 'beatle', 'J', choices=self.beatles, html=(
"""<select name="beatle">
<option value="J" selected="selected">John</option>
<option value="P">Paul</option>
<option value="G">George</option>
<option value="R">Ringo</option>
</select>"""
))
def test_render_none(self):
"""
If the value is None, none of the options are selected.
"""
self.check_html(self.widget, 'beatle', None, choices=self.beatles, html=(
"""<select name="beatle">
<option value="J">John</option>
<option value="P">Paul</option>
<option value="G">George</option>
<option value="R">Ringo</option>
</select>"""
))
def test_render_label_value(self):
"""
If the value corresponds to a label (but not to an option value), none
of the options are selected.
"""
self.check_html(self.widget, 'beatle', 'John', choices=self.beatles, html=(
"""<select name="beatle">
<option value="J">John</option>
<option value="P">Paul</option>
<option value="G">George</option>
<option value="R">Ringo</option>
</select>"""
))
def test_render_selected(self):
"""
Only one option can be selected (#8103).
"""
choices = [('0', '0'), ('1', '1'), ('2', '2'), ('3', '3'), ('0', 'extra')]
self.check_html(self.widget, 'choices', '0', choices=choices, html=(
"""<select name="choices">
<option value="0" selected="selected">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="0">extra</option>
</select>"""
))
def test_constructor_attrs(self):
"""
Select options shouldn't inherit the parent widget attrs.
"""
widget = Select(
attrs={'class': 'super', 'id': 'super'},
choices=[(1, 1), (2, 2), (3, 3)],
)
self.check_html(widget, 'num', 2, html=(
"""<select name="num" class="super" id="super">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
</select>"""
))
def test_compare_to_str(self):
"""
The value is compared to its str().
"""
self.check_html(
self.widget, 'num', 2,
choices=[('1', '1'), ('2', '2'), ('3', '3')],
html=(
"""<select name="num">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
</select>"""
),
)
self.check_html(
self.widget, 'num', '2',
choices=[(1, 1), (2, 2), (3, 3)],
html=(
"""<select name="num">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
</select>"""
),
)
self.check_html(
self.widget, 'num', 2,
choices=[(1, 1), (2, 2), (3, 3)],
html=(
"""<select name="num">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
</select>"""
),
)
def test_choices_constuctor(self):
widget = Select(choices=[(1, 1), (2, 2), (3, 3)])
self.check_html(widget, 'num', 2, html=(
"""<select name="num">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
</select>"""
))
def test_choices_constructor_generator(self):
"""
If choices is passed to the constructor and is a generator, it can be
iterated over multiple times without getting consumed.
"""
def get_choices():
for i in range(5):
yield (i, i)
widget = Select(choices=get_choices())
self.check_html(widget, 'num', 2, html=(
"""<select name="num">
<option value="0">0</option>
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>"""
))
self.check_html(widget, 'num', 3, html=(
"""<select name="num">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3" selected="selected">3</option>
<option value="4">4</option>
</select>"""
))
def test_choices_constuctor_and_render(self):
"""
If 'choices' is passed to both the constructor and render(), then
they'll both be in the output.
"""
widget = Select(choices=[(1, 1), (2, 2), (3, 3)])
self.check_html(widget, 'num', 2, choices=[(4, 4), (5, 5)], html=(
"""<select name="num">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>"""
))
def test_choices_escaping(self):
choices = (('bad', 'you & me'), ('good', mark_safe('you &gt; me')))
self.check_html(self.widget, 'escape', None, choices=choices, html=(
"""<select name="escape">
<option value="bad">you &amp; me</option>
<option value="good">you &gt; me</option>
</select>"""
))
def test_choices_unicode(self):
self.check_html(
self.widget, 'email', 'ŠĐĆŽćžšđ',
choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')],
html=(
"""<select name="email">
<option value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" selected="selected">
\u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111
</option>
<option value="\u0107\u017e\u0161\u0111">abc\u0107\u017e\u0161\u0111</option>
</select>"""
),
)
def test_choices_optgroup(self):
"""
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>"""
))
def test_choices_select_outer(self):
self.check_html(self.nested_widget, 'nestchoice', 'outer1', html=(
"""<select name="nestchoice">
<option value="outer1" selected="selected">Outer 1</option>
<optgroup label="Group &quot;1&quot;">
<option value="inner1">Inner 1</option>
<option value="inner2">Inner 2</option>
</optgroup>
</select>"""
))
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="selected">Inner 1</option>
<option value="inner2">Inner 2</option>
</optgroup>
</select>"""
))
def test_deepcopy(self):
"""
__deepcopy__() should copy all attributes properly (#25085).
"""
widget = Select()
obj = copy.deepcopy(widget)
self.assertIsNot(widget, obj)
self.assertEqual(widget.choices, obj.choices)
self.assertIsNot(widget.choices, obj.choices)
self.assertEqual(widget.attrs, obj.attrs)
self.assertIsNot(widget.attrs, obj.attrs)
from django.forms import SelectMultiple
from .base import WidgetTest
class SelectMultipleTest(WidgetTest):
widget = SelectMultiple()
numeric_choices = (('0', '0'), ('1', '1'), ('2', '2'), ('3', '3'), ('0', 'extra'))
def test_render_selected(self):
self.check_html(self.widget, 'beatles', ['J'], choices=self.beatles, html=(
"""<select multiple="multiple" name="beatles">
<option value="J" selected="selected">John</option>
<option value="P">Paul</option>
<option value="G">George</option>
<option value="R">Ringo</option>
</select>"""
))
def test_render_multiple_selected(self):
self.check_html(self.widget, 'beatles', ['J', 'P'], choices=self.beatles, html=(
"""<select multiple="multiple" name="beatles">
<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>"""
))
def test_render_none(self):
"""
If the value is None, none of the options are selected.
"""
self.check_html(self.widget, 'beatles', None, choices=self.beatles, html=(
"""<select multiple="multiple" name="beatles">
<option value="J">John</option>
<option value="P">Paul</option>
<option value="G">George</option>
<option value="R">Ringo</option>
</select>"""
))
def test_render_value_label(self):
"""
If the value corresponds to a label (but not to an option value), none
of the options are selected.
"""
self.check_html(self.widget, 'beatles', ['John'], choices=self.beatles, html=(
"""<select multiple="multiple" name="beatles">
<option value="J">John</option>
<option value="P">Paul</option>
<option value="G">George</option>
<option value="R">Ringo</option>
</select>"""
))
def test_multiple_options_same_value(self):
"""
Multiple options with the same value can be selected (#8103).
"""
self.check_html(self.widget, 'choices', ['0'], choices=self.numeric_choices, html=(
"""<select multiple="multiple" name="choices">
<option value="0" selected="selected">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="0" selected="selected">extra</option>
</select>"""
))
def test_multiple_values_invalid(self):
"""
If multiple values are given, but some of them are not valid, the valid
ones are selected.
"""
self.check_html(self.widget, 'beatles', ['J', 'G', 'foo'], choices=self.beatles, html=(
"""<select multiple="multiple" name="beatles">
<option value="J" selected="selected">John</option>
<option value="P">Paul</option>
<option value="G" selected="selected">George</option>
<option value="R">Ringo</option>
</select>"""
))
def test_compare_string(self):
choices = [('1', '1'), ('2', '2'), ('3', '3')]
self.check_html(self.widget, 'nums', [2], choices=choices, html=(
"""<select multiple="multiple" name="nums">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
</select>"""
))
self.check_html(self.widget, 'nums', ['2'], choices=choices, html=(
"""<select multiple="multiple" name="nums">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
</select>"""
))
self.check_html(self.widget, 'nums', [2], choices=choices, html=(
"""<select multiple="multiple" name="nums">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
</select>"""
))
def test_optgroup_select_multiple(self):
widget = SelectMultiple(choices=(
('outer1', 'Outer 1'),
('Group "1"', (('inner1', 'Inner 1'), ('inner2', 'Inner 2'))),
))
self.check_html(widget, 'nestchoice', ['outer1', 'inner2'], html=(
"""<select multiple="multiple" name="nestchoice">
<option value="outer1" selected="selected">Outer 1</option>
<optgroup label="Group &quot;1&quot;">
<option value="inner1">Inner 1</option>
<option value="inner2" selected="selected">Inner 2</option>
</optgroup>
</select>"""
))
from datetime import date, datetime, time
from django.forms import SplitDateTimeWidget
from .base import WidgetTest
class SplitDateTimeWidgetTest(WidgetTest):
widget = SplitDateTimeWidget()
def test_render_empty(self):
self.check_html(self.widget, 'date', '', html=(
'<input type="text" name="date_0" /><input type="text" name="date_1" />'
))
def test_render_none(self):
self.check_html(self.widget, 'date', None, html=(
'<input type="text" name="date_0" /><input type="text" name="date_1" />'
))
def test_render_datetime(self):
self.check_html(self.widget, 'date', datetime(2006, 1, 10, 7, 30), html=(
'<input type="text" name="date_0" value="2006-01-10" />'
'<input type="text" name="date_1" value="07:30:00" />'
))
def test_render_date_and_time(self):
self.check_html(self.widget, 'date', [date(2006, 1, 10), time(7, 30)], html=(
'<input type="text" name="date_0" value="2006-01-10" />'
'<input type="text" name="date_1" value="07:30:00" />'
))
def test_constructor_attrs(self):
widget = SplitDateTimeWidget(attrs={'class': 'pretty'})
self.check_html(widget, 'date', datetime(2006, 1, 10, 7, 30), html=(
'<input type="text" class="pretty" value="2006-01-10" name="date_0" />'
'<input type="text" class="pretty" value="07:30:00" name="date_1" />'
))
def test_formatting(self):
"""
Use 'date_format' and 'time_format' to change the way a value is
displayed.
"""
widget = SplitDateTimeWidget(
date_format='%d/%m/%Y', time_format='%H:%M',
)
self.check_html(widget, 'date', datetime(2006, 1, 10, 7, 30), html=(
'<input type="text" name="date_0" value="10/01/2006" />'
'<input type="text" name="date_1" value="07:30" />'
))
from datetime import datetime
from django.forms import SplitHiddenDateTimeWidget
from django.test import override_settings
from django.utils import translation
from .base import WidgetTest
class SplitHiddenDateTimeWidgetTest(WidgetTest):
widget = SplitHiddenDateTimeWidget()
def test_render_empty(self):
self.check_html(self.widget, 'date', '', html=(
'<input type="hidden" name="date_0" /><input type="hidden" name="date_1" />'
))
def test_render_value(self):
d = datetime(2007, 9, 17, 12, 51, 34, 482548)
self.check_html(self.widget, 'date', d, html=(
'<input type="hidden" name="date_0" value="2007-09-17" />'
'<input type="hidden" name="date_1" value="12:51:34" />'
))
self.check_html(self.widget, 'date', datetime(2007, 9, 17, 12, 51, 34), html=(
'<input type="hidden" name="date_0" value="2007-09-17" />'
'<input type="hidden" name="date_1" value="12:51:34" />'
))
self.check_html(self.widget, 'date', datetime(2007, 9, 17, 12, 51), html=(
'<input type="hidden" name="date_0" value="2007-09-17" />'
'<input type="hidden" name="date_1" value="12:51:00" />'
))
@override_settings(USE_L10N=True)
@translation.override('de-at')
def test_l10n(self):
d = datetime(2007, 9, 17, 12, 51)
self.check_html(self.widget, 'date', d, html=(
"""
<input type="hidden" name="date_0" value="17.09.2007" />
<input type="hidden" name="date_1" value="12:51:00" />
"""
))
from django.forms import Textarea
from django.utils.safestring import mark_safe
from .base import WidgetTest
class TextareaTest(WidgetTest):
widget = Textarea()
def test_render(self):
self.check_html(self.widget, 'msg', 'value', html=(
'<textarea rows="10" cols="40" name="msg">value</textarea>'
))
def test_render_required(self):
widget = Textarea()
widget.is_required = True
self.check_html(widget, 'msg', 'value', html='<textarea rows="10" cols="40" name="msg">value</textarea>')
def test_render_empty(self):
self.check_html(self.widget, 'msg', '', html='<textarea rows="10" cols="40" name="msg"></textarea>')
def test_render_none(self):
self.check_html(self.widget, 'msg', None, html='<textarea rows="10" cols="40" name="msg"></textarea>')
def test_escaping(self):
self.check_html(self.widget, 'msg', 'some "quoted" & ampersanded value', html=(
'<textarea rows="10" cols="40" name="msg">some &quot;quoted&quot; &amp; ampersanded value</textarea>'
))
def test_mark_safe(self):
self.check_html(self.widget, 'msg', mark_safe('pre &quot;quoted&quot; value'), html=(
'<textarea rows="10" cols="40" name="msg">pre &quot;quoted&quot; value</textarea>'
))
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.forms import TextInput
from django.utils.safestring import mark_safe
from .base import WidgetTest
class TextInputTest(WidgetTest):
widget = TextInput()
def test_render(self):
self.check_html(self.widget, 'email', '', html='<input type="text" name="email" />')
def test_render_none(self):
self.check_html(self.widget, 'email', None, html='<input type="text" name="email" />')
def test_render_value(self):
self.check_html(self.widget, 'email', 'test@example.com', html=(
'<input type="text" name="email" value="test@example.com" />'
))
def test_render_boolean(self):
"""
Boolean values are rendered to their string forms ("True" and
"False").
"""
self.check_html(self.widget, 'get_spam', False, html=(
'<input type="text" name="get_spam" value="False" />'
))
self.check_html(self.widget, 'get_spam', True, html=(
'<input type="text" name="get_spam" value="True" />'
))
def test_render_quoted(self):
self.check_html(
self.widget, 'email', 'some "quoted" & ampersanded value',
html='<input type="text" name="email" value="some &quot;quoted&quot; &amp; ampersanded value" />',
)
def test_render_custom_attrs(self):
self.check_html(
self.widget, 'email', 'test@example.com', attrs={'class': 'fun'},
html='<input type="text" name="email" value="test@example.com" class="fun" />',
)
def test_render_unicode(self):
self.check_html(
self.widget, 'email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'},
html=(
'<input type="text" name="email" '
'value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" class="fun" />'
),
)
def test_constructor_attrs(self):
widget = TextInput(attrs={'class': 'fun', 'type': 'email'})
self.check_html(widget, 'email', '', html='<input type="email" class="fun" name="email" />')
self.check_html(
widget, 'email', 'foo@example.com',
html='<input type="email" class="fun" value="foo@example.com" name="email" />',
)
def test_attrs_precedence(self):
"""
`attrs` passed to render() get precedence over those passed to the
constructor
"""
widget = TextInput(attrs={'class': 'pretty'})
self.check_html(
widget, 'email', '', attrs={'class': 'special'},
html='<input type="text" class="special" name="email" />',
)
def test_attrs_safestring(self):
widget = TextInput(attrs={'onBlur': mark_safe("function('foo')")})
self.check_html(widget, 'email', '', html='<input onBlur="function(\'foo\')" type="text" name="email" />')
from datetime import time
from django.forms import TimeInput
from django.test import override_settings
from django.utils import translation
from .base import WidgetTest
class TimeInputTest(WidgetTest):
widget = TimeInput()
def test_render_none(self):
self.check_html(self.widget, 'time', None, html='<input type="text" name="time" />')
def test_render_value(self):
"""
The microseconds are trimmed on display, by default.
"""
t = time(12, 51, 34, 482548)
self.assertEqual(str(t), '12:51:34.482548')
self.check_html(self.widget, 'time', t, html='<input type="text" name="time" value="12:51:34" />')
self.check_html(self.widget, 'time', time(12, 51, 34), html=(
'<input type="text" name="time" value="12:51:34" />'
))
self.check_html(self.widget, 'time', time(12, 51), html=(
'<input type="text" name="time" value="12:51:00" />'
))
def test_string(self):
"""
We should be able to initialize from a unicode value.
"""
self.check_html(self.widget, 'time', '13:12:11', html=(
'<input type="text" name="time" value="13:12:11" />'
))
def test_format(self):
"""
Use 'format' to change the way a value is displayed.
"""
t = time(12, 51, 34, 482548)
widget = TimeInput(format='%H:%M', attrs={'type': 'time'})
self.check_html(widget, 'time', t, html='<input type="time" name="time" value="12:51" />')
@override_settings(USE_L10N=True)
@translation.override('de-at')
def test_l10n(self):
t = time(12, 51, 34, 482548)
self.check_html(self.widget, 'time', t, html='<input type="text" name="time" value="12:51:34" />')
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment