PageRenderTime 22ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/regressiontests/templates/response.py

https://code.google.com/p/mango-py/
Python | 316 lines | 247 code | 51 blank | 18 comment | 2 complexity | 0bdcc31e267336e22e57a3c90976b78c MD5 | raw file
Possible License(s): BSD-3-Clause
  1. from datetime import datetime
  2. import os
  3. import pickle
  4. import time
  5. from django.utils import unittest
  6. from django.test import RequestFactory, TestCase
  7. from django.conf import settings
  8. import django.template.context
  9. from django.template import Template, Context, RequestContext
  10. from django.template.response import (TemplateResponse, SimpleTemplateResponse,
  11. ContentNotRenderedError)
  12. def test_processor(request):
  13. return {'processors': 'yes'}
  14. test_processor_name = 'regressiontests.templates.response.test_processor'
  15. # A test middleware that installs a temporary URLConf
  16. class CustomURLConfMiddleware(object):
  17. def process_request(self, request):
  18. request.urlconf = 'regressiontests.templates.alternate_urls'
  19. class BaseTemplateResponseTest(unittest.TestCase):
  20. # tests rely on fact that global context
  21. # processors should only work when RequestContext is used.
  22. def setUp(self):
  23. self.factory = RequestFactory()
  24. self._old_processors = settings.TEMPLATE_CONTEXT_PROCESSORS
  25. self._old_TEMPLATE_DIRS = settings.TEMPLATE_DIRS
  26. settings.TEMPLATE_CONTEXT_PROCESSORS = [test_processor_name]
  27. settings.TEMPLATE_DIRS = (
  28. os.path.join(
  29. os.path.dirname(__file__),
  30. 'templates'
  31. ),
  32. )
  33. # Force re-evaluation of the contex processor list
  34. django.template.context._standard_context_processors = None
  35. def tearDown(self):
  36. settings.TEMPLATE_DIRS = self._old_TEMPLATE_DIRS
  37. settings.TEMPLATE_CONTEXT_PROCESSORS = self._old_processors
  38. # Force re-evaluation of the contex processor list
  39. django.template.context._standard_context_processors = None
  40. class SimpleTemplateResponseTest(BaseTemplateResponseTest):
  41. def _response(self, template='foo', *args, **kwargs):
  42. return SimpleTemplateResponse(Template(template), *args, **kwargs)
  43. def test_template_resolving(self):
  44. response = SimpleTemplateResponse('first/test.html')
  45. response.render()
  46. self.assertEqual('First template\n', response.content)
  47. templates = ['foo.html', 'second/test.html', 'first/test.html']
  48. response = SimpleTemplateResponse(templates)
  49. response.render()
  50. self.assertEqual('Second template\n', response.content)
  51. response = self._response()
  52. response.render()
  53. self.assertEqual(response.content, 'foo')
  54. def test_explicit_baking(self):
  55. # explicit baking
  56. response = self._response()
  57. self.assertFalse(response.is_rendered)
  58. response.render()
  59. self.assertTrue(response.is_rendered)
  60. def test_render(self):
  61. # response is not re-rendered without the render call
  62. response = self._response().render()
  63. self.assertEqual(response.content, 'foo')
  64. # rebaking doesn't change the rendered content
  65. response.template_name = Template('bar{{ baz }}')
  66. response.render()
  67. self.assertEqual(response.content, 'foo')
  68. # but rendered content can be overridden by manually
  69. # setting content
  70. response.content = 'bar'
  71. self.assertEqual(response.content, 'bar')
  72. def test_iteration_unrendered(self):
  73. # unrendered response raises an exception on iteration
  74. response = self._response()
  75. self.assertFalse(response.is_rendered)
  76. def iteration():
  77. for x in response:
  78. pass
  79. self.assertRaises(ContentNotRenderedError, iteration)
  80. self.assertFalse(response.is_rendered)
  81. def test_iteration_rendered(self):
  82. # iteration works for rendered responses
  83. response = self._response().render()
  84. res = [x for x in response]
  85. self.assertEqual(res, ['foo'])
  86. def test_content_access_unrendered(self):
  87. # unrendered response raises an exception when content is accessed
  88. response = self._response()
  89. self.assertFalse(response.is_rendered)
  90. self.assertRaises(ContentNotRenderedError, lambda: response.content)
  91. self.assertFalse(response.is_rendered)
  92. def test_content_access_rendered(self):
  93. # rendered response content can be accessed
  94. response = self._response().render()
  95. self.assertEqual(response.content, 'foo')
  96. def test_set_content(self):
  97. # content can be overriden
  98. response = self._response()
  99. self.assertFalse(response.is_rendered)
  100. response.content = 'spam'
  101. self.assertTrue(response.is_rendered)
  102. self.assertEqual(response.content, 'spam')
  103. response.content = 'baz'
  104. self.assertEqual(response.content, 'baz')
  105. def test_dict_context(self):
  106. response = self._response('{{ foo }}{{ processors }}',
  107. {'foo': 'bar'})
  108. self.assertEqual(response.context_data, {'foo': 'bar'})
  109. response.render()
  110. self.assertEqual(response.content, 'bar')
  111. def test_context_instance(self):
  112. response = self._response('{{ foo }}{{ processors }}',
  113. Context({'foo': 'bar'}))
  114. self.assertEqual(response.context_data.__class__, Context)
  115. response.render()
  116. self.assertEqual(response.content, 'bar')
  117. def test_kwargs(self):
  118. response = self._response(content_type = 'application/json', status=504)
  119. self.assertEqual(response['content-type'], 'application/json')
  120. self.assertEqual(response.status_code, 504)
  121. def test_args(self):
  122. response = SimpleTemplateResponse('', {}, 'application/json', 504)
  123. self.assertEqual(response['content-type'], 'application/json')
  124. self.assertEqual(response.status_code, 504)
  125. def test_post_callbacks(self):
  126. "Rendering a template response triggers the post-render callbacks"
  127. post = []
  128. def post1(obj):
  129. post.append('post1')
  130. def post2(obj):
  131. post.append('post2')
  132. response = SimpleTemplateResponse('first/test.html', {})
  133. response.add_post_render_callback(post1)
  134. response.add_post_render_callback(post2)
  135. # When the content is rendered, all the callbacks are invoked, too.
  136. response.render()
  137. self.assertEqual('First template\n', response.content)
  138. self.assertEqual(post, ['post1','post2'])
  139. def test_pickling(self):
  140. # Create a template response. The context is
  141. # known to be unpickleable (e.g., a function).
  142. response = SimpleTemplateResponse('first/test.html', {
  143. 'value': 123,
  144. 'fn': datetime.now,
  145. })
  146. self.assertRaises(ContentNotRenderedError,
  147. pickle.dumps, response)
  148. # But if we render the response, we can pickle it.
  149. response.render()
  150. pickled_response = pickle.dumps(response)
  151. unpickled_response = pickle.loads(pickled_response)
  152. self.assertEqual(unpickled_response.content, response.content)
  153. self.assertEqual(unpickled_response['content-type'], response['content-type'])
  154. self.assertEqual(unpickled_response.status_code, response.status_code)
  155. # ...and the unpickled reponse doesn't have the
  156. # template-related attributes, so it can't be re-rendered
  157. self.assertFalse(hasattr(unpickled_response, 'template_name'))
  158. self.assertFalse(hasattr(unpickled_response, 'context_data'))
  159. self.assertFalse(hasattr(unpickled_response, '_post_render_callbacks'))
  160. class TemplateResponseTest(BaseTemplateResponseTest):
  161. def _response(self, template='foo', *args, **kwargs):
  162. return TemplateResponse(self.factory.get('/'), Template(template),
  163. *args, **kwargs)
  164. def test_render(self):
  165. response = self._response('{{ foo }}{{ processors }}').render()
  166. self.assertEqual(response.content, 'yes')
  167. def test_render_with_requestcontext(self):
  168. response = self._response('{{ foo }}{{ processors }}',
  169. {'foo': 'bar'}).render()
  170. self.assertEqual(response.content, 'baryes')
  171. def test_render_with_context(self):
  172. response = self._response('{{ foo }}{{ processors }}',
  173. Context({'foo': 'bar'})).render()
  174. self.assertEqual(response.content, 'bar')
  175. def test_kwargs(self):
  176. response = self._response(content_type = 'application/json',
  177. status=504)
  178. self.assertEqual(response['content-type'], 'application/json')
  179. self.assertEqual(response.status_code, 504)
  180. def test_args(self):
  181. response = TemplateResponse(self.factory.get('/'), '', {},
  182. 'application/json', 504)
  183. self.assertEqual(response['content-type'], 'application/json')
  184. self.assertEqual(response.status_code, 504)
  185. def test_custom_app(self):
  186. response = self._response('{{ foo }}', current_app="foobar")
  187. rc = response.resolve_context(response.context_data)
  188. self.assertEqual(rc.current_app, 'foobar')
  189. def test_pickling(self):
  190. # Create a template response. The context is
  191. # known to be unpickleable (e.g., a function).
  192. response = TemplateResponse(self.factory.get('/'),
  193. 'first/test.html', {
  194. 'value': 123,
  195. 'fn': datetime.now,
  196. })
  197. self.assertRaises(ContentNotRenderedError,
  198. pickle.dumps, response)
  199. # But if we render the response, we can pickle it.
  200. response.render()
  201. pickled_response = pickle.dumps(response)
  202. unpickled_response = pickle.loads(pickled_response)
  203. self.assertEqual(unpickled_response.content, response.content)
  204. self.assertEqual(unpickled_response['content-type'], response['content-type'])
  205. self.assertEqual(unpickled_response.status_code, response.status_code)
  206. # ...and the unpickled reponse doesn't have the
  207. # template-related attributes, so it can't be re-rendered
  208. self.assertFalse(hasattr(unpickled_response, '_request'))
  209. self.assertFalse(hasattr(unpickled_response, 'template_name'))
  210. self.assertFalse(hasattr(unpickled_response, 'context_data'))
  211. self.assertFalse(hasattr(unpickled_response, '_post_render_callbacks'))
  212. class CustomURLConfTest(TestCase):
  213. urls = 'regressiontests.templates.urls'
  214. def setUp(self):
  215. self.old_MIDDLEWARE_CLASSES = settings.MIDDLEWARE_CLASSES
  216. settings.MIDDLEWARE_CLASSES = list(settings.MIDDLEWARE_CLASSES) + [
  217. 'regressiontests.templates.response.CustomURLConfMiddleware'
  218. ]
  219. def tearDown(self):
  220. settings.MIDDLEWARE_CLASSES = self.old_MIDDLEWARE_CLASSES
  221. def test_custom_urlconf(self):
  222. response = self.client.get('/template_response_view/')
  223. self.assertEqual(response.status_code, 200)
  224. self.assertContains(response, 'This is where you can find the snark: /snark/')
  225. class CacheMiddlewareTest(TestCase):
  226. urls = 'regressiontests.templates.alternate_urls'
  227. def setUp(self):
  228. self.old_MIDDLEWARE_CLASSES = settings.MIDDLEWARE_CLASSES
  229. self.CACHE_MIDDLEWARE_SECONDS = settings.CACHE_MIDDLEWARE_SECONDS
  230. settings.CACHE_MIDDLEWARE_SECONDS = 2.0
  231. settings.MIDDLEWARE_CLASSES = list(settings.MIDDLEWARE_CLASSES) + [
  232. 'django.middleware.cache.FetchFromCacheMiddleware',
  233. 'django.middleware.cache.UpdateCacheMiddleware',
  234. ]
  235. def tearDown(self):
  236. settings.MIDDLEWARE_CLASSES = self.old_MIDDLEWARE_CLASSES
  237. settings.CACHE_MIDDLEWARE_SECONDS = self.CACHE_MIDDLEWARE_SECONDS
  238. def test_middleware_caching(self):
  239. response = self.client.get('/template_response_view/')
  240. self.assertEqual(response.status_code, 200)
  241. time.sleep(1.0)
  242. response2 = self.client.get('/template_response_view/')
  243. self.assertEqual(response2.status_code, 200)
  244. self.assertEqual(response.content, response2.content)
  245. time.sleep(2.0)
  246. # Let the cache expire and test again
  247. response2 = self.client.get('/template_response_view/')
  248. self.assertEqual(response2.status_code, 200)
  249. self.assertNotEqual(response.content, response2.content)