tests.py 67 KB

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