tests.py 64 KB

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