test_uploading_css.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. import os
  2. import pytest
  3. from django.core.files.uploadedfile import UploadedFile
  4. from django.urls import reverse
  5. from ....test import assert_has_error_message
  6. TESTS_DIR = os.path.dirname(os.path.abspath(__file__))
  7. @pytest.fixture
  8. def css_file():
  9. return os.path.join(TESTS_DIR, "css", "test.css")
  10. @pytest.fixture
  11. def other_file():
  12. return os.path.join(TESTS_DIR, "images", "test.png")
  13. @pytest.fixture
  14. def hashed_css_file():
  15. return os.path.join(TESTS_DIR, "css", "test.4846cb3b.css")
  16. @pytest.fixture
  17. def upload(admin_client):
  18. def post_upload(theme, asset_files=None):
  19. url = reverse("misago:admin:themes:upload-css", kwargs={"pk": theme.pk})
  20. if asset_files is not None:
  21. data = asset_files if isinstance(asset_files, list) else [asset_files]
  22. else:
  23. data = None
  24. return admin_client.post(url, {"assets": data})
  25. return post_upload
  26. def test_css_file_can_be_uploaded(upload, theme, css_file):
  27. with open(css_file) as fp:
  28. upload(theme, fp)
  29. assert theme.css.exists()
  30. def test_multiple_css_files_can_be_uploaded_at_once(
  31. upload, theme, css_file, hashed_css_file
  32. ):
  33. with open(css_file) as fp1:
  34. with open(hashed_css_file) as fp2:
  35. upload(theme, [fp1, fp2])
  36. assert theme.css.exists()
  37. assert theme.css.count() == 2
  38. def test_css_files_uploaded_one_after_another_are_ordered(
  39. upload, theme, css_file, hashed_css_file
  40. ):
  41. with open(css_file) as fp:
  42. upload(theme, fp)
  43. first_css = theme.css.last()
  44. assert first_css.name == str(css_file).split("/")[-1]
  45. assert first_css.order == 0
  46. with open(hashed_css_file) as fp:
  47. upload(theme, fp)
  48. last_css = theme.css.last()
  49. assert last_css.name == str(hashed_css_file).split("/")[-1]
  50. assert last_css.order == 1
  51. def test_multiple_css_files_uploaded_at_once_are_ordered(
  52. upload, theme, css_file, hashed_css_file
  53. ):
  54. with open(css_file) as fp1:
  55. with open(hashed_css_file) as fp2:
  56. upload(theme, [fp1, fp2])
  57. assert list(theme.css.values_list("name", flat=True)) == [
  58. str(css_file).split("/")[-1],
  59. str(hashed_css_file).split("/")[-1],
  60. ]
  61. assert list(theme.css.values_list("order", flat=True)) == [0, 1]
  62. def test_uploaded_file_is_rejected_if_its_not_css_file(upload, theme, other_file):
  63. with open(other_file, "rb") as fp:
  64. upload(theme, fp)
  65. assert not theme.css.exists()
  66. def test_error_message_is_set_if_uploaded_file_is_not_css(upload, theme, other_file):
  67. with open(other_file, "rb") as fp:
  68. response = upload(theme, fp)
  69. assert_has_error_message(response)
  70. def test_if_some_of_uploaded_files_are_incorrect_only_css_files_are_added_to_theme(
  71. upload, theme, css_file, other_file
  72. ):
  73. with open(css_file) as fp1:
  74. with open(other_file, "rb") as fp2:
  75. upload(theme, [fp1, fp2])
  76. assert theme.css.exists()
  77. assert theme.css.count() == 1
  78. css = theme.css.last()
  79. expected_filename = str(css_file).split("/")[-1]
  80. assert css.name == expected_filename
  81. def test_css_file_is_uploaded_to_theme_directory(upload, theme, css_file):
  82. with open(css_file) as fp:
  83. upload(theme, fp)
  84. css = theme.css.last()
  85. assert theme.dirname in str(css.source_file)
  86. def test_css_file_name_is_set_as_asset_name(upload, theme, css_file):
  87. with open(css_file) as fp:
  88. upload(theme, fp)
  89. css = theme.css.last()
  90. expected_filename = str(css_file).split("/")[-1]
  91. assert css.name == expected_filename
  92. def test_hash_is_added_to_uploaded_css_file_name(
  93. upload, theme, css_file, hashed_css_file
  94. ):
  95. with open(css_file) as fp:
  96. upload(theme, fp)
  97. css = theme.css.last()
  98. filename = str(css.source_file.path).split("/")[-1]
  99. expected_filename = str(hashed_css_file).split("/")[-1]
  100. assert filename == expected_filename
  101. def test_hash_is_set_on_css_source_asset(upload, theme, css_file):
  102. with open(css_file) as fp:
  103. upload(theme, fp)
  104. css = theme.css.last()
  105. assert css.source_hash
  106. def test_css_file_name_is_preserved_if_it_already_contains_correct_hash(
  107. upload, theme, hashed_css_file
  108. ):
  109. with open(hashed_css_file) as fp:
  110. upload(theme, fp)
  111. css = theme.css.last()
  112. filename = str(css.source_file.path).split("/")[-1]
  113. expected_filename = str(hashed_css_file).split("/")[-1]
  114. assert filename == expected_filename
  115. def test_new_hash_is_added_to_css_file_name_if_it_contains_incorrect_hash(
  116. upload, theme
  117. ):
  118. incorrectly_hashed_css_file = os.path.join(TESTS_DIR, "css", "test.0046cb3b.css")
  119. with open(incorrectly_hashed_css_file) as fp:
  120. upload(theme, fp)
  121. css = theme.css.last()
  122. filename = str(css.source_file.path).split("/")[-1]
  123. assert css.source_hash in filename
  124. def test_newly_uploaded_css_file_replaces_old_one_if_file_names_are_same(
  125. upload, theme, css_file
  126. ):
  127. with open(css_file) as fp:
  128. upload(theme, fp)
  129. original_css = theme.css.get()
  130. with open(os.path.join(TESTS_DIR, "css", "test-changed.css")) as fp:
  131. size = len(fp.read())
  132. fp.seek(0)
  133. upload(
  134. theme, UploadedFile(fp, name="test.css", content_type="text/css", size=size)
  135. )
  136. updated_css = theme.css.last()
  137. assert updated_css.name == original_css.name
  138. assert updated_css.source_hash != original_css.source_hash
  139. assert theme.css.count() == 1
  140. def test_newly_uploaded_css_file_reuses_replaced_file_order_if_names_are_same(
  141. upload, theme, css_file, hashed_css_file
  142. ):
  143. with open(css_file) as fp:
  144. upload(theme, fp)
  145. original_css = theme.css.last()
  146. with open(hashed_css_file) as fp:
  147. upload(theme, fp)
  148. with open(os.path.join(TESTS_DIR, "css", "test-changed.css")) as fp:
  149. size = len(fp.read())
  150. fp.seek(0)
  151. upload(
  152. theme, UploadedFile(fp, name="test.css", content_type="text/css", size=size)
  153. )
  154. updated_css = theme.css.get(order=original_css.order)
  155. assert updated_css.name == original_css.name
  156. def test_if_uploaded_css_file_contains_no_image_urls_rebuild_flag_is_not_set(
  157. upload, theme, css_file
  158. ):
  159. with open(css_file) as fp:
  160. upload(theme, fp)
  161. css = theme.css.last()
  162. assert not css.source_needs_building
  163. def test_if_uploaded_css_file_contains_image_url_it_has_rebuild_flag_set(upload, theme):
  164. css_file = os.path.join(TESTS_DIR, "css", "test.needs-build.css")
  165. with open(css_file) as fp:
  166. upload(theme, fp)
  167. css = theme.css.last()
  168. assert css.source_needs_building
  169. def test_uploading_css_file_triggers_css_build(
  170. upload, theme, css_file, mock_build_theme_css
  171. ):
  172. with open(css_file) as fp:
  173. upload(theme, fp)
  174. mock_build_theme_css.assert_called_once_with(theme.pk)
  175. def test_error_message_is_set_if_no_css_file_was_uploaded(upload, theme):
  176. response = upload(theme)
  177. assert_has_error_message(response)
  178. def test_error_message_is_set_if_user_attempts_to_upload_css_file_to_default_theme(
  179. upload, default_theme
  180. ):
  181. response = upload(default_theme)
  182. assert_has_error_message(response)
  183. def test_error_message_is_set_if_user_attempts_to_upload_css_file_to_nonexisting_theme(
  184. upload, nonexisting_theme
  185. ):
  186. response = upload(nonexisting_theme)
  187. assert_has_error_message(response)