test_views.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. from django.contrib.auth.models import Group, Permission
  2. from django.contrib.contenttypes.models import ContentType
  3. from django.http import Http404
  4. from django.test import RequestFactory, override_settings
  5. from django.urls import reverse
  6. from django.utils.translation import gettext_lazy
  7. from wagtail.contrib.simple_translation.forms import SubmitTranslationForm
  8. from wagtail.contrib.simple_translation.models import after_create_page
  9. from wagtail.contrib.simple_translation.views import (
  10. SubmitPageTranslationView,
  11. SubmitSnippetTranslationView,
  12. SubmitTranslationView,
  13. )
  14. from wagtail.core import hooks
  15. from wagtail.core.actions.copy_for_translation import ParentNotTranslatedError
  16. from wagtail.core.models import Locale, Page
  17. from wagtail.test.i18n.models import TestPage
  18. from wagtail.test.snippets.models import TranslatableSnippet
  19. from wagtail.test.utils import TestCase, WagtailTestUtils
  20. @override_settings(
  21. LANGUAGES=[
  22. ("en", "English"),
  23. ("fr", "French"),
  24. ("de", "German"),
  25. ],
  26. WAGTAIL_CONTENT_LANGUAGES=[
  27. ("en", "English"),
  28. ("fr", "French"),
  29. ("de", "German"),
  30. ],
  31. )
  32. class TestSubmitTranslationView(WagtailTestUtils, TestCase):
  33. def setUp(self):
  34. self.en_locale = Locale.objects.first()
  35. self.fr_locale = Locale.objects.create(language_code="fr")
  36. self.de_locale = Locale.objects.create(language_code="de")
  37. self.en_homepage = Page.objects.get(depth=2)
  38. self.factory = RequestFactory()
  39. def test_template_name(self):
  40. self.assertEqual(
  41. SubmitTranslationView.template_name,
  42. "simple_translation/admin/submit_translation.html",
  43. )
  44. def test_title(self):
  45. self.assertEqual(SubmitTranslationView().title, gettext_lazy("Translate"))
  46. self.assertEqual(SubmitTranslationView().get_title(), gettext_lazy("Translate"))
  47. def test_subtitle(self):
  48. view = SubmitTranslationView()
  49. view.object = self.en_homepage
  50. self.assertEqual(view.get_subtitle(), str(self.en_homepage))
  51. def test_get_form(self):
  52. view = SubmitTranslationView()
  53. view.request = self.factory.get("/path/does/not/matter/")
  54. view.object = self.en_homepage
  55. form = view.get_form()
  56. self.assertIsInstance(form, SubmitTranslationForm)
  57. def test_get_success_url(self):
  58. with self.assertRaises(NotImplementedError):
  59. view = SubmitTranslationView()
  60. view.object = self.en_homepage
  61. view.get_success_url()
  62. def test_get_context_data(self, **kwargs):
  63. view = SubmitTranslationView()
  64. view.request = self.factory.get("/path/does/not/matter/")
  65. view.object = self.en_homepage
  66. context = view.get_context_data()
  67. self.assertIn("form", context.keys())
  68. self.assertIsInstance(context["form"], SubmitTranslationForm)
  69. def test_dispatch_as_anon(self):
  70. url = reverse(
  71. "simple_translation:submit_page_translation", args=(self.en_homepage.id,)
  72. )
  73. response = self.client.get(url)
  74. self.assertEqual(response.status_code, 302)
  75. self.assertEqual(response.url, f"/admin/login/?next={url}")
  76. def test_dispatch_as_moderator(self):
  77. url = reverse(
  78. "simple_translation:submit_page_translation", args=(self.en_homepage.id,)
  79. )
  80. user = self.login()
  81. group = Group.objects.get(name="Moderators")
  82. user.groups.add(group)
  83. response = self.client.get(url)
  84. self.assertEqual(response.status_code, 200)
  85. def test_dispatch_as_user_with_perm(self):
  86. url = reverse(
  87. "simple_translation:submit_page_translation", args=(self.en_homepage.id,)
  88. )
  89. user = self.login()
  90. permission = Permission.objects.get(codename="submit_translation")
  91. user.user_permissions.add(permission)
  92. response = self.client.get(url)
  93. self.assertEqual(response.status_code, 200)
  94. @override_settings(
  95. LANGUAGES=[
  96. ("en", "English"),
  97. ("fr", "French"),
  98. ("de", "German"),
  99. ],
  100. WAGTAIL_CONTENT_LANGUAGES=[
  101. ("en", "English"),
  102. ("fr", "French"),
  103. ("de", "German"),
  104. ],
  105. )
  106. class TestSubmitPageTranslationView(WagtailTestUtils, TestCase):
  107. def setUp(self):
  108. self.en_locale = Locale.objects.first()
  109. self.fr_locale = Locale.objects.create(language_code="fr")
  110. self.de_locale = Locale.objects.create(language_code="de")
  111. self.en_homepage = Page.objects.get(depth=2)
  112. self.fr_homepage = self.en_homepage.copy_for_translation(self.fr_locale)
  113. self.de_homepage = self.en_homepage.copy_for_translation(self.de_locale)
  114. self.en_blog_index = TestPage(title="Blog", slug="blog")
  115. self.en_homepage.add_child(instance=self.en_blog_index)
  116. self.en_blog_post = TestPage(title="Blog post", slug="blog-post")
  117. self.en_blog_index.add_child(instance=self.en_blog_post)
  118. def test_title(self):
  119. self.assertEqual(SubmitPageTranslationView.title, "Translate page")
  120. def test_get_subtitle(self):
  121. view = SubmitPageTranslationView()
  122. view.object = self.en_homepage
  123. self.assertEqual(view.get_subtitle(), "Welcome to your new Wagtail site!")
  124. def test_submit_page_translation_view_test_get(self):
  125. url = reverse(
  126. "simple_translation:submit_page_translation", args=(self.en_blog_index.id,)
  127. )
  128. self.login()
  129. response = self.client.get(url)
  130. assert isinstance(response.context["form"], SubmitTranslationForm)
  131. def test_submit_page_translation_view_test_post_invalid(self):
  132. url = reverse(
  133. "simple_translation:submit_page_translation", args=(self.en_blog_index.id,)
  134. )
  135. self.login()
  136. response = self.client.post(url, {})
  137. assert response.status_code == 200
  138. assert response.context["form"].errors == {
  139. "locales": ["This field is required."]
  140. }
  141. def test_submit_page_translation_view_test_post_single_locale(self):
  142. url = reverse(
  143. "simple_translation:submit_page_translation", args=(self.en_blog_index.id,)
  144. )
  145. de = Locale.objects.get(language_code="de").id
  146. data = {"locales": [de], "include_subtree": True}
  147. self.login()
  148. response = self.client.post(url, data, follow=True)
  149. translated_page = self.en_blog_index.get_translation(de)
  150. self.assertRedirects(
  151. response, reverse("wagtailadmin_pages:edit", args=[translated_page.pk])
  152. )
  153. self.assertIn(
  154. "The page 'Blog' was successfully created in German",
  155. [msg.message for msg in response.context["messages"]],
  156. )
  157. def test_submit_page_translation_view_test_post_multiple_locales(self):
  158. # Needs an extra page to hit recursive function
  159. en_blog_post_sub = Page(title="Blog post sub", slug="blog-post-sub")
  160. self.en_blog_post.add_child(instance=en_blog_post_sub)
  161. url = reverse(
  162. "simple_translation:submit_page_translation", args=(self.en_blog_post.id,)
  163. )
  164. de = Locale.objects.get(language_code="de").id
  165. fr = Locale.objects.get(language_code="fr").id
  166. data = {"locales": [de, fr], "include_subtree": True}
  167. self.login()
  168. with self.assertRaisesMessage(ParentNotTranslatedError, ""):
  169. self.client.post(url, data)
  170. url = reverse(
  171. "simple_translation:submit_page_translation", args=(self.en_blog_index.id,)
  172. )
  173. response = self.client.post(url, data)
  174. assert response.status_code == 302
  175. assert response.url == f"/admin/pages/{self.en_blog_index.get_parent().id}/"
  176. response = self.client.get(response.url) # follow the redirect
  177. assert [msg.message for msg in response.context["messages"]] == [
  178. "The page 'Blog' was successfully created in 2 locales"
  179. ]
  180. @override_settings(
  181. LANGUAGES=[
  182. ("en", "English"),
  183. ("fr", "French"),
  184. ("de", "German"),
  185. ],
  186. WAGTAIL_CONTENT_LANGUAGES=[
  187. ("en", "English"),
  188. ("fr", "French"),
  189. ("de", "German"),
  190. ],
  191. )
  192. class TestSubmitSnippetTranslationView(WagtailTestUtils, TestCase):
  193. def setUp(self):
  194. self.en_locale = Locale.objects.first()
  195. self.fr_locale = Locale.objects.create(language_code="fr")
  196. self.en_snippet = TranslatableSnippet(text="Hello world", locale=self.en_locale)
  197. self.en_snippet.save()
  198. def test_get_title(self):
  199. view = SubmitSnippetTranslationView()
  200. view.object = self.en_snippet
  201. self.assertEqual(view.get_title(), "Translate translatable snippet")
  202. def test_get_object(self):
  203. view = SubmitSnippetTranslationView()
  204. view.object = self.en_snippet
  205. view.kwargs = {
  206. "app_label": "some_app",
  207. "model_name": "some_model",
  208. "pk": 1,
  209. }
  210. with self.assertRaises(Http404):
  211. view.get_object()
  212. content_type = ContentType.objects.get_for_model(self.en_snippet)
  213. view.kwargs = {
  214. "app_label": content_type.app_label,
  215. "model_name": content_type.model,
  216. "pk": str(self.en_snippet.pk),
  217. }
  218. self.assertEqual(view.get_object(), self.en_snippet)
  219. def test_get_success_url(self):
  220. view = SubmitSnippetTranslationView()
  221. view.object = self.en_snippet
  222. view.kwargs = {
  223. "app_label": "some_app",
  224. "model_name": "some_model",
  225. "pk": 99,
  226. }
  227. self.assertEqual(
  228. view.get_success_url(), "/admin/snippets/some_app/some_model/edit/99/"
  229. )
  230. def test_get_success_url_for_single_locale(self):
  231. view = SubmitSnippetTranslationView()
  232. view.object = self.en_snippet
  233. view.kwargs = {
  234. "app_label": "some_app",
  235. "model_name": "some_model",
  236. "pk": 99,
  237. }
  238. self.assertEqual(
  239. view.get_success_url(view.object),
  240. reverse(
  241. "wagtailsnippets:edit",
  242. args=[
  243. "some_app",
  244. "some_model",
  245. view.object.pk,
  246. ],
  247. ),
  248. )
  249. def test_get_success_message(self):
  250. view = SubmitSnippetTranslationView()
  251. view.object = self.en_snippet
  252. self.assertEqual(
  253. view.get_success_message(self.fr_locale),
  254. f"Successfully created French for translatable snippet 'TranslatableSnippet object ({self.en_snippet.id})'",
  255. )
  256. @override_settings(
  257. LANGUAGES=[
  258. ("en", "English"),
  259. ("fr", "French"),
  260. ("de", "German"),
  261. ],
  262. WAGTAIL_CONTENT_LANGUAGES=[
  263. ("en", "English"),
  264. ("fr", "French"),
  265. ("de", "German"),
  266. ],
  267. WAGTAILSIMPLETRANSLATION_SYNC_PAGE_TREE=True,
  268. )
  269. class TestPageTreeSync(WagtailTestUtils, TestCase):
  270. def setUp(self):
  271. self.en_locale = Locale.objects.first()
  272. self.fr_locale = Locale.objects.create(language_code="fr")
  273. self.de_locale = Locale.objects.create(language_code="de")
  274. self.en_homepage = Page.objects.get(depth=2)
  275. self.fr_homepage = self.en_homepage.copy_for_translation(self.fr_locale)
  276. self.de_homepage = self.en_homepage.copy_for_translation(self.de_locale)
  277. def test_hook_function_registered(self):
  278. fns = hooks.get_hooks("after_create_page")
  279. self.assertIn(after_create_page, fns)
  280. def test_alias_created_after_page_saved(self):
  281. en_blog_index = TestPage(title="Blog", slug="blog")
  282. self.en_homepage.add_child(instance=en_blog_index)
  283. after_create_page(None, en_blog_index)
  284. fr_blog_index = en_blog_index.get_translation(self.fr_locale)
  285. de_blog_index = en_blog_index.get_translation(self.de_locale)
  286. self.assertEqual(fr_blog_index.alias_of.specific, en_blog_index)
  287. self.assertEqual(de_blog_index.alias_of.specific, en_blog_index)
  288. @override_settings(WAGTAILSIMPLETRANSLATION_SYNC_PAGE_TREE=False)
  289. def test_page_sync_disabled(self):
  290. en_blog_index = TestPage(title="Blog", slug="blog")
  291. self.en_homepage.add_child(instance=en_blog_index)
  292. after_create_page(None, en_blog_index)
  293. self.assertFalse(en_blog_index.has_translation(self.fr_locale))
  294. self.assertFalse(en_blog_index.has_translation(self.de_locale))