test_forms.py 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. import json
  2. import os
  3. from contextlib import contextmanager
  4. import pytest
  5. from django.forms import ClearableFileInput
  6. from selenium.common.exceptions import NoSuchElementException
  7. from selenium.webdriver.common.by import By
  8. from selenium.webdriver.support.expected_conditions import staleness_of
  9. from selenium.webdriver.support.wait import WebDriverWait
  10. from s3file.storages import storage
  11. from tests.testapp.forms import UploadForm
  12. try:
  13. from django.urls import reverse
  14. except ImportError:
  15. # Django 1.8 support
  16. from django.core.urlresolvers import reverse
  17. @contextmanager
  18. def wait_for_page_load(driver, timeout=30):
  19. old_page = driver.find_element(By.TAG_NAME, "html")
  20. yield
  21. WebDriverWait(driver, timeout).until(staleness_of(old_page))
  22. class TestS3FileInput:
  23. @property
  24. def url(self):
  25. return reverse("upload")
  26. def test_value_from_datadict(self, freeze_upload_folder, client, upload_file):
  27. with open(upload_file) as f:
  28. uploaded_file = storage.save(freeze_upload_folder / "test.jpg", f)
  29. response = client.post(
  30. reverse("upload"),
  31. {
  32. "file": f"custom/location/{uploaded_file}",
  33. "file-s3f-signature": "FxQXie3wnVnCUFqGzFZ8DCFKAXFA3bnQ8tE96U11o80",
  34. "s3file": "file",
  35. },
  36. )
  37. assert response.status_code == 201
  38. def test_value_from_datadict_initial_data(self, filemodel):
  39. form = UploadForm(instance=filemodel)
  40. assert filemodel.file.name in form.as_p(), form.as_p()
  41. assert not form.is_valid()
  42. def test_file_does_not_exist_no_fallback(self, filemodel):
  43. form = UploadForm(
  44. data={"file": "foo.bar", "s3file": "file"},
  45. instance=filemodel,
  46. )
  47. assert form.is_valid()
  48. assert form.cleaned_data["file"] == filemodel.file
  49. def test_initial_no_file_uploaded(self, filemodel):
  50. form = UploadForm(data={"file": ""}, instance=filemodel)
  51. assert form.is_valid(), form.errors
  52. assert not form.has_changed()
  53. assert form.cleaned_data["file"] == filemodel.file
  54. def test_initial_fallback(self, filemodel):
  55. form = UploadForm(data={"file": ""}, instance=filemodel)
  56. assert form.is_valid()
  57. assert form.cleaned_data["file"] == filemodel.file
  58. def test_clear(self, filemodel):
  59. form = UploadForm(data={"file-clear": "1"}, instance=filemodel)
  60. assert form.is_valid()
  61. assert not form.cleaned_data["file"]
  62. def test_build_attr(self, freeze_upload_folder):
  63. assert set(ClearableFileInput().build_attrs({}).keys()) == {
  64. "class",
  65. "data-url",
  66. "data-fields-x-amz-algorithm",
  67. "data-fields-x-amz-date",
  68. "data-fields-x-amz-signature",
  69. "data-fields-x-amz-credential",
  70. "data-fields-policy",
  71. "data-fields-key",
  72. "data-s3f-signature",
  73. }
  74. assert (
  75. ClearableFileInput().build_attrs({})["data-s3f-signature"]
  76. == "VRIPlI1LCjUh1EtplrgxQrG8gSAaIwT48mMRlwaCytI"
  77. )
  78. assert ClearableFileInput().build_attrs({})["class"] == "s3file"
  79. assert (
  80. ClearableFileInput().build_attrs({"class": "my-class"})["class"]
  81. == "my-class s3file"
  82. )
  83. def test_get_conditions(self, freeze_upload_folder):
  84. conditions = ClearableFileInput().get_conditions(None)
  85. assert all(
  86. condition in conditions
  87. for condition in [
  88. {"bucket": "test-bucket"},
  89. {"success_action_status": "201"},
  90. ["starts-with", "$key", "custom/location/tmp/s3file"],
  91. ["starts-with", "$Content-Type", ""],
  92. ]
  93. ), conditions
  94. def test_accept(self):
  95. widget = ClearableFileInput()
  96. assert "accept" not in widget.render(name="file", value="test.jpg")
  97. assert ["starts-with", "$Content-Type", ""] in widget.get_conditions(None)
  98. widget = ClearableFileInput(attrs={"accept": "image/*"})
  99. assert 'accept="image/*"' in widget.render(name="file", value="test.jpg")
  100. assert ["starts-with", "$Content-Type", "image/"] in widget.get_conditions(
  101. "image/*"
  102. )
  103. widget = ClearableFileInput(attrs={"accept": "image/jpeg"})
  104. assert 'accept="image/jpeg"' in widget.render(name="file", value="test.jpg")
  105. assert {"Content-Type": "image/jpeg"} in widget.get_conditions("image/jpeg")
  106. widget = ClearableFileInput(attrs={"accept": "application/pdf,image/*"})
  107. assert 'accept="application/pdf,image/*"' in widget.render(
  108. name="file",
  109. value="test.jpg",
  110. )
  111. assert ["starts-with", "$Content-Type", ""] in widget.get_conditions(
  112. "application/pdf,image/*"
  113. )
  114. assert {"Content-Type": "application/pdf"} not in widget.get_conditions(
  115. "application/pdf,image/*"
  116. )
  117. def test_no_js_error(self, driver, live_server):
  118. driver.get(live_server + self.url)
  119. with pytest.raises(NoSuchElementException):
  120. error = driver.find_element(By.XPATH, "//body[@JSError]")
  121. pytest.fail(error.get_attribute("JSError"))
  122. def test_file_insert(
  123. self, request, driver, live_server, upload_file, freeze_upload_folder
  124. ):
  125. driver.get(live_server + self.url)
  126. file_input = driver.find_element(By.XPATH, "//input[@name='file']")
  127. file_input.send_keys(upload_file)
  128. assert file_input.get_attribute("name") == "file"
  129. with wait_for_page_load(driver, timeout=10):
  130. file_input.submit()
  131. assert storage.exists("tmp/s3file/%s.txt" % request.node.name)
  132. with pytest.raises(NoSuchElementException):
  133. error = driver.find_element(By.XPATH, "//body[@JSError]")
  134. pytest.fail(error.get_attribute("JSError"))
  135. def test_file_insert_submit_value(
  136. self, driver, live_server, upload_file, freeze_upload_folder
  137. ):
  138. driver.get(live_server + self.url)
  139. file_input = driver.find_element(By.XPATH, "//input[@name='file']")
  140. file_input.send_keys(upload_file)
  141. assert file_input.get_attribute("name") == "file"
  142. save_button = driver.find_element(By.XPATH, "//input[@name='save']")
  143. with wait_for_page_load(driver, timeout=10):
  144. save_button.click()
  145. assert "save" in driver.page_source
  146. driver.get(live_server + self.url)
  147. file_input = driver.find_element(By.XPATH, "//input[@name='file']")
  148. file_input.send_keys(upload_file)
  149. assert file_input.get_attribute("name") == "file"
  150. save_button = driver.find_element(By.XPATH, "//button[@name='save_continue']")
  151. with wait_for_page_load(driver, timeout=10):
  152. save_button.click()
  153. assert "save_continue" in driver.page_source
  154. assert "continue_value" in driver.page_source
  155. def test_progress(self, driver, live_server, upload_file, freeze_upload_folder):
  156. driver.get(live_server + self.url)
  157. file_input = driver.find_element(By.XPATH, "//input[@name='file']")
  158. file_input.send_keys(upload_file)
  159. assert file_input.get_attribute("name") == "file"
  160. save_button = driver.find_element(By.XPATH, "//input[@name='save']")
  161. with wait_for_page_load(driver, timeout=10):
  162. save_button.click()
  163. assert "save" in driver.page_source
  164. driver.get(live_server + self.url)
  165. file_input = driver.find_element(By.XPATH, "//input[@name='file']")
  166. file_input.send_keys(upload_file)
  167. assert file_input.get_attribute("name") == "file"
  168. save_button = driver.find_element(By.XPATH, "//button[@name='save_continue']")
  169. with wait_for_page_load(driver, timeout=10):
  170. save_button.click()
  171. response = json.loads(driver.find_elements(By.CSS_SELECTOR, "pre")[0].text)
  172. assert response["POST"]["progress"] == "1"
  173. def test_multi_file(
  174. self,
  175. driver,
  176. live_server,
  177. freeze_upload_folder,
  178. upload_file,
  179. another_upload_file,
  180. yet_another_upload_file,
  181. ):
  182. driver.get(live_server + self.url)
  183. file_input = driver.find_element(By.XPATH, "//input[@name='file']")
  184. file_input.send_keys(
  185. " \n ".join(
  186. [
  187. str(freeze_upload_folder / upload_file),
  188. str(freeze_upload_folder / another_upload_file),
  189. ]
  190. )
  191. )
  192. file_input = driver.find_element(By.XPATH, "//input[@name='other_file']")
  193. file_input.send_keys(str(freeze_upload_folder / yet_another_upload_file))
  194. save_button = driver.find_element(By.XPATH, "//input[@name='save']")
  195. with wait_for_page_load(driver, timeout=10):
  196. save_button.click()
  197. response = json.loads(driver.find_elements(By.CSS_SELECTOR, "pre")[0].text)
  198. assert response["FILES"] == {
  199. "file": [
  200. os.path.basename(upload_file),
  201. os.path.basename(another_upload_file),
  202. ],
  203. "other_file": [os.path.basename(yet_another_upload_file)],
  204. }
  205. def test_media(self):
  206. assert ClearableFileInput().media._js == ["s3file/js/s3file.js"]
  207. def test_upload_folder(self):
  208. assert "custom/location/tmp/s3file/" in ClearableFileInput().upload_folder
  209. assert len(os.path.basename(ClearableFileInput().upload_folder)) == 22