tests.py 62 KB

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