test_templates.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. from copy import deepcopy
  2. from itertools import chain
  3. from django.core.checks import Error, Warning
  4. from django.core.checks.templates import check_templates
  5. from django.template import engines
  6. from django.template.backends.base import BaseEngine
  7. from django.test import SimpleTestCase
  8. from django.test.utils import override_settings
  9. class ErrorEngine(BaseEngine):
  10. def __init__(self, params):
  11. params.pop("OPTIONS")
  12. super().__init__(params)
  13. def check(self, **kwargs):
  14. return [Error("Example")]
  15. class CheckTemplatesTests(SimpleTestCase):
  16. @override_settings(
  17. TEMPLATES=[
  18. {"BACKEND": f"{__name__}.{ErrorEngine.__qualname__}", "NAME": "backend_1"},
  19. {"BACKEND": f"{__name__}.{ErrorEngine.__qualname__}", "NAME": "backend_2"},
  20. ]
  21. )
  22. def test_errors_aggregated(self):
  23. errors = check_templates(None)
  24. self.assertEqual(errors, [Error("Example")] * 2)
  25. class CheckTemplateStringIfInvalidTest(SimpleTestCase):
  26. TEMPLATES_STRING_IF_INVALID = [
  27. {
  28. "BACKEND": "django.template.backends.django.DjangoTemplates",
  29. "NAME": "backend_1",
  30. "OPTIONS": {
  31. "string_if_invalid": False,
  32. },
  33. },
  34. {
  35. "BACKEND": "django.template.backends.django.DjangoTemplates",
  36. "NAME": "backend_2",
  37. "OPTIONS": {
  38. "string_if_invalid": 42,
  39. },
  40. },
  41. ]
  42. def _get_error_for_engine(self, engine):
  43. value = engine.engine.string_if_invalid
  44. return Error(
  45. "'string_if_invalid' in TEMPLATES OPTIONS must be a string but got: %r "
  46. "(%s)." % (value, type(value)),
  47. obj=engine,
  48. id="templates.E002",
  49. )
  50. def _check_engines(self, engines):
  51. return list(
  52. chain.from_iterable(e._check_string_if_invalid_is_string() for e in engines)
  53. )
  54. @override_settings(TEMPLATES=TEMPLATES_STRING_IF_INVALID)
  55. def test_string_if_invalid_not_string(self):
  56. _engines = engines.all()
  57. errors = [
  58. self._get_error_for_engine(_engines[0]),
  59. self._get_error_for_engine(_engines[1]),
  60. ]
  61. self.assertEqual(self._check_engines(_engines), errors)
  62. def test_string_if_invalid_first_is_string(self):
  63. TEMPLATES = deepcopy(self.TEMPLATES_STRING_IF_INVALID)
  64. TEMPLATES[0]["OPTIONS"]["string_if_invalid"] = "test"
  65. with self.settings(TEMPLATES=TEMPLATES):
  66. _engines = engines.all()
  67. errors = [self._get_error_for_engine(_engines[1])]
  68. self.assertEqual(self._check_engines(_engines), errors)
  69. def test_string_if_invalid_both_are_strings(self):
  70. TEMPLATES = deepcopy(self.TEMPLATES_STRING_IF_INVALID)
  71. TEMPLATES[0]["OPTIONS"]["string_if_invalid"] = "test"
  72. TEMPLATES[1]["OPTIONS"]["string_if_invalid"] = "test"
  73. with self.settings(TEMPLATES=TEMPLATES):
  74. self.assertEqual(self._check_engines(engines.all()), [])
  75. def test_string_if_invalid_not_specified(self):
  76. TEMPLATES = deepcopy(self.TEMPLATES_STRING_IF_INVALID)
  77. del TEMPLATES[1]["OPTIONS"]["string_if_invalid"]
  78. with self.settings(TEMPLATES=TEMPLATES):
  79. _engines = engines.all()
  80. errors = [self._get_error_for_engine(_engines[0])]
  81. self.assertEqual(self._check_engines(_engines), errors)
  82. class CheckTemplateTagLibrariesWithSameName(SimpleTestCase):
  83. def get_settings(self, module_name, module_path, name="django"):
  84. return {
  85. "BACKEND": "django.template.backends.django.DjangoTemplates",
  86. "NAME": name,
  87. "OPTIONS": {
  88. "libraries": {
  89. module_name: f"check_framework.template_test_apps.{module_path}",
  90. },
  91. },
  92. }
  93. def _get_error_for_engine(self, engine, modules):
  94. return Warning(
  95. f"'same_tags' is used for multiple template tag modules: {modules}",
  96. obj=engine,
  97. id="templates.W003",
  98. )
  99. def _check_engines(self, engines):
  100. return list(
  101. chain.from_iterable(
  102. e._check_for_template_tags_with_the_same_name() for e in engines
  103. )
  104. )
  105. @override_settings(
  106. INSTALLED_APPS=[
  107. "check_framework.template_test_apps.same_tags_app_1",
  108. "check_framework.template_test_apps.same_tags_app_2",
  109. ]
  110. )
  111. def test_template_tags_with_same_name(self):
  112. _engines = engines.all()
  113. modules = (
  114. "'check_framework.template_test_apps.same_tags_app_1.templatetags"
  115. ".same_tags', 'check_framework.template_test_apps.same_tags_app_2"
  116. ".templatetags.same_tags'"
  117. )
  118. errors = [self._get_error_for_engine(_engines[0], modules)]
  119. self.assertEqual(self._check_engines(_engines), errors)
  120. def test_template_tags_for_separate_backends(self):
  121. # The "libraries" names are the same, but the backends are different.
  122. with self.settings(
  123. TEMPLATES=[
  124. self.get_settings(
  125. "same_tags",
  126. "same_tags_app_1.templatetags.same_tags",
  127. name="backend_1",
  128. ),
  129. self.get_settings(
  130. "same_tags",
  131. "same_tags_app_2.templatetags.same_tags",
  132. name="backend_2",
  133. ),
  134. ]
  135. ):
  136. self.assertEqual(self._check_engines(engines.all()), [])
  137. @override_settings(
  138. INSTALLED_APPS=["check_framework.template_test_apps.same_tags_app_1"]
  139. )
  140. def test_template_tags_same_library_in_installed_apps_libraries(self):
  141. with self.settings(
  142. TEMPLATES=[
  143. self.get_settings(
  144. "same_tags", "same_tags_app_1.templatetags.same_tags"
  145. ),
  146. ]
  147. ):
  148. self.assertEqual(self._check_engines(engines.all()), [])
  149. @override_settings(
  150. INSTALLED_APPS=["check_framework.template_test_apps.same_tags_app_1"]
  151. )
  152. def test_template_tags_with_same_library_name_and_module_name(self):
  153. modules = (
  154. "'check_framework.template_test_apps.different_tags_app.templatetags"
  155. ".different_tags', 'check_framework.template_test_apps.same_tags_app_1"
  156. ".templatetags.same_tags'"
  157. )
  158. with self.settings(
  159. TEMPLATES=[
  160. self.get_settings(
  161. "same_tags", "different_tags_app.templatetags.different_tags"
  162. ),
  163. ]
  164. ):
  165. _engines = engines.all()
  166. errors = [self._get_error_for_engine(_engines[0], modules)]
  167. self.assertEqual(self._check_engines(_engines), errors)
  168. def test_template_tags_with_different_library_name(self):
  169. with self.settings(
  170. TEMPLATES=[
  171. self.get_settings(
  172. "same_tags",
  173. "same_tags_app_1.templatetags.same_tags",
  174. name="backend_1",
  175. ),
  176. self.get_settings(
  177. "not_same_tags",
  178. "same_tags_app_2.templatetags.same_tags",
  179. name="backend_2",
  180. ),
  181. ]
  182. ):
  183. self.assertEqual(self._check_engines(engines.all()), [])
  184. @override_settings(
  185. INSTALLED_APPS=[
  186. "check_framework.template_test_apps.same_tags_app_1",
  187. "check_framework.template_test_apps.different_tags_app",
  188. ]
  189. )
  190. def test_template_tags_with_different_name(self):
  191. self.assertEqual(self._check_engines(engines.all()), [])