tests.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. from __future__ import unicode_literals
  2. import os
  3. from django.core.exceptions import ImproperlyConfigured
  4. from django.core.urlresolvers import reverse, clear_url_caches, set_script_prefix
  5. from django.http import HttpResponsePermanentRedirect
  6. from django.middleware.locale import LocaleMiddleware
  7. from django.test import TestCase, override_settings
  8. from django.template import Template, Context
  9. from django.utils._os import upath
  10. from django.utils import translation
  11. class PermanentRedirectLocaleMiddleWare(LocaleMiddleware):
  12. response_redirect_class = HttpResponsePermanentRedirect
  13. @override_settings(
  14. USE_I18N=True,
  15. LOCALE_PATHS=(
  16. os.path.join(os.path.dirname(upath(__file__)), 'locale'),
  17. ),
  18. LANGUAGE_CODE='en-us',
  19. LANGUAGES=(
  20. ('nl', 'Dutch'),
  21. ('en', 'English'),
  22. ('pt-br', 'Brazilian Portuguese'),
  23. ),
  24. MIDDLEWARE_CLASSES=(
  25. 'django.middleware.locale.LocaleMiddleware',
  26. 'django.middleware.common.CommonMiddleware',
  27. ),
  28. ROOT_URLCONF='i18n.patterns.urls.default',
  29. TEMPLATES=[{
  30. 'BACKEND': 'django.template.backends.django.DjangoTemplates',
  31. 'DIRS': [os.path.join(os.path.dirname(upath(__file__)), 'templates')],
  32. 'OPTIONS': {
  33. 'context_processors': [
  34. 'django.template.context_processors.i18n',
  35. ],
  36. },
  37. }],
  38. )
  39. class URLTestCaseBase(TestCase):
  40. """
  41. TestCase base-class for the URL tests.
  42. """
  43. def setUp(self):
  44. # Make sure the cache is empty before we are doing our tests.
  45. clear_url_caches()
  46. def tearDown(self):
  47. # Make sure we will leave an empty cache for other testcases.
  48. clear_url_caches()
  49. class URLPrefixTests(URLTestCaseBase):
  50. """
  51. Tests if the `i18n_patterns` is adding the prefix correctly.
  52. """
  53. def test_not_prefixed(self):
  54. with translation.override('en'):
  55. self.assertEqual(reverse('not-prefixed'), '/not-prefixed/')
  56. self.assertEqual(reverse('not-prefixed-included-url'), '/not-prefixed-include/foo/')
  57. with translation.override('nl'):
  58. self.assertEqual(reverse('not-prefixed'), '/not-prefixed/')
  59. self.assertEqual(reverse('not-prefixed-included-url'), '/not-prefixed-include/foo/')
  60. def test_prefixed(self):
  61. with translation.override('en'):
  62. self.assertEqual(reverse('prefixed'), '/en/prefixed/')
  63. with translation.override('nl'):
  64. self.assertEqual(reverse('prefixed'), '/nl/prefixed/')
  65. @override_settings(ROOT_URLCONF='i18n.patterns.urls.wrong')
  66. def test_invalid_prefix_use(self):
  67. self.assertRaises(ImproperlyConfigured, lambda: reverse('account:register'))
  68. @override_settings(ROOT_URLCONF='i18n.patterns.urls.disabled')
  69. class URLDisabledTests(URLTestCaseBase):
  70. @override_settings(USE_I18N=False)
  71. def test_prefixed_i18n_disabled(self):
  72. with translation.override('en'):
  73. self.assertEqual(reverse('prefixed'), '/prefixed/')
  74. with translation.override('nl'):
  75. self.assertEqual(reverse('prefixed'), '/prefixed/')
  76. @override_settings(ROOT_URLCONF='i18n.patterns.urls.path_unused')
  77. class PathUnusedTests(URLTestCaseBase):
  78. """
  79. Check that if no i18n_patterns is used in root urlconfs, then no
  80. language activation happens based on url prefix.
  81. """
  82. def test_no_lang_activate(self):
  83. response = self.client.get('/nl/foo/')
  84. self.assertEqual(response.status_code, 200)
  85. self.assertEqual(response['content-language'], 'en')
  86. self.assertEqual(response.context['LANGUAGE_CODE'], 'en')
  87. class URLTranslationTests(URLTestCaseBase):
  88. """
  89. Tests if the pattern-strings are translated correctly (within the
  90. `i18n_patterns` and the normal `patterns` function).
  91. """
  92. def test_no_prefix_translated(self):
  93. with translation.override('en'):
  94. self.assertEqual(reverse('no-prefix-translated'), '/translated/')
  95. self.assertEqual(reverse('no-prefix-translated-slug', kwargs={'slug': 'yeah'}), '/translated/yeah/')
  96. with translation.override('nl'):
  97. self.assertEqual(reverse('no-prefix-translated'), '/vertaald/')
  98. self.assertEqual(reverse('no-prefix-translated-slug', kwargs={'slug': 'yeah'}), '/vertaald/yeah/')
  99. with translation.override('pt-br'):
  100. self.assertEqual(reverse('no-prefix-translated'), '/traduzidos/')
  101. self.assertEqual(reverse('no-prefix-translated-slug', kwargs={'slug': 'yeah'}), '/traduzidos/yeah/')
  102. def test_users_url(self):
  103. with translation.override('en'):
  104. self.assertEqual(reverse('users'), '/en/users/')
  105. with translation.override('nl'):
  106. self.assertEqual(reverse('users'), '/nl/gebruikers/')
  107. self.assertEqual(reverse('prefixed_xml'), '/nl/prefixed.xml')
  108. with translation.override('pt-br'):
  109. self.assertEqual(reverse('users'), '/pt-br/usuarios/')
  110. class URLNamespaceTests(URLTestCaseBase):
  111. """
  112. Tests if the translations are still working within namespaces.
  113. """
  114. def test_account_register(self):
  115. with translation.override('en'):
  116. self.assertEqual(reverse('account:register'), '/en/account/register/')
  117. with translation.override('nl'):
  118. self.assertEqual(reverse('account:register'), '/nl/profiel/registeren/')
  119. class URLRedirectTests(URLTestCaseBase):
  120. """
  121. Tests if the user gets redirected to the right URL when there is no
  122. language-prefix in the request URL.
  123. """
  124. def test_no_prefix_response(self):
  125. response = self.client.get('/not-prefixed/')
  126. self.assertEqual(response.status_code, 200)
  127. def test_en_redirect(self):
  128. response = self.client.get('/account/register/', HTTP_ACCEPT_LANGUAGE='en')
  129. self.assertRedirects(response, '/en/account/register/')
  130. response = self.client.get(response['location'])
  131. self.assertEqual(response.status_code, 200)
  132. def test_en_redirect_wrong_url(self):
  133. response = self.client.get('/profiel/registeren/', HTTP_ACCEPT_LANGUAGE='en')
  134. self.assertEqual(response.status_code, 404)
  135. def test_nl_redirect(self):
  136. response = self.client.get('/profiel/registeren/', HTTP_ACCEPT_LANGUAGE='nl')
  137. self.assertRedirects(response, '/nl/profiel/registeren/')
  138. response = self.client.get(response['location'])
  139. self.assertEqual(response.status_code, 200)
  140. def test_nl_redirect_wrong_url(self):
  141. response = self.client.get('/account/register/', HTTP_ACCEPT_LANGUAGE='nl')
  142. self.assertEqual(response.status_code, 404)
  143. def test_pt_br_redirect(self):
  144. response = self.client.get('/conta/registre-se/', HTTP_ACCEPT_LANGUAGE='pt-br')
  145. self.assertRedirects(response, '/pt-br/conta/registre-se/')
  146. response = self.client.get(response['location'])
  147. self.assertEqual(response.status_code, 200)
  148. def test_pl_pl_redirect(self):
  149. # language from outside of the supported LANGUAGES list
  150. response = self.client.get('/account/register/', HTTP_ACCEPT_LANGUAGE='pl-pl')
  151. self.assertRedirects(response, '/en/account/register/')
  152. response = self.client.get(response['location'])
  153. self.assertEqual(response.status_code, 200)
  154. @override_settings(
  155. MIDDLEWARE_CLASSES=(
  156. 'i18n.patterns.tests.PermanentRedirectLocaleMiddleWare',
  157. 'django.middleware.common.CommonMiddleware',
  158. ),
  159. )
  160. def test_custom_redirect_class(self):
  161. response = self.client.get('/account/register/', HTTP_ACCEPT_LANGUAGE='en')
  162. self.assertRedirects(response, '/en/account/register/', 301)
  163. class URLVaryAcceptLanguageTests(URLTestCaseBase):
  164. """
  165. Tests that 'Accept-Language' is not added to the Vary header when using
  166. prefixed URLs.
  167. """
  168. def test_no_prefix_response(self):
  169. response = self.client.get('/not-prefixed/')
  170. self.assertEqual(response.status_code, 200)
  171. self.assertEqual(response.get('Vary'), 'Accept-Language')
  172. def test_en_redirect(self):
  173. response = self.client.get('/account/register/', HTTP_ACCEPT_LANGUAGE='en')
  174. self.assertRedirects(response, '/en/account/register/')
  175. self.assertFalse(response.get('Vary'))
  176. response = self.client.get(response['location'])
  177. self.assertEqual(response.status_code, 200)
  178. self.assertFalse(response.get('Vary'))
  179. class URLRedirectWithoutTrailingSlashTests(URLTestCaseBase):
  180. """
  181. Tests the redirect when the requested URL doesn't end with a slash
  182. (`settings.APPEND_SLASH=True`).
  183. """
  184. def test_not_prefixed_redirect(self):
  185. response = self.client.get('/not-prefixed', HTTP_ACCEPT_LANGUAGE='en')
  186. self.assertRedirects(response, '/not-prefixed/', 301)
  187. def test_en_redirect(self):
  188. response = self.client.get('/account/register', HTTP_ACCEPT_LANGUAGE='en', follow=True)
  189. # target status code of 301 because of CommonMiddleware redirecting
  190. self.assertIn(('http://testserver/en/account/register/', 301), response.redirect_chain)
  191. self.assertRedirects(response, '/en/account/register/', 302)
  192. response = self.client.get('/prefixed.xml', HTTP_ACCEPT_LANGUAGE='en', follow=True)
  193. self.assertRedirects(response, '/en/prefixed.xml', 302)
  194. class URLRedirectWithoutTrailingSlashSettingTests(URLTestCaseBase):
  195. """
  196. Tests the redirect when the requested URL doesn't end with a slash
  197. (`settings.APPEND_SLASH=False`).
  198. """
  199. @override_settings(APPEND_SLASH=False)
  200. def test_not_prefixed_redirect(self):
  201. response = self.client.get('/not-prefixed', HTTP_ACCEPT_LANGUAGE='en')
  202. self.assertEqual(response.status_code, 404)
  203. @override_settings(APPEND_SLASH=False)
  204. def test_en_redirect(self):
  205. response = self.client.get('/account/register-without-slash', HTTP_ACCEPT_LANGUAGE='en')
  206. self.assertRedirects(response, '/en/account/register-without-slash', 302)
  207. response = self.client.get(response['location'])
  208. self.assertEqual(response.status_code, 200)
  209. class URLResponseTests(URLTestCaseBase):
  210. """
  211. Tests if the response has the right language-code.
  212. """
  213. def test_not_prefixed_with_prefix(self):
  214. response = self.client.get('/en/not-prefixed/')
  215. self.assertEqual(response.status_code, 404)
  216. def test_en_url(self):
  217. response = self.client.get('/en/account/register/')
  218. self.assertEqual(response.status_code, 200)
  219. self.assertEqual(response['content-language'], 'en')
  220. self.assertEqual(response.context['LANGUAGE_CODE'], 'en')
  221. def test_nl_url(self):
  222. response = self.client.get('/nl/profiel/registeren/')
  223. self.assertEqual(response.status_code, 200)
  224. self.assertEqual(response['content-language'], 'nl')
  225. self.assertEqual(response.context['LANGUAGE_CODE'], 'nl')
  226. def test_wrong_en_prefix(self):
  227. response = self.client.get('/en/profiel/registeren/')
  228. self.assertEqual(response.status_code, 404)
  229. def test_wrong_nl_prefix(self):
  230. response = self.client.get('/nl/account/register/')
  231. self.assertEqual(response.status_code, 404)
  232. def test_pt_br_url(self):
  233. response = self.client.get('/pt-br/conta/registre-se/')
  234. self.assertEqual(response.status_code, 200)
  235. self.assertEqual(response['content-language'], 'pt-br')
  236. self.assertEqual(response.context['LANGUAGE_CODE'], 'pt-br')
  237. class URLRedirectWithScriptAliasTests(URLTestCaseBase):
  238. """
  239. #21579 - LocaleMiddleware should respect the script prefix.
  240. """
  241. def setUp(self):
  242. super(URLRedirectWithScriptAliasTests, self).setUp()
  243. self.script_prefix = '/script_prefix'
  244. set_script_prefix(self.script_prefix)
  245. def tearDown(self):
  246. super(URLRedirectWithScriptAliasTests, self).tearDown()
  247. # reset script prefix
  248. set_script_prefix('')
  249. def test_language_prefix_with_script_prefix(self):
  250. response = self.client.get('/prefixed/', HTTP_ACCEPT_LANGUAGE='en', SCRIPT_NAME=self.script_prefix)
  251. self.assertRedirects(response, '%s/en/prefixed/' % self.script_prefix, target_status_code=404)
  252. class URLTagTests(URLTestCaseBase):
  253. """
  254. Test if the language tag works.
  255. """
  256. def test_strings_only(self):
  257. t = Template("""{% load i18n %}
  258. {% language 'nl' %}{% url 'no-prefix-translated' %}{% endlanguage %}
  259. {% language 'pt-br' %}{% url 'no-prefix-translated' %}{% endlanguage %}""")
  260. self.assertEqual(t.render(Context({})).strip().split(),
  261. ['/vertaald/', '/traduzidos/'])
  262. def test_context(self):
  263. ctx = Context({'lang1': 'nl', 'lang2': 'pt-br'})
  264. tpl = Template("""{% load i18n %}
  265. {% language lang1 %}{% url 'no-prefix-translated' %}{% endlanguage %}
  266. {% language lang2 %}{% url 'no-prefix-translated' %}{% endlanguage %}""")
  267. self.assertEqual(tpl.render(ctx).strip().split(),
  268. ['/vertaald/', '/traduzidos/'])
  269. def test_args(self):
  270. tpl = Template("""{% load i18n %}
  271. {% language 'nl' %}{% url 'no-prefix-translated-slug' 'apo' %}{% endlanguage %}
  272. {% language 'pt-br' %}{% url 'no-prefix-translated-slug' 'apo' %}{% endlanguage %}""")
  273. self.assertEqual(tpl.render(Context({})).strip().split(),
  274. ['/vertaald/apo/', '/traduzidos/apo/'])
  275. def test_kwargs(self):
  276. tpl = Template("""{% load i18n %}
  277. {% language 'nl' %}{% url 'no-prefix-translated-slug' slug='apo' %}{% endlanguage %}
  278. {% language 'pt-br' %}{% url 'no-prefix-translated-slug' slug='apo' %}{% endlanguage %}""")
  279. self.assertEqual(tpl.render(Context({})).strip().split(),
  280. ['/vertaald/apo/', '/traduzidos/apo/'])