tests.py 65 KB

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