tests.py 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435
  1. # -*- coding: utf-8 -*-
  2. """
  3. Regression tests for the Test Client, especially the customized assertions.
  4. """
  5. from __future__ import unicode_literals
  6. import itertools
  7. import os
  8. from django.contrib.auth.models import User
  9. from django.contrib.auth.signals import user_logged_in, user_logged_out
  10. from django.http import HttpResponse
  11. from django.template import (
  12. Context, RequestContext, TemplateSyntaxError, engines,
  13. )
  14. from django.template.response import SimpleTemplateResponse
  15. from django.test import (
  16. Client, SimpleTestCase, TestCase, ignore_warnings, modify_settings,
  17. override_settings,
  18. )
  19. from django.test.client import RedirectCycleError, RequestFactory, encode_file
  20. from django.test.utils import ContextList, str_prefix
  21. from django.urls import NoReverseMatch, reverse
  22. from django.utils._os import upath
  23. from django.utils.deprecation import RemovedInDjango20Warning
  24. from django.utils.translation import ugettext_lazy
  25. from .models import CustomUser
  26. from .views import CustomTestException
  27. class TestDataMixin(object):
  28. @classmethod
  29. def setUpTestData(cls):
  30. cls.u1 = User.objects.create_user(username='testclient', password='password')
  31. cls.staff = User.objects.create_user(username='staff', password='password', is_staff=True)
  32. @override_settings(ROOT_URLCONF='test_client_regress.urls')
  33. class AssertContainsTests(SimpleTestCase):
  34. def test_contains(self):
  35. "Responses can be inspected for content, including counting repeated substrings"
  36. response = self.client.get('/no_template_view/')
  37. self.assertNotContains(response, 'never')
  38. self.assertContains(response, 'never', 0)
  39. self.assertContains(response, 'once')
  40. self.assertContains(response, 'once', 1)
  41. self.assertContains(response, 'twice')
  42. self.assertContains(response, 'twice', 2)
  43. try:
  44. self.assertContains(response, 'text', status_code=999)
  45. except AssertionError as e:
  46. self.assertIn("Couldn't retrieve content: Response code was 200 (expected 999)", str(e))
  47. try:
  48. self.assertContains(response, 'text', status_code=999, msg_prefix='abc')
  49. except AssertionError as e:
  50. self.assertIn("abc: Couldn't retrieve content: Response code was 200 (expected 999)", str(e))
  51. try:
  52. self.assertNotContains(response, 'text', status_code=999)
  53. except AssertionError as e:
  54. self.assertIn("Couldn't retrieve content: Response code was 200 (expected 999)", str(e))
  55. try:
  56. self.assertNotContains(response, 'text', status_code=999, msg_prefix='abc')
  57. except AssertionError as e:
  58. self.assertIn("abc: Couldn't retrieve content: Response code was 200 (expected 999)", str(e))
  59. try:
  60. self.assertNotContains(response, 'once')
  61. except AssertionError as e:
  62. self.assertIn("Response should not contain 'once'", str(e))
  63. try:
  64. self.assertNotContains(response, 'once', msg_prefix='abc')
  65. except AssertionError as e:
  66. self.assertIn("abc: Response should not contain 'once'", str(e))
  67. try:
  68. self.assertContains(response, 'never', 1)
  69. except AssertionError as e:
  70. self.assertIn("Found 0 instances of 'never' in response (expected 1)", str(e))
  71. try:
  72. self.assertContains(response, 'never', 1, msg_prefix='abc')
  73. except AssertionError as e:
  74. self.assertIn("abc: Found 0 instances of 'never' in response (expected 1)", str(e))
  75. try:
  76. self.assertContains(response, 'once', 0)
  77. except AssertionError as e:
  78. self.assertIn("Found 1 instances of 'once' in response (expected 0)", str(e))
  79. try:
  80. self.assertContains(response, 'once', 0, msg_prefix='abc')
  81. except AssertionError as e:
  82. self.assertIn("abc: Found 1 instances of 'once' in response (expected 0)", str(e))
  83. try:
  84. self.assertContains(response, 'once', 2)
  85. except AssertionError as e:
  86. self.assertIn("Found 1 instances of 'once' in response (expected 2)", str(e))
  87. try:
  88. self.assertContains(response, 'once', 2, msg_prefix='abc')
  89. except AssertionError as e:
  90. self.assertIn("abc: Found 1 instances of 'once' in response (expected 2)", str(e))
  91. try:
  92. self.assertContains(response, 'twice', 1)
  93. except AssertionError as e:
  94. self.assertIn("Found 2 instances of 'twice' in response (expected 1)", str(e))
  95. try:
  96. self.assertContains(response, 'twice', 1, msg_prefix='abc')
  97. except AssertionError as e:
  98. self.assertIn("abc: Found 2 instances of 'twice' in response (expected 1)", str(e))
  99. try:
  100. self.assertContains(response, 'thrice')
  101. except AssertionError as e:
  102. self.assertIn("Couldn't find 'thrice' in response", str(e))
  103. try:
  104. self.assertContains(response, 'thrice', msg_prefix='abc')
  105. except AssertionError as e:
  106. self.assertIn("abc: Couldn't find 'thrice' in response", str(e))
  107. try:
  108. self.assertContains(response, 'thrice', 3)
  109. except AssertionError as e:
  110. self.assertIn("Found 0 instances of 'thrice' in response (expected 3)", str(e))
  111. try:
  112. self.assertContains(response, 'thrice', 3, msg_prefix='abc')
  113. except AssertionError as e:
  114. self.assertIn("abc: Found 0 instances of 'thrice' in response (expected 3)", str(e))
  115. def test_unicode_contains(self):
  116. "Unicode characters can be found in template context"
  117. # Regression test for #10183
  118. r = self.client.get('/check_unicode/')
  119. self.assertContains(r, 'さかき')
  120. self.assertContains(r, b'\xe5\xb3\xa0'.decode('utf-8'))
  121. def test_unicode_not_contains(self):
  122. "Unicode characters can be searched for, and not found in template context"
  123. # Regression test for #10183
  124. r = self.client.get('/check_unicode/')
  125. self.assertNotContains(r, 'はたけ')
  126. self.assertNotContains(r, b'\xe3\x81\xaf\xe3\x81\x9f\xe3\x81\x91'.decode('utf-8'))
  127. def test_binary_contains(self):
  128. r = self.client.get('/check_binary/')
  129. self.assertContains(r, b'%PDF-1.4\r\n%\x93\x8c\x8b\x9e')
  130. with self.assertRaises(AssertionError):
  131. self.assertContains(r, b'%PDF-1.4\r\n%\x93\x8c\x8b\x9e', count=2)
  132. def test_binary_not_contains(self):
  133. r = self.client.get('/check_binary/')
  134. self.assertNotContains(r, b'%ODF-1.4\r\n%\x93\x8c\x8b\x9e')
  135. with self.assertRaises(AssertionError):
  136. self.assertNotContains(r, b'%PDF-1.4\r\n%\x93\x8c\x8b\x9e')
  137. def test_nontext_contains(self):
  138. r = self.client.get('/no_template_view/')
  139. self.assertContains(r, ugettext_lazy('once'))
  140. def test_nontext_not_contains(self):
  141. r = self.client.get('/no_template_view/')
  142. self.assertNotContains(r, ugettext_lazy('never'))
  143. def test_assert_contains_renders_template_response(self):
  144. """ Test that we can pass in an unrendered SimpleTemplateResponse
  145. without throwing an error.
  146. Refs #15826.
  147. """
  148. template = engines['django'].from_string('Hello')
  149. response = SimpleTemplateResponse(template)
  150. self.assertContains(response, 'Hello')
  151. def test_assert_contains_using_non_template_response(self):
  152. """ Test that auto-rendering does not affect responses that aren't
  153. instances (or subclasses) of SimpleTemplateResponse.
  154. Refs #15826.
  155. """
  156. response = HttpResponse('Hello')
  157. self.assertContains(response, 'Hello')
  158. def test_assert_not_contains_renders_template_response(self):
  159. """ Test that we can pass in an unrendered SimpleTemplateResponse
  160. without throwing an error.
  161. Refs #15826.
  162. """
  163. template = engines['django'].from_string('Hello')
  164. response = SimpleTemplateResponse(template)
  165. self.assertNotContains(response, 'Bye')
  166. def test_assert_not_contains_using_non_template_response(self):
  167. """ Test that auto-rendering does not affect responses that aren't
  168. instances (or subclasses) of SimpleTemplateResponse.
  169. Refs #15826.
  170. """
  171. response = HttpResponse('Hello')
  172. self.assertNotContains(response, 'Bye')
  173. @override_settings(ROOT_URLCONF='test_client_regress.urls')
  174. class AssertTemplateUsedTests(TestDataMixin, TestCase):
  175. def test_no_context(self):
  176. "Template usage assertions work then templates aren't in use"
  177. response = self.client.get('/no_template_view/')
  178. # Check that the no template case doesn't mess with the template assertions
  179. self.assertTemplateNotUsed(response, 'GET Template')
  180. try:
  181. self.assertTemplateUsed(response, 'GET Template')
  182. except AssertionError as e:
  183. self.assertIn("No templates used to render the response", str(e))
  184. try:
  185. self.assertTemplateUsed(response, 'GET Template', msg_prefix='abc')
  186. except AssertionError as e:
  187. self.assertIn("abc: No templates used to render the response", str(e))
  188. with self.assertRaises(AssertionError) as context:
  189. self.assertTemplateUsed(response, 'GET Template', count=2)
  190. self.assertIn(
  191. "No templates used to render the response",
  192. str(context.exception))
  193. def test_single_context(self):
  194. "Template assertions work when there is a single context"
  195. response = self.client.get('/post_view/', {})
  196. try:
  197. self.assertTemplateNotUsed(response, 'Empty GET Template')
  198. except AssertionError as e:
  199. self.assertIn("Template 'Empty GET Template' was used unexpectedly in rendering the response", str(e))
  200. try:
  201. self.assertTemplateNotUsed(response, 'Empty GET Template', msg_prefix='abc')
  202. except AssertionError as e:
  203. self.assertIn("abc: Template 'Empty GET Template' was used unexpectedly in rendering the response", str(e))
  204. try:
  205. self.assertTemplateUsed(response, 'Empty POST Template')
  206. except AssertionError as e:
  207. self.assertIn(
  208. "Template 'Empty POST Template' was not a template used to "
  209. "render the response. Actual template(s) used: Empty GET Template",
  210. str(e)
  211. )
  212. try:
  213. self.assertTemplateUsed(response, 'Empty POST Template', msg_prefix='abc')
  214. except AssertionError as e:
  215. self.assertIn(
  216. "abc: Template 'Empty POST Template' was not a template used "
  217. "to render the response. Actual template(s) used: Empty GET Template",
  218. str(e)
  219. )
  220. with self.assertRaises(AssertionError) as context:
  221. self.assertTemplateUsed(response, 'Empty GET Template', count=2)
  222. self.assertIn(
  223. "Template 'Empty GET Template' was expected to be rendered 2 "
  224. "time(s) but was actually rendered 1 time(s).",
  225. str(context.exception))
  226. with self.assertRaises(AssertionError) as context:
  227. self.assertTemplateUsed(
  228. response, 'Empty GET Template', msg_prefix='abc', count=2)
  229. self.assertIn(
  230. "abc: Template 'Empty GET Template' was expected to be rendered 2 "
  231. "time(s) but was actually rendered 1 time(s).",
  232. str(context.exception))
  233. def test_multiple_context(self):
  234. "Template assertions work when there are multiple contexts"
  235. post_data = {
  236. 'text': 'Hello World',
  237. 'email': 'foo@example.com',
  238. 'value': 37,
  239. 'single': 'b',
  240. 'multi': ('b', 'c', 'e')
  241. }
  242. response = self.client.post('/form_view_with_template/', post_data)
  243. self.assertContains(response, 'POST data OK')
  244. try:
  245. self.assertTemplateNotUsed(response, "form_view.html")
  246. except AssertionError as e:
  247. self.assertIn("Template 'form_view.html' was used unexpectedly in rendering the response", str(e))
  248. try:
  249. self.assertTemplateNotUsed(response, 'base.html')
  250. except AssertionError as e:
  251. self.assertIn("Template 'base.html' was used unexpectedly in rendering the response", str(e))
  252. try:
  253. self.assertTemplateUsed(response, "Valid POST Template")
  254. except AssertionError as e:
  255. self.assertIn(
  256. "Template 'Valid POST Template' was not a template used to "
  257. "render the response. Actual template(s) used: form_view.html, base.html",
  258. str(e)
  259. )
  260. with self.assertRaises(AssertionError) as context:
  261. self.assertTemplateUsed(response, 'base.html', count=2)
  262. self.assertIn(
  263. "Template 'base.html' was expected to be rendered 2 "
  264. "time(s) but was actually rendered 1 time(s).",
  265. str(context.exception))
  266. def test_template_rendered_multiple_times(self):
  267. """Template assertions work when a template is rendered multiple times."""
  268. response = self.client.get('/render_template_multiple_times/')
  269. self.assertTemplateUsed(response, 'base.html', count=2)
  270. @override_settings(ROOT_URLCONF='test_client_regress.urls')
  271. class AssertRedirectsTests(SimpleTestCase):
  272. def test_redirect_page(self):
  273. "An assertion is raised if the original page couldn't be retrieved as expected"
  274. # This page will redirect with code 301, not 302
  275. response = self.client.get('/permanent_redirect_view/')
  276. try:
  277. self.assertRedirects(response, '/get_view/')
  278. except AssertionError as e:
  279. self.assertIn("Response didn't redirect as expected: Response code was 301 (expected 302)", str(e))
  280. try:
  281. self.assertRedirects(response, '/get_view/', msg_prefix='abc')
  282. except AssertionError as e:
  283. self.assertIn("abc: Response didn't redirect as expected: Response code was 301 (expected 302)", str(e))
  284. def test_lost_query(self):
  285. "An assertion is raised if the redirect location doesn't preserve GET parameters"
  286. response = self.client.get('/redirect_view/', {'var': 'value'})
  287. try:
  288. self.assertRedirects(response, '/get_view/')
  289. except AssertionError as e:
  290. self.assertIn("Response redirected to '/get_view/?var=value', expected '/get_view/'", str(e))
  291. try:
  292. self.assertRedirects(response, '/get_view/', msg_prefix='abc')
  293. except AssertionError as e:
  294. self.assertIn("abc: Response redirected to '/get_view/?var=value', expected '/get_view/'", str(e))
  295. def test_incorrect_target(self):
  296. "An assertion is raised if the response redirects to another target"
  297. response = self.client.get('/permanent_redirect_view/')
  298. try:
  299. # Should redirect to get_view
  300. self.assertRedirects(response, '/some_view/')
  301. except AssertionError as e:
  302. self.assertIn("Response didn't redirect as expected: Response code was 301 (expected 302)", str(e))
  303. def test_target_page(self):
  304. "An assertion is raised if the response redirect target cannot be retrieved as expected"
  305. response = self.client.get('/double_redirect_view/')
  306. try:
  307. # The redirect target responds with a 301 code, not 200
  308. self.assertRedirects(response, 'http://testserver/permanent_redirect_view/')
  309. except AssertionError as e:
  310. self.assertIn(
  311. "Couldn't retrieve redirection page '/permanent_redirect_view/': "
  312. "response code was 301 (expected 200)",
  313. str(e)
  314. )
  315. try:
  316. # The redirect target responds with a 301 code, not 200
  317. self.assertRedirects(response, 'http://testserver/permanent_redirect_view/', msg_prefix='abc')
  318. except AssertionError as e:
  319. self.assertIn(
  320. "abc: Couldn't retrieve redirection page '/permanent_redirect_view/': "
  321. "response code was 301 (expected 200)",
  322. str(e)
  323. )
  324. def test_redirect_chain(self):
  325. "You can follow a redirect chain of multiple redirects"
  326. response = self.client.get('/redirects/further/more/', {}, follow=True)
  327. self.assertRedirects(response, '/no_template_view/', status_code=302, target_status_code=200)
  328. self.assertEqual(len(response.redirect_chain), 1)
  329. self.assertEqual(response.redirect_chain[0], ('/no_template_view/', 302))
  330. def test_multiple_redirect_chain(self):
  331. "You can follow a redirect chain of multiple redirects"
  332. response = self.client.get('/redirects/', {}, follow=True)
  333. self.assertRedirects(response, '/no_template_view/', status_code=302, target_status_code=200)
  334. self.assertEqual(len(response.redirect_chain), 3)
  335. self.assertEqual(response.redirect_chain[0], ('/redirects/further/', 302))
  336. self.assertEqual(response.redirect_chain[1], ('/redirects/further/more/', 302))
  337. self.assertEqual(response.redirect_chain[2], ('/no_template_view/', 302))
  338. def test_redirect_chain_to_non_existent(self):
  339. "You can follow a chain to a non-existent view"
  340. response = self.client.get('/redirect_to_non_existent_view2/', {}, follow=True)
  341. self.assertRedirects(response, '/non_existent_view/', status_code=302, target_status_code=404)
  342. def test_redirect_chain_to_self(self):
  343. "Redirections to self are caught and escaped"
  344. with self.assertRaises(RedirectCycleError) as context:
  345. self.client.get('/redirect_to_self/', {}, follow=True)
  346. response = context.exception.last_response
  347. # The chain of redirects stops once the cycle is detected.
  348. self.assertRedirects(response, '/redirect_to_self/', status_code=302, target_status_code=302)
  349. self.assertEqual(len(response.redirect_chain), 2)
  350. def test_redirect_to_self_with_changing_query(self):
  351. "Redirections don't loop forever even if query is changing"
  352. with self.assertRaises(RedirectCycleError):
  353. self.client.get('/redirect_to_self_with_changing_query_view/', {'counter': '0'}, follow=True)
  354. def test_circular_redirect(self):
  355. "Circular redirect chains are caught and escaped"
  356. with self.assertRaises(RedirectCycleError) as context:
  357. self.client.get('/circular_redirect_1/', {}, follow=True)
  358. response = context.exception.last_response
  359. # The chain of redirects will get back to the starting point, but stop there.
  360. self.assertRedirects(response, '/circular_redirect_2/', status_code=302, target_status_code=302)
  361. self.assertEqual(len(response.redirect_chain), 4)
  362. def test_redirect_chain_post(self):
  363. "A redirect chain will be followed from an initial POST post"
  364. response = self.client.post('/redirects/', {'nothing': 'to_send'}, follow=True)
  365. self.assertRedirects(response, '/no_template_view/', 302, 200)
  366. self.assertEqual(len(response.redirect_chain), 3)
  367. def test_redirect_chain_head(self):
  368. "A redirect chain will be followed from an initial HEAD request"
  369. response = self.client.head('/redirects/', {'nothing': 'to_send'}, follow=True)
  370. self.assertRedirects(response, '/no_template_view/', 302, 200)
  371. self.assertEqual(len(response.redirect_chain), 3)
  372. def test_redirect_chain_options(self):
  373. "A redirect chain will be followed from an initial OPTIONS request"
  374. response = self.client.options('/redirects/', follow=True)
  375. self.assertRedirects(response, '/no_template_view/', 302, 200)
  376. self.assertEqual(len(response.redirect_chain), 3)
  377. def test_redirect_chain_put(self):
  378. "A redirect chain will be followed from an initial PUT request"
  379. response = self.client.put('/redirects/', follow=True)
  380. self.assertRedirects(response, '/no_template_view/', 302, 200)
  381. self.assertEqual(len(response.redirect_chain), 3)
  382. def test_redirect_chain_delete(self):
  383. "A redirect chain will be followed from an initial DELETE request"
  384. response = self.client.delete('/redirects/', follow=True)
  385. self.assertRedirects(response, '/no_template_view/', 302, 200)
  386. self.assertEqual(len(response.redirect_chain), 3)
  387. @modify_settings(ALLOWED_HOSTS={'append': 'otherserver'})
  388. def test_redirect_to_different_host(self):
  389. "The test client will preserve scheme, host and port changes"
  390. response = self.client.get('/redirect_other_host/', follow=True)
  391. self.assertRedirects(
  392. response, 'https://otherserver:8443/no_template_view/',
  393. status_code=302, target_status_code=200
  394. )
  395. # We can't use is_secure() or get_host()
  396. # because response.request is a dictionary, not an HttpRequest
  397. self.assertEqual(response.request.get('wsgi.url_scheme'), 'https')
  398. self.assertEqual(response.request.get('SERVER_NAME'), 'otherserver')
  399. self.assertEqual(response.request.get('SERVER_PORT'), '8443')
  400. # assertRedirects() can follow redirect to 'otherserver' too.
  401. response = self.client.get('/redirect_other_host/', follow=False)
  402. self.assertRedirects(
  403. response, 'https://otherserver:8443/no_template_view/',
  404. status_code=302, target_status_code=200
  405. )
  406. def test_redirect_chain_on_non_redirect_page(self):
  407. "An assertion is raised if the original page couldn't be retrieved as expected"
  408. # This page will redirect with code 301, not 302
  409. response = self.client.get('/get_view/', follow=True)
  410. try:
  411. self.assertRedirects(response, '/get_view/')
  412. except AssertionError as e:
  413. self.assertIn("Response didn't redirect as expected: Response code was 200 (expected 302)", str(e))
  414. try:
  415. self.assertRedirects(response, '/get_view/', msg_prefix='abc')
  416. except AssertionError as e:
  417. self.assertIn("abc: Response didn't redirect as expected: Response code was 200 (expected 302)", str(e))
  418. def test_redirect_on_non_redirect_page(self):
  419. "An assertion is raised if the original page couldn't be retrieved as expected"
  420. # This page will redirect with code 301, not 302
  421. response = self.client.get('/get_view/')
  422. try:
  423. self.assertRedirects(response, '/get_view/')
  424. except AssertionError as e:
  425. self.assertIn("Response didn't redirect as expected: Response code was 200 (expected 302)", str(e))
  426. try:
  427. self.assertRedirects(response, '/get_view/', msg_prefix='abc')
  428. except AssertionError as e:
  429. self.assertIn("abc: Response didn't redirect as expected: Response code was 200 (expected 302)", str(e))
  430. def test_redirect_scheme(self):
  431. "An assertion is raised if the response doesn't have the scheme specified in expected_url"
  432. # For all possible True/False combinations of follow and secure
  433. for follow, secure in itertools.product([True, False], repeat=2):
  434. # always redirects to https
  435. response = self.client.get('/https_redirect_view/', follow=follow, secure=secure)
  436. # the goal scheme is https
  437. self.assertRedirects(response, 'https://testserver/secure_view/', status_code=302)
  438. with self.assertRaises(AssertionError):
  439. self.assertRedirects(response, 'http://testserver/secure_view/', status_code=302)
  440. @ignore_warnings(category=RemovedInDjango20Warning)
  441. def test_full_path_in_expected_urls(self):
  442. """
  443. Test that specifying a full URL as assertRedirects expected_url still
  444. work as backwards compatible behavior until Django 2.0.
  445. """
  446. response = self.client.get('/redirect_view/')
  447. self.assertRedirects(response, 'http://testserver/get_view/')
  448. @override_settings(ROOT_URLCONF='test_client_regress.urls')
  449. class AssertFormErrorTests(SimpleTestCase):
  450. def test_unknown_form(self):
  451. "An assertion is raised if the form name is unknown"
  452. post_data = {
  453. 'text': 'Hello World',
  454. 'email': 'not an email address',
  455. 'value': 37,
  456. 'single': 'b',
  457. 'multi': ('b', 'c', 'e')
  458. }
  459. response = self.client.post('/form_view/', post_data)
  460. self.assertEqual(response.status_code, 200)
  461. self.assertTemplateUsed(response, "Invalid POST Template")
  462. try:
  463. self.assertFormError(response, 'wrong_form', 'some_field', 'Some error.')
  464. except AssertionError as e:
  465. self.assertIn("The form 'wrong_form' was not used to render the response", str(e))
  466. try:
  467. self.assertFormError(response, 'wrong_form', 'some_field', 'Some error.', msg_prefix='abc')
  468. except AssertionError as e:
  469. self.assertIn("abc: The form 'wrong_form' was not used to render the response", str(e))
  470. def test_unknown_field(self):
  471. "An assertion is raised if the field name is unknown"
  472. post_data = {
  473. 'text': 'Hello World',
  474. 'email': 'not an email address',
  475. 'value': 37,
  476. 'single': 'b',
  477. 'multi': ('b', 'c', 'e')
  478. }
  479. response = self.client.post('/form_view/', post_data)
  480. self.assertEqual(response.status_code, 200)
  481. self.assertTemplateUsed(response, "Invalid POST Template")
  482. try:
  483. self.assertFormError(response, 'form', 'some_field', 'Some error.')
  484. except AssertionError as e:
  485. self.assertIn("The form 'form' in context 0 does not contain the field 'some_field'", str(e))
  486. try:
  487. self.assertFormError(response, 'form', 'some_field', 'Some error.', msg_prefix='abc')
  488. except AssertionError as e:
  489. self.assertIn("abc: The form 'form' in context 0 does not contain the field 'some_field'", str(e))
  490. def test_noerror_field(self):
  491. "An assertion is raised if the field doesn't have any errors"
  492. post_data = {
  493. 'text': 'Hello World',
  494. 'email': 'not an email address',
  495. 'value': 37,
  496. 'single': 'b',
  497. 'multi': ('b', 'c', 'e')
  498. }
  499. response = self.client.post('/form_view/', post_data)
  500. self.assertEqual(response.status_code, 200)
  501. self.assertTemplateUsed(response, "Invalid POST Template")
  502. try:
  503. self.assertFormError(response, 'form', 'value', 'Some error.')
  504. except AssertionError as e:
  505. self.assertIn("The field 'value' on form 'form' in context 0 contains no errors", str(e))
  506. try:
  507. self.assertFormError(response, 'form', 'value', 'Some error.', msg_prefix='abc')
  508. except AssertionError as e:
  509. self.assertIn("abc: The field 'value' on form 'form' in context 0 contains no errors", str(e))
  510. def test_unknown_error(self):
  511. "An assertion is raised if the field doesn't contain the provided error"
  512. post_data = {
  513. 'text': 'Hello World',
  514. 'email': 'not an email address',
  515. 'value': 37,
  516. 'single': 'b',
  517. 'multi': ('b', 'c', 'e')
  518. }
  519. response = self.client.post('/form_view/', post_data)
  520. self.assertEqual(response.status_code, 200)
  521. self.assertTemplateUsed(response, "Invalid POST Template")
  522. try:
  523. self.assertFormError(response, 'form', 'email', 'Some error.')
  524. except AssertionError as e:
  525. self.assertIn(
  526. str_prefix(
  527. "The field 'email' on form 'form' in context 0 does not "
  528. "contain the error 'Some error.' (actual errors: "
  529. "[%(_)s'Enter a valid email address.'])"
  530. ), str(e)
  531. )
  532. try:
  533. self.assertFormError(response, 'form', 'email', 'Some error.', msg_prefix='abc')
  534. except AssertionError as e:
  535. self.assertIn(
  536. str_prefix(
  537. "abc: The field 'email' on form 'form' in context 0 does "
  538. "not contain the error 'Some error.' (actual errors: "
  539. "[%(_)s'Enter a valid email address.'])",
  540. ), str(e)
  541. )
  542. def test_unknown_nonfield_error(self):
  543. """
  544. Checks that an assertion is raised if the form's non field errors
  545. doesn't contain the provided error.
  546. """
  547. post_data = {
  548. 'text': 'Hello World',
  549. 'email': 'not an email address',
  550. 'value': 37,
  551. 'single': 'b',
  552. 'multi': ('b', 'c', 'e')
  553. }
  554. response = self.client.post('/form_view/', post_data)
  555. self.assertEqual(response.status_code, 200)
  556. self.assertTemplateUsed(response, "Invalid POST Template")
  557. try:
  558. self.assertFormError(response, 'form', None, 'Some error.')
  559. except AssertionError as e:
  560. self.assertIn(
  561. "The form 'form' in context 0 does not contain the non-field "
  562. "error 'Some error.' (actual errors: )",
  563. str(e)
  564. )
  565. try:
  566. self.assertFormError(response, 'form', None, 'Some error.', msg_prefix='abc')
  567. except AssertionError as e:
  568. self.assertIn(
  569. "abc: The form 'form' in context 0 does not contain the "
  570. "non-field error 'Some error.' (actual errors: )",
  571. str(e)
  572. )
  573. @override_settings(ROOT_URLCONF='test_client_regress.urls')
  574. class AssertFormsetErrorTests(SimpleTestCase):
  575. msg_prefixes = [("", {}), ("abc: ", {"msg_prefix": "abc"})]
  576. def setUp(self):
  577. """Makes response object for testing field and non-field errors"""
  578. # For testing field and non-field errors
  579. self.response_form_errors = self.getResponse({
  580. 'form-TOTAL_FORMS': '2',
  581. 'form-INITIAL_FORMS': '2',
  582. 'form-0-text': 'Raise non-field error',
  583. 'form-0-email': 'not an email address',
  584. 'form-0-value': 37,
  585. 'form-0-single': 'b',
  586. 'form-0-multi': ('b', 'c', 'e'),
  587. 'form-1-text': 'Hello World',
  588. 'form-1-email': 'email@domain.com',
  589. 'form-1-value': 37,
  590. 'form-1-single': 'b',
  591. 'form-1-multi': ('b', 'c', 'e'),
  592. })
  593. # For testing non-form errors
  594. self.response_nonform_errors = self.getResponse({
  595. 'form-TOTAL_FORMS': '2',
  596. 'form-INITIAL_FORMS': '2',
  597. 'form-0-text': 'Hello World',
  598. 'form-0-email': 'email@domain.com',
  599. 'form-0-value': 37,
  600. 'form-0-single': 'b',
  601. 'form-0-multi': ('b', 'c', 'e'),
  602. 'form-1-text': 'Hello World',
  603. 'form-1-email': 'email@domain.com',
  604. 'form-1-value': 37,
  605. 'form-1-single': 'b',
  606. 'form-1-multi': ('b', 'c', 'e'),
  607. })
  608. def getResponse(self, post_data):
  609. response = self.client.post('/formset_view/', post_data)
  610. self.assertEqual(response.status_code, 200)
  611. self.assertTemplateUsed(response, "Invalid POST Template")
  612. return response
  613. def test_unknown_formset(self):
  614. "An assertion is raised if the formset name is unknown"
  615. for prefix, kwargs in self.msg_prefixes:
  616. msg = prefix + "The formset 'wrong_formset' was not used to render the response"
  617. with self.assertRaisesMessage(AssertionError, msg):
  618. self.assertFormsetError(
  619. self.response_form_errors,
  620. 'wrong_formset', 0, 'Some_field', 'Some error.', **kwargs
  621. )
  622. def test_unknown_field(self):
  623. "An assertion is raised if the field name is unknown"
  624. for prefix, kwargs in self.msg_prefixes:
  625. msg = prefix + "The formset 'my_formset', form 0 in context 0 does not contain the field 'Some_field'"
  626. with self.assertRaisesMessage(AssertionError, msg):
  627. self.assertFormsetError(
  628. self.response_form_errors,
  629. 'my_formset', 0, 'Some_field', 'Some error.', **kwargs
  630. )
  631. def test_no_error_field(self):
  632. "An assertion is raised if the field doesn't have any errors"
  633. for prefix, kwargs in self.msg_prefixes:
  634. msg = prefix + "The field 'value' on formset 'my_formset', form 1 in context 0 contains no errors"
  635. with self.assertRaisesMessage(AssertionError, msg):
  636. self.assertFormsetError(self.response_form_errors, 'my_formset', 1, 'value', 'Some error.', **kwargs)
  637. def test_unknown_error(self):
  638. "An assertion is raised if the field doesn't contain the specified error"
  639. for prefix, kwargs in self.msg_prefixes:
  640. msg = str_prefix(
  641. prefix + "The field 'email' on formset 'my_formset', form 0 "
  642. "in context 0 does not contain the error 'Some error.' "
  643. "(actual errors: [%(_)s'Enter a valid email address.'])"
  644. )
  645. with self.assertRaisesMessage(AssertionError, msg):
  646. self.assertFormsetError(self.response_form_errors, 'my_formset', 0, 'email', 'Some error.', **kwargs)
  647. def test_field_error(self):
  648. "No assertion is raised if the field contains the provided error"
  649. error_msg = ['Enter a valid email address.']
  650. for prefix, kwargs in self.msg_prefixes:
  651. self.assertFormsetError(self.response_form_errors, 'my_formset', 0, 'email', error_msg, **kwargs)
  652. def test_no_nonfield_error(self):
  653. "An assertion is raised if the formsets non-field errors doesn't contain any errors."
  654. for prefix, kwargs in self.msg_prefixes:
  655. msg = prefix + "The formset 'my_formset', form 1 in context 0 does not contain any non-field errors."
  656. with self.assertRaisesMessage(AssertionError, msg):
  657. self.assertFormsetError(self.response_form_errors, 'my_formset', 1, None, 'Some error.', **kwargs)
  658. def test_unknown_nonfield_error(self):
  659. "An assertion is raised if the formsets non-field errors doesn't contain the provided error."
  660. for prefix, kwargs in self.msg_prefixes:
  661. msg = str_prefix(
  662. prefix + "The formset 'my_formset', form 0 in context 0 does not "
  663. "contain the non-field error 'Some error.' (actual errors: "
  664. "[%(_)s'Non-field error.'])"
  665. )
  666. with self.assertRaisesMessage(AssertionError, msg):
  667. self.assertFormsetError(self.response_form_errors, 'my_formset', 0, None, 'Some error.', **kwargs)
  668. def test_nonfield_error(self):
  669. "No assertion is raised if the formsets non-field errors contains the provided error."
  670. for prefix, kwargs in self.msg_prefixes:
  671. self.assertFormsetError(self.response_form_errors, 'my_formset', 0, None, 'Non-field error.', **kwargs)
  672. def test_no_nonform_error(self):
  673. "An assertion is raised if the formsets non-form errors doesn't contain any errors."
  674. for prefix, kwargs in self.msg_prefixes:
  675. msg = prefix + "The formset 'my_formset' in context 0 does not contain any non-form errors."
  676. with self.assertRaisesMessage(AssertionError, msg):
  677. self.assertFormsetError(self.response_form_errors, 'my_formset', None, None, 'Some error.', **kwargs)
  678. def test_unknown_nonform_error(self):
  679. "An assertion is raised if the formsets non-form errors doesn't contain the provided error."
  680. for prefix, kwargs in self.msg_prefixes:
  681. msg = str_prefix(
  682. prefix +
  683. "The formset 'my_formset' in context 0 does not contain the "
  684. "non-form error 'Some error.' (actual errors: [%(_)s'Forms "
  685. "in a set must have distinct email addresses.'])"
  686. )
  687. with self.assertRaisesMessage(AssertionError, msg):
  688. self.assertFormsetError(
  689. self.response_nonform_errors,
  690. 'my_formset', None, None, 'Some error.', **kwargs
  691. )
  692. def test_nonform_error(self):
  693. "No assertion is raised if the formsets non-form errors contains the provided error."
  694. msg = 'Forms in a set must have distinct email addresses.'
  695. for prefix, kwargs in self.msg_prefixes:
  696. self.assertFormsetError(self.response_nonform_errors, 'my_formset', None, None, msg, **kwargs)
  697. @override_settings(ROOT_URLCONF='test_client_regress.urls')
  698. class LoginTests(TestDataMixin, TestCase):
  699. def test_login_different_client(self):
  700. "Check that using a different test client doesn't violate authentication"
  701. # Create a second client, and log in.
  702. c = Client()
  703. login = c.login(username='testclient', password='password')
  704. self.assertTrue(login, 'Could not log in')
  705. # Get a redirection page with the second client.
  706. response = c.get("/login_protected_redirect_view/")
  707. # At this points, the self.client isn't logged in.
  708. # Check that assertRedirects uses the original client, not the
  709. # default client.
  710. self.assertRedirects(response, "/get_view/")
  711. @override_settings(
  712. SESSION_ENGINE='test_client_regress.session',
  713. ROOT_URLCONF='test_client_regress.urls',
  714. )
  715. class SessionEngineTests(TestDataMixin, TestCase):
  716. def test_login(self):
  717. "A session engine that modifies the session key can be used to log in"
  718. login = self.client.login(username='testclient', password='password')
  719. self.assertTrue(login, 'Could not log in')
  720. # Try to access a login protected page.
  721. response = self.client.get("/login_protected_view/")
  722. self.assertEqual(response.status_code, 200)
  723. self.assertEqual(response.context['user'].username, 'testclient')
  724. @override_settings(ROOT_URLCONF='test_client_regress.urls',)
  725. class URLEscapingTests(SimpleTestCase):
  726. def test_simple_argument_get(self):
  727. "Get a view that has a simple string argument"
  728. response = self.client.get(reverse('arg_view', args=['Slartibartfast']))
  729. self.assertEqual(response.status_code, 200)
  730. self.assertEqual(response.content, b'Howdy, Slartibartfast')
  731. def test_argument_with_space_get(self):
  732. "Get a view that has a string argument that requires escaping"
  733. response = self.client.get(reverse('arg_view', args=['Arthur Dent']))
  734. self.assertEqual(response.status_code, 200)
  735. self.assertEqual(response.content, b'Hi, Arthur')
  736. def test_simple_argument_post(self):
  737. "Post for a view that has a simple string argument"
  738. response = self.client.post(reverse('arg_view', args=['Slartibartfast']))
  739. self.assertEqual(response.status_code, 200)
  740. self.assertEqual(response.content, b'Howdy, Slartibartfast')
  741. def test_argument_with_space_post(self):
  742. "Post for a view that has a string argument that requires escaping"
  743. response = self.client.post(reverse('arg_view', args=['Arthur Dent']))
  744. self.assertEqual(response.status_code, 200)
  745. self.assertEqual(response.content, b'Hi, Arthur')
  746. @override_settings(ROOT_URLCONF='test_client_regress.urls')
  747. class ExceptionTests(TestDataMixin, TestCase):
  748. def test_exception_cleared(self):
  749. "#5836 - A stale user exception isn't re-raised by the test client."
  750. login = self.client.login(username='testclient', password='password')
  751. self.assertTrue(login, 'Could not log in')
  752. try:
  753. self.client.get("/staff_only/")
  754. self.fail("General users should not be able to visit this page")
  755. except CustomTestException:
  756. pass
  757. # At this point, an exception has been raised, and should be cleared.
  758. # This next operation should be successful; if it isn't we have a problem.
  759. login = self.client.login(username='staff', password='password')
  760. self.assertTrue(login, 'Could not log in')
  761. try:
  762. self.client.get("/staff_only/")
  763. except CustomTestException:
  764. self.fail("Staff should be able to visit this page")
  765. @override_settings(ROOT_URLCONF='test_client_regress.urls')
  766. class TemplateExceptionTests(SimpleTestCase):
  767. @override_settings(TEMPLATES=[{
  768. 'BACKEND': 'django.template.backends.django.DjangoTemplates',
  769. 'DIRS': [os.path.join(os.path.dirname(upath(__file__)), 'bad_templates')],
  770. }])
  771. def test_bad_404_template(self):
  772. "Errors found when rendering 404 error templates are re-raised"
  773. try:
  774. self.client.get("/no_such_view/")
  775. except TemplateSyntaxError:
  776. pass
  777. else:
  778. self.fail("Should get error about syntax error in template")
  779. # We need two different tests to check URLconf substitution - one to check
  780. # it was changed, and another one (without self.urls) to check it was reverted on
  781. # teardown. This pair of tests relies upon the alphabetical ordering of test execution.
  782. @override_settings(ROOT_URLCONF='test_client_regress.urls')
  783. class UrlconfSubstitutionTests(SimpleTestCase):
  784. def test_urlconf_was_changed(self):
  785. "TestCase can enforce a custom URLconf on a per-test basis"
  786. url = reverse('arg_view', args=['somename'])
  787. self.assertEqual(url, '/arg_view/somename/')
  788. # This test needs to run *after* UrlconfSubstitutionTests; the zz prefix in the
  789. # name is to ensure alphabetical ordering.
  790. class zzUrlconfSubstitutionTests(SimpleTestCase):
  791. def test_urlconf_was_reverted(self):
  792. """URLconf is reverted to original value after modification in a TestCase
  793. This will not find a match as the default ROOT_URLCONF is empty.
  794. """
  795. with self.assertRaises(NoReverseMatch):
  796. reverse('arg_view', args=['somename'])
  797. @override_settings(ROOT_URLCONF='test_client_regress.urls')
  798. class ContextTests(TestDataMixin, TestCase):
  799. def test_single_context(self):
  800. "Context variables can be retrieved from a single context"
  801. response = self.client.get("/request_data/", data={'foo': 'whiz'})
  802. self.assertIsInstance(response.context, RequestContext)
  803. self.assertIn('get-foo', response.context)
  804. self.assertEqual(response.context['get-foo'], 'whiz')
  805. self.assertEqual(response.context['data'], 'sausage')
  806. try:
  807. response.context['does-not-exist']
  808. self.fail('Should not be able to retrieve non-existent key')
  809. except KeyError as e:
  810. self.assertEqual(e.args[0], 'does-not-exist')
  811. def test_inherited_context(self):
  812. "Context variables can be retrieved from a list of contexts"
  813. response = self.client.get("/request_data_extended/", data={'foo': 'whiz'})
  814. self.assertEqual(response.context.__class__, ContextList)
  815. self.assertEqual(len(response.context), 2)
  816. self.assertIn('get-foo', response.context)
  817. self.assertEqual(response.context['get-foo'], 'whiz')
  818. self.assertEqual(response.context['data'], 'bacon')
  819. with self.assertRaises(KeyError) as cm:
  820. response.context['does-not-exist']
  821. self.assertEqual(cm.exception.args[0], 'does-not-exist')
  822. def test_contextlist_keys(self):
  823. c1 = Context()
  824. c1.update({'hello': 'world', 'goodbye': 'john'})
  825. c1.update({'hello': 'dolly', 'dolly': 'parton'})
  826. c2 = Context()
  827. c2.update({'goodbye': 'world', 'python': 'rocks'})
  828. c2.update({'goodbye': 'dolly'})
  829. l = ContextList([c1, c2])
  830. # None, True and False are builtins of BaseContext, and present
  831. # in every Context without needing to be added.
  832. self.assertEqual({'None', 'True', 'False', 'hello', 'goodbye', 'python', 'dolly'}, l.keys())
  833. def test_15368(self):
  834. # Need to insert a context processor that assumes certain things about
  835. # the request instance. This triggers a bug caused by some ways of
  836. # copying RequestContext.
  837. with self.settings(TEMPLATES=[{
  838. 'BACKEND': 'django.template.backends.django.DjangoTemplates',
  839. 'APP_DIRS': True,
  840. 'OPTIONS': {
  841. 'context_processors': [
  842. 'test_client_regress.context_processors.special',
  843. ],
  844. },
  845. }]):
  846. response = self.client.get("/request_context_view/")
  847. self.assertContains(response, 'Path: /request_context_view/')
  848. def test_nested_requests(self):
  849. """
  850. response.context is not lost when view call another view.
  851. """
  852. response = self.client.get("/nested_view/")
  853. self.assertIsInstance(response.context, RequestContext)
  854. self.assertEqual(response.context['nested'], 'yes')
  855. @override_settings(ROOT_URLCONF='test_client_regress.urls')
  856. class SessionTests(TestDataMixin, TestCase):
  857. def test_session(self):
  858. "The session isn't lost if a user logs in"
  859. # The session doesn't exist to start.
  860. response = self.client.get('/check_session/')
  861. self.assertEqual(response.status_code, 200)
  862. self.assertEqual(response.content, b'NO')
  863. # This request sets a session variable.
  864. response = self.client.get('/set_session/')
  865. self.assertEqual(response.status_code, 200)
  866. self.assertEqual(response.content, b'set_session')
  867. # Check that the session has been modified
  868. response = self.client.get('/check_session/')
  869. self.assertEqual(response.status_code, 200)
  870. self.assertEqual(response.content, b'YES')
  871. # Log in
  872. login = self.client.login(username='testclient', password='password')
  873. self.assertTrue(login, 'Could not log in')
  874. # Session should still contain the modified value
  875. response = self.client.get('/check_session/')
  876. self.assertEqual(response.status_code, 200)
  877. self.assertEqual(response.content, b'YES')
  878. def test_session_initiated(self):
  879. session = self.client.session
  880. session['session_var'] = 'foo'
  881. session.save()
  882. response = self.client.get('/check_session/')
  883. self.assertEqual(response.content, b'foo')
  884. def test_logout(self):
  885. """Logout should work whether the user is logged in or not (#9978)."""
  886. self.client.logout()
  887. login = self.client.login(username='testclient', password='password')
  888. self.assertTrue(login, 'Could not log in')
  889. self.client.logout()
  890. self.client.logout()
  891. def test_logout_with_user(self):
  892. """Logout should send user_logged_out signal if user was logged in."""
  893. def listener(*args, **kwargs):
  894. listener.executed = True
  895. self.assertEqual(kwargs['sender'], User)
  896. listener.executed = False
  897. user_logged_out.connect(listener)
  898. self.client.login(username='testclient', password='password')
  899. self.client.logout()
  900. user_logged_out.disconnect(listener)
  901. self.assertTrue(listener.executed)
  902. @override_settings(AUTH_USER_MODEL='test_client_regress.CustomUser')
  903. def test_logout_with_custom_user(self):
  904. """Logout should send user_logged_out signal if custom user was logged in."""
  905. def listener(*args, **kwargs):
  906. self.assertEqual(kwargs['sender'], CustomUser)
  907. listener.executed = True
  908. listener.executed = False
  909. u = CustomUser.custom_objects.create(email='test@test.com')
  910. u.set_password('password')
  911. u.save()
  912. user_logged_out.connect(listener)
  913. self.client.login(username='test@test.com', password='password')
  914. self.client.logout()
  915. user_logged_out.disconnect(listener)
  916. self.assertTrue(listener.executed)
  917. @override_settings(AUTHENTICATION_BACKENDS=(
  918. 'django.contrib.auth.backends.ModelBackend',
  919. 'test_client_regress.auth_backends.CustomUserBackend'))
  920. def test_logout_with_custom_auth_backend(self):
  921. "Request a logout after logging in with custom authentication backend"
  922. def listener(*args, **kwargs):
  923. self.assertEqual(kwargs['sender'], CustomUser)
  924. listener.executed = True
  925. listener.executed = False
  926. u = CustomUser.custom_objects.create(email='test@test.com')
  927. u.set_password('password')
  928. u.save()
  929. user_logged_out.connect(listener)
  930. self.client.login(username='test@test.com', password='password')
  931. self.client.logout()
  932. user_logged_out.disconnect(listener)
  933. self.assertTrue(listener.executed)
  934. def test_logout_without_user(self):
  935. """Logout should send signal even if user not authenticated."""
  936. def listener(user, *args, **kwargs):
  937. listener.user = user
  938. listener.executed = True
  939. listener.executed = False
  940. user_logged_out.connect(listener)
  941. self.client.login(username='incorrect', password='password')
  942. self.client.logout()
  943. user_logged_out.disconnect(listener)
  944. self.assertTrue(listener.executed)
  945. self.assertIsNone(listener.user)
  946. def test_login_with_user(self):
  947. """Login should send user_logged_in signal on successful login."""
  948. def listener(*args, **kwargs):
  949. listener.executed = True
  950. listener.executed = False
  951. user_logged_in.connect(listener)
  952. self.client.login(username='testclient', password='password')
  953. user_logged_out.disconnect(listener)
  954. self.assertTrue(listener.executed)
  955. def test_login_without_signal(self):
  956. """Login shouldn't send signal if user wasn't logged in"""
  957. def listener(*args, **kwargs):
  958. listener.executed = True
  959. listener.executed = False
  960. user_logged_in.connect(listener)
  961. self.client.login(username='incorrect', password='password')
  962. user_logged_in.disconnect(listener)
  963. self.assertFalse(listener.executed)
  964. @override_settings(ROOT_URLCONF='test_client_regress.urls')
  965. class RequestMethodTests(SimpleTestCase):
  966. def test_get(self):
  967. "Request a view via request method GET"
  968. response = self.client.get('/request_methods/')
  969. self.assertEqual(response.status_code, 200)
  970. self.assertEqual(response.content, b'request method: GET')
  971. def test_post(self):
  972. "Request a view via request method POST"
  973. response = self.client.post('/request_methods/')
  974. self.assertEqual(response.status_code, 200)
  975. self.assertEqual(response.content, b'request method: POST')
  976. def test_head(self):
  977. "Request a view via request method HEAD"
  978. response = self.client.head('/request_methods/')
  979. self.assertEqual(response.status_code, 200)
  980. # A HEAD request doesn't return any content.
  981. self.assertNotEqual(response.content, b'request method: HEAD')
  982. self.assertEqual(response.content, b'')
  983. def test_options(self):
  984. "Request a view via request method OPTIONS"
  985. response = self.client.options('/request_methods/')
  986. self.assertEqual(response.status_code, 200)
  987. self.assertEqual(response.content, b'request method: OPTIONS')
  988. def test_put(self):
  989. "Request a view via request method PUT"
  990. response = self.client.put('/request_methods/')
  991. self.assertEqual(response.status_code, 200)
  992. self.assertEqual(response.content, b'request method: PUT')
  993. def test_delete(self):
  994. "Request a view via request method DELETE"
  995. response = self.client.delete('/request_methods/')
  996. self.assertEqual(response.status_code, 200)
  997. self.assertEqual(response.content, b'request method: DELETE')
  998. def test_patch(self):
  999. "Request a view via request method PATCH"
  1000. response = self.client.patch('/request_methods/')
  1001. self.assertEqual(response.status_code, 200)
  1002. self.assertEqual(response.content, b'request method: PATCH')
  1003. @override_settings(ROOT_URLCONF='test_client_regress.urls')
  1004. class RequestMethodStringDataTests(SimpleTestCase):
  1005. def test_post(self):
  1006. "Request a view with string data via request method POST"
  1007. # Regression test for #11371
  1008. data = '{"test": "json"}'
  1009. response = self.client.post('/request_methods/', data=data, content_type='application/json')
  1010. self.assertEqual(response.status_code, 200)
  1011. self.assertEqual(response.content, b'request method: POST')
  1012. def test_put(self):
  1013. "Request a view with string data via request method PUT"
  1014. # Regression test for #11371
  1015. data = '{"test": "json"}'
  1016. response = self.client.put('/request_methods/', data=data, content_type='application/json')
  1017. self.assertEqual(response.status_code, 200)
  1018. self.assertEqual(response.content, b'request method: PUT')
  1019. def test_patch(self):
  1020. "Request a view with string data via request method PATCH"
  1021. # Regression test for #17797
  1022. data = '{"test": "json"}'
  1023. response = self.client.patch('/request_methods/', data=data, content_type='application/json')
  1024. self.assertEqual(response.status_code, 200)
  1025. self.assertEqual(response.content, b'request method: PATCH')
  1026. def test_empty_string_data(self):
  1027. "Request a view with empty string data via request method GET/POST/HEAD"
  1028. # Regression test for #21740
  1029. response = self.client.get('/body/', data='', content_type='application/json')
  1030. self.assertEqual(response.content, b'')
  1031. response = self.client.post('/body/', data='', content_type='application/json')
  1032. self.assertEqual(response.content, b'')
  1033. response = self.client.head('/body/', data='', content_type='application/json')
  1034. self.assertEqual(response.content, b'')
  1035. def test_json(self):
  1036. response = self.client.get('/json_response/')
  1037. self.assertEqual(response.json(), {'key': 'value'})
  1038. def test_json_wrong_header(self):
  1039. response = self.client.get('/body/')
  1040. msg = 'Content-Type header is "text/html; charset=utf-8", not "application/json"'
  1041. with self.assertRaisesMessage(ValueError, msg):
  1042. self.assertEqual(response.json(), {'key': 'value'})
  1043. @override_settings(ROOT_URLCONF='test_client_regress.urls',)
  1044. class QueryStringTests(SimpleTestCase):
  1045. def test_get_like_requests(self):
  1046. # See: https://code.djangoproject.com/ticket/10571.
  1047. for method_name in ('get', 'head'):
  1048. # A GET-like request can pass a query string as data
  1049. method = getattr(self.client, method_name)
  1050. response = method("/request_data/", data={'foo': 'whiz'})
  1051. self.assertEqual(response.context['get-foo'], 'whiz')
  1052. # A GET-like request can pass a query string as part of the URL
  1053. response = method("/request_data/?foo=whiz")
  1054. self.assertEqual(response.context['get-foo'], 'whiz')
  1055. # Data provided in the URL to a GET-like request is overridden by actual form data
  1056. response = method("/request_data/?foo=whiz", data={'foo': 'bang'})
  1057. self.assertEqual(response.context['get-foo'], 'bang')
  1058. response = method("/request_data/?foo=whiz", data={'bar': 'bang'})
  1059. self.assertIsNone(response.context['get-foo'])
  1060. self.assertEqual(response.context['get-bar'], 'bang')
  1061. def test_post_like_requests(self):
  1062. # A POST-like request can pass a query string as data
  1063. response = self.client.post("/request_data/", data={'foo': 'whiz'})
  1064. self.assertIsNone(response.context['get-foo'])
  1065. self.assertEqual(response.context['post-foo'], 'whiz')
  1066. # A POST-like request can pass a query string as part of the URL
  1067. response = self.client.post("/request_data/?foo=whiz")
  1068. self.assertEqual(response.context['get-foo'], 'whiz')
  1069. self.assertIsNone(response.context['post-foo'])
  1070. # POST data provided in the URL augments actual form data
  1071. response = self.client.post("/request_data/?foo=whiz", data={'foo': 'bang'})
  1072. self.assertEqual(response.context['get-foo'], 'whiz')
  1073. self.assertEqual(response.context['post-foo'], 'bang')
  1074. response = self.client.post("/request_data/?foo=whiz", data={'bar': 'bang'})
  1075. self.assertEqual(response.context['get-foo'], 'whiz')
  1076. self.assertIsNone(response.context['get-bar'])
  1077. self.assertIsNone(response.context['post-foo'])
  1078. self.assertEqual(response.context['post-bar'], 'bang')
  1079. @override_settings(ROOT_URLCONF='test_client_regress.urls')
  1080. class UnicodePayloadTests(SimpleTestCase):
  1081. def test_simple_unicode_payload(self):
  1082. "A simple ASCII-only unicode JSON document can be POSTed"
  1083. # Regression test for #10571
  1084. json = '{"english": "mountain pass"}'
  1085. response = self.client.post("/parse_unicode_json/", json, content_type="application/json")
  1086. self.assertEqual(response.content, json.encode())
  1087. def test_unicode_payload_utf8(self):
  1088. "A non-ASCII unicode data encoded as UTF-8 can be POSTed"
  1089. # Regression test for #10571
  1090. json = '{"dog": "собака"}'
  1091. response = self.client.post("/parse_unicode_json/", json, content_type="application/json; charset=utf-8")
  1092. self.assertEqual(response.content, json.encode('utf-8'))
  1093. def test_unicode_payload_utf16(self):
  1094. "A non-ASCII unicode data encoded as UTF-16 can be POSTed"
  1095. # Regression test for #10571
  1096. json = '{"dog": "собака"}'
  1097. response = self.client.post("/parse_unicode_json/", json, content_type="application/json; charset=utf-16")
  1098. self.assertEqual(response.content, json.encode('utf-16'))
  1099. def test_unicode_payload_non_utf(self):
  1100. "A non-ASCII unicode data as a non-UTF based encoding can be POSTed"
  1101. # Regression test for #10571
  1102. json = '{"dog": "собака"}'
  1103. response = self.client.post("/parse_unicode_json/", json, content_type="application/json; charset=koi8-r")
  1104. self.assertEqual(response.content, json.encode('koi8-r'))
  1105. class DummyFile(object):
  1106. def __init__(self, filename):
  1107. self.name = filename
  1108. def read(self):
  1109. return b'TEST_FILE_CONTENT'
  1110. class UploadedFileEncodingTest(SimpleTestCase):
  1111. def test_file_encoding(self):
  1112. encoded_file = encode_file('TEST_BOUNDARY', 'TEST_KEY', DummyFile('test_name.bin'))
  1113. self.assertEqual(b'--TEST_BOUNDARY', encoded_file[0])
  1114. self.assertEqual(b'Content-Disposition: form-data; name="TEST_KEY"; filename="test_name.bin"', encoded_file[1])
  1115. self.assertEqual(b'TEST_FILE_CONTENT', encoded_file[-1])
  1116. def test_guesses_content_type_on_file_encoding(self):
  1117. self.assertEqual(b'Content-Type: application/octet-stream',
  1118. encode_file('IGNORE', 'IGNORE', DummyFile("file.bin"))[2])
  1119. self.assertEqual(b'Content-Type: text/plain',
  1120. encode_file('IGNORE', 'IGNORE', DummyFile("file.txt"))[2])
  1121. self.assertIn(encode_file('IGNORE', 'IGNORE', DummyFile("file.zip"))[2], (
  1122. b'Content-Type: application/x-compress',
  1123. b'Content-Type: application/x-zip',
  1124. b'Content-Type: application/x-zip-compressed',
  1125. b'Content-Type: application/zip',))
  1126. self.assertEqual(b'Content-Type: application/octet-stream',
  1127. encode_file('IGNORE', 'IGNORE', DummyFile("file.unknown"))[2])
  1128. @override_settings(ROOT_URLCONF='test_client_regress.urls',)
  1129. class RequestHeadersTest(SimpleTestCase):
  1130. def test_client_headers(self):
  1131. "A test client can receive custom headers"
  1132. response = self.client.get("/check_headers/", HTTP_X_ARG_CHECK='Testing 123')
  1133. self.assertEqual(response.content, b"HTTP_X_ARG_CHECK: Testing 123")
  1134. self.assertEqual(response.status_code, 200)
  1135. def test_client_headers_redirect(self):
  1136. "Test client headers are preserved through redirects"
  1137. response = self.client.get("/check_headers_redirect/", follow=True, HTTP_X_ARG_CHECK='Testing 123')
  1138. self.assertEqual(response.content, b"HTTP_X_ARG_CHECK: Testing 123")
  1139. self.assertRedirects(response, '/check_headers/', status_code=302, target_status_code=200)
  1140. @override_settings(ROOT_URLCONF='test_client_regress.urls')
  1141. class ReadLimitedStreamTest(SimpleTestCase):
  1142. """
  1143. Tests that ensure that HttpRequest.body, HttpRequest.read() and
  1144. HttpRequest.read(BUFFER) have proper LimitedStream behavior.
  1145. Refs #14753, #15785
  1146. """
  1147. def test_body_from_empty_request(self):
  1148. """HttpRequest.body on a test client GET request should return
  1149. the empty string."""
  1150. self.assertEqual(self.client.get("/body/").content, b'')
  1151. def test_read_from_empty_request(self):
  1152. """HttpRequest.read() on a test client GET request should return the
  1153. empty string."""
  1154. self.assertEqual(self.client.get("/read_all/").content, b'')
  1155. def test_read_numbytes_from_empty_request(self):
  1156. """HttpRequest.read(LARGE_BUFFER) on a test client GET request should
  1157. return the empty string."""
  1158. self.assertEqual(self.client.get("/read_buffer/").content, b'')
  1159. def test_read_from_nonempty_request(self):
  1160. """HttpRequest.read() on a test client PUT request with some payload
  1161. should return that payload."""
  1162. payload = b'foobar'
  1163. self.assertEqual(self.client.put("/read_all/", data=payload, content_type='text/plain').content, payload)
  1164. def test_read_numbytes_from_nonempty_request(self):
  1165. """HttpRequest.read(LARGE_BUFFER) on a test client PUT request with
  1166. some payload should return that payload."""
  1167. payload = b'foobar'
  1168. self.assertEqual(self.client.put("/read_buffer/", data=payload, content_type='text/plain').content, payload)
  1169. @override_settings(ROOT_URLCONF='test_client_regress.urls')
  1170. class RequestFactoryStateTest(SimpleTestCase):
  1171. """Regression tests for #15929."""
  1172. # These tests are checking that certain middleware don't change certain
  1173. # global state. Alternatively, from the point of view of a test, they are
  1174. # ensuring test isolation behavior. So, unusually, it doesn't make sense to
  1175. # run the tests individually, and if any are failing it is confusing to run
  1176. # them with any other set of tests.
  1177. def common_test_that_should_always_pass(self):
  1178. request = RequestFactory().get('/')
  1179. request.session = {}
  1180. self.assertFalse(hasattr(request, 'user'))
  1181. def test_request(self):
  1182. self.common_test_that_should_always_pass()
  1183. def test_request_after_client(self):
  1184. # apart from the next line the three tests are identical
  1185. self.client.get('/')
  1186. self.common_test_that_should_always_pass()
  1187. def test_request_after_client_2(self):
  1188. # This test is executed after the previous one
  1189. self.common_test_that_should_always_pass()
  1190. @override_settings(ROOT_URLCONF='test_client_regress.urls')
  1191. class RequestFactoryEnvironmentTests(SimpleTestCase):
  1192. """
  1193. Regression tests for #8551 and #17067: ensure that environment variables
  1194. are set correctly in RequestFactory.
  1195. """
  1196. def test_should_set_correct_env_variables(self):
  1197. request = RequestFactory().get('/path/')
  1198. self.assertEqual(request.META.get('REMOTE_ADDR'), '127.0.0.1')
  1199. self.assertEqual(request.META.get('SERVER_NAME'), 'testserver')
  1200. self.assertEqual(request.META.get('SERVER_PORT'), '80')
  1201. self.assertEqual(request.META.get('SERVER_PROTOCOL'), 'HTTP/1.1')
  1202. self.assertEqual(request.META.get('SCRIPT_NAME') + request.META.get('PATH_INFO'), '/path/')