1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
|
from django.core.files.uploadedfile import SimpleUploadedFile
from django.forms import ClearableFileInput, MultiWidget
from .base import WidgetTest
class FakeFieldFile:
"""
Quacks like a FieldFile (has a .url and string 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).
"""
class StrangeFieldFile:
url = "something?chapter=1§=2©=3&lang=en"
def __str__(self):
return '''something<div onclick="alert('oops')">.jpg'''
self.check_html(ClearableFileInput(), 'my<div>file', StrangeFieldFile(), html=(
"""
Currently: <a href="something?chapter=1&sect=2&copy=3&lang=en">
something<div onclick="alert('oops')">.jpg</a>
<input type="checkbox" name="my<div>file-clear" id="my<div>file-clear_id">
<label for="my<div>file-clear_id">Clear</label><br>
Change: <input type="file" name="my<div>file">
"""
))
def test_clear_input_renders_only_if_not_required(self):
"""
A ClearableFileInput with is_required=True 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_render_disabled(self):
self.check_html(
self.widget,
'myfile',
FakeFieldFile(),
attrs={'disabled': True},
html=(
'Currently: <a href="something">something</a>'
'<input type="checkbox" name="myfile-clear" '
'id="myfile-clear_id" disabled>'
'<label for="myfile-clear_id">Clear</label><br>'
'Change: <input type="file" name="myfile" disabled>'
),
)
def test_render_as_subwidget(self):
"""A ClearableFileInput as a subwidget of MultiWidget."""
widget = MultiWidget(widgets=(self.widget,))
self.check_html(widget, 'myfile', [FakeFieldFile()], html=(
"""
Currently: <a href="something">something</a>
<input type="checkbox" name="myfile_0-clear" id="myfile_0-clear_id">
<label for="myfile_0-clear_id">Clear</label><br>
Change: <input type="file" name="myfile_0">
"""
))
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.assertIs(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)
def test_html_does_not_mask_exceptions(self):
"""
A ClearableFileInput should not mask exceptions produced while
checking that it has a value.
"""
class FailingURLFieldFile:
@property
def url(self):
raise ValueError('Canary')
def __str__(self):
return 'value'
with self.assertRaisesMessage(ValueError, 'Canary'):
self.widget.render('myfile', FailingURLFieldFile())
def test_url_as_property(self):
class URLFieldFile:
@property
def url(self):
return 'https://www.python.org/'
def __str__(self):
return 'value'
html = self.widget.render('myfile', URLFieldFile())
self.assertInHTML('<a href="https://www.python.org/">value</a>', html)
def test_return_false_if_url_does_not_exists(self):
class NoURLFieldFile:
def __str__(self):
return 'value'
html = self.widget.render('myfile', NoURLFieldFile())
self.assertHTMLEqual(html, '<input name="myfile" type="file">')
def test_use_required_attribute(self):
# False when initial data exists. The file input is left blank by the
# user to keep the existing, initial value.
self.assertIs(self.widget.use_required_attribute(None), True)
self.assertIs(self.widget.use_required_attribute('resume.txt'), False)
def test_value_omitted_from_data(self):
widget = ClearableFileInput()
self.assertIs(widget.value_omitted_from_data({}, {}, 'field'), True)
self.assertIs(widget.value_omitted_from_data({}, {'field': 'x'}, 'field'), False)
self.assertIs(widget.value_omitted_from_data({'field-clear': 'y'}, {}, 'field'), False)
def test_multiple_error(self):
msg = "ClearableFileInput doesn't support uploading multiple files."
with self.assertRaisesMessage(ValueError, msg):
ClearableFileInput(attrs={"multiple": True})
|