PageRenderTime 68ms CodeModel.GetById 36ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/regressiontests/templates/response.py

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