test_clearablefileinput.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. from django.core.files.uploadedfile import SimpleUploadedFile
  2. from django.forms import ClearableFileInput
  3. from .base import WidgetTest
  4. class FakeFieldFile:
  5. """
  6. Quacks like a FieldFile (has a .url and string representation), but
  7. doesn't require us to care about storages etc.
  8. """
  9. url = 'something'
  10. def __str__(self):
  11. return self.url
  12. class ClearableFileInputTest(WidgetTest):
  13. widget = ClearableFileInput()
  14. def test_clear_input_renders(self):
  15. """
  16. A ClearableFileInput with is_required False and rendered with an
  17. initial value that is a file renders a clear checkbox.
  18. """
  19. self.check_html(self.widget, 'myfile', FakeFieldFile(), html=(
  20. """
  21. Currently: <a href="something">something</a>
  22. <input type="checkbox" name="myfile-clear" id="myfile-clear_id" />
  23. <label for="myfile-clear_id">Clear</label><br />
  24. Change: <input type="file" name="myfile" />
  25. """
  26. ))
  27. def test_html_escaped(self):
  28. """
  29. A ClearableFileInput should escape name, filename, and URL
  30. when rendering HTML (#15182).
  31. """
  32. class StrangeFieldFile:
  33. url = "something?chapter=1&sect=2&copy=3&lang=en"
  34. def __str__(self):
  35. return '''something<div onclick="alert('oops')">.jpg'''
  36. self.check_html(ClearableFileInput(), 'my<div>file', StrangeFieldFile(), html=(
  37. """
  38. Currently: <a href="something?chapter=1&amp;sect=2&amp;copy=3&amp;lang=en">
  39. something&lt;div onclick=&quot;alert(&#39;oops&#39;)&quot;&gt;.jpg</a>
  40. <input type="checkbox" name="my&lt;div&gt;file-clear" id="my&lt;div&gt;file-clear_id" />
  41. <label for="my&lt;div&gt;file-clear_id">Clear</label><br />
  42. Change: <input type="file" name="my&lt;div&gt;file" />
  43. """
  44. ))
  45. def test_clear_input_renders_only_if_not_required(self):
  46. """
  47. A ClearableFileInput with is_required=False does not render a clear
  48. checkbox.
  49. """
  50. widget = ClearableFileInput()
  51. widget.is_required = True
  52. self.check_html(widget, 'myfile', FakeFieldFile(), html=(
  53. """
  54. Currently: <a href="something">something</a> <br />
  55. Change: <input type="file" name="myfile" />
  56. """
  57. ))
  58. def test_clear_input_renders_only_if_initial(self):
  59. """
  60. A ClearableFileInput instantiated with no initial value does not render
  61. a clear checkbox.
  62. """
  63. self.check_html(self.widget, 'myfile', None, html='<input type="file" name="myfile" />')
  64. def test_clear_input_checked_returns_false(self):
  65. """
  66. ClearableFileInput.value_from_datadict returns False if the clear
  67. checkbox is checked, if not required.
  68. """
  69. value = self.widget.value_from_datadict(
  70. data={'myfile-clear': True},
  71. files={},
  72. name='myfile',
  73. )
  74. self.assertIs(value, False)
  75. def test_clear_input_checked_returns_false_only_if_not_required(self):
  76. """
  77. ClearableFileInput.value_from_datadict never returns False if the field
  78. is required.
  79. """
  80. widget = ClearableFileInput()
  81. widget.is_required = True
  82. field = SimpleUploadedFile('something.txt', b'content')
  83. value = widget.value_from_datadict(
  84. data={'myfile-clear': True},
  85. files={'myfile': field},
  86. name='myfile',
  87. )
  88. self.assertEqual(value, field)
  89. def test_html_does_not_mask_exceptions(self):
  90. """
  91. A ClearableFileInput should not mask exceptions produced while
  92. checking that it has a value.
  93. """
  94. class FailingURLFieldFile:
  95. @property
  96. def url(self):
  97. raise ValueError('Canary')
  98. def __str__(self):
  99. return 'value'
  100. with self.assertRaisesMessage(ValueError, 'Canary'):
  101. self.widget.render('myfile', FailingURLFieldFile())
  102. def test_url_as_property(self):
  103. class URLFieldFile:
  104. @property
  105. def url(self):
  106. return 'https://www.python.org/'
  107. def __str__(self):
  108. return 'value'
  109. html = self.widget.render('myfile', URLFieldFile())
  110. self.assertInHTML('<a href="https://www.python.org/">value</a>', html)
  111. def test_return_false_if_url_does_not_exists(self):
  112. class NoURLFieldFile:
  113. def __str__(self):
  114. return 'value'
  115. html = self.widget.render('myfile', NoURLFieldFile())
  116. self.assertHTMLEqual(html, '<input name="myfile" type="file" />')
  117. def test_use_required_attribute(self):
  118. # False when initial data exists. The file input is left blank by the
  119. # user to keep the existing, initial value.
  120. self.assertIs(self.widget.use_required_attribute(None), True)
  121. self.assertIs(self.widget.use_required_attribute('resume.txt'), False)