Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #10482 -- Unified access to response.context when inspecting re…

…sponses from the test client. Thanks to James Bennett for the design, and Julien Phalip for the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@10084 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit ee2f04d79e5bca55637b9bb3301618738a4e342a 1 parent 61a2708
Russell Keith-Magee authored March 18, 2009
5  django/test/client.py
@@ -20,6 +20,7 @@
20 20
 from django.utils.http import urlencode
21 21
 from django.utils.itercompat import is_iterable
22 22
 from django.db import transaction, close_connection
  23
+from django.test.utils import ContextList
23 24
 
24 25
 BOUNDARY = 'BoUnDaRyStRiNg'
25 26
 MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY
@@ -80,8 +81,8 @@ def store_rendered_templates(store, signal, sender, template, context, **kwargs)
80 81
     """
81 82
     Stores templates and contexts that are rendered.
82 83
     """
83  
-    store.setdefault('template',[]).append(template)
84  
-    store.setdefault('context',[]).append(context)
  84
+    store.setdefault('template', []).append(template)
  85
+    store.setdefault('context', ContextList()).append(context)
85 86
 
86 87
 def encode_multipart(boundary, data):
87 88
     """
14  django/test/utils.py
@@ -6,6 +6,20 @@
6 6
 from django.template import Template
7 7
 from django.utils.translation import deactivate
8 8
 
  9
+class ContextList(list):
  10
+    """A wrapper that provides direct key access to context items contained
  11
+    in a list of context objects.
  12
+    """
  13
+    def __getitem__(self, key):
  14
+        if isinstance(key, basestring):
  15
+            for subcontext in self:
  16
+                if key in subcontext:
  17
+                    return subcontext[key]
  18
+            raise KeyError
  19
+        else:
  20
+            return super(ContextList, self).__getitem__(key)
  21
+
  22
+
9 23
 def instrumented_test_render(self, context):
10 24
     """
11 25
     An instrumented Template render method, providing a signal
10  docs/topics/testing.txt
@@ -712,6 +712,16 @@ Specifically, a ``Response`` object has the following attributes:
712 712
         If the rendered page used multiple templates, then ``context`` will be a
713 713
         list of ``Context`` objects, in the order in which they were rendered.
714 714
 
  715
+        .. versionadded:: 1.1
  716
+
  717
+        Regardless of the number of templates used during rendering, you can
  718
+        retrieve context values using the ``[]`` operator. For example, the
  719
+        context variable ``name`` could be retrieved using::
  720
+
  721
+            >>> response = client.get('/foo/')
  722
+            >>> response.context['name']
  723
+            'Arthur'
  724
+
715 725
     .. attribute:: request
716 726
 
717 727
         The request data that stimulated the response.
23  tests/regressiontests/test_client_regress/models.py
@@ -5,9 +5,10 @@
5 5
 from django.conf import settings
6 6
 
7 7
 from django.test import Client, TestCase
  8
+from django.test.utils import ContextList
8 9
 from django.core.urlresolvers import reverse
9 10
 from django.core.exceptions import SuspiciousOperation
10  
-from django.template import TemplateDoesNotExist, TemplateSyntaxError
  11
+from django.template import TemplateDoesNotExist, TemplateSyntaxError, Context
11 12
 
12 13
 class AssertContainsTests(TestCase):
13 14
     def test_contains(self):
@@ -455,6 +456,26 @@ def test_urlconf_was_reverted(self):
455 456
         url = reverse('arg_view', args=['somename'])
456 457
         self.assertEquals(url, '/test_client_regress/arg_view/somename/')
457 458
 
  459
+class ContextTests(TestCase):
  460
+    fixtures = ['testdata']
  461
+
  462
+    def test_single_context(self):
  463
+        "Context variables can be retrieved from a single context"
  464
+        response = self.client.get("/test_client_regress/request_data/", data={'foo':'whiz'})
  465
+        self.assertEqual(response.context.__class__, Context)
  466
+        self.assertEqual(response.context['get-foo'], 'whiz')
  467
+        self.assertEqual(response.context['request-foo'], 'whiz')
  468
+        self.assertEqual(response.context['data'], 'sausage')
  469
+
  470
+    def test_inherited_context(self):
  471
+        "Context variables can be retrieved from a list of contexts"
  472
+        response = self.client.get("/test_client_regress/request_data_extended/", data={'foo':'whiz'})
  473
+        self.assertEqual(response.context.__class__, ContextList)
  474
+        self.assertEqual(len(response.context), 2)
  475
+        self.assertEqual(response.context['get-foo'], 'whiz')
  476
+        self.assertEqual(response.context['request-foo'], 'whiz')
  477
+        self.assertEqual(response.context['data'], 'bacon')
  478
+
458 479
 class SessionTests(TestCase):
459 480
     fixtures = ['testdata.json']
460 481
 
1  tests/regressiontests/test_client_regress/urls.py
@@ -7,6 +7,7 @@
7 7
     (r'^staff_only/$', views.staff_only_view),
8 8
     (r'^get_view/$', views.get_view),
9 9
     (r'^request_data/$', views.request_data),
  10
+    (r'^request_data_extended/$', views.request_data, {'template':'extended.html', 'data':'bacon'}),
10 11
     url(r'^arg_view/(?P<name>.+)/$', views.view_with_argument, name='arg_view'),
11 12
     (r'^login_protected_redirect_view/$', views.login_protected_redirect_view),
12 13
     (r'^redirects/$', redirect_to, {'url': '/test_client_regress/redirects/further/'}),
5  tests/regressiontests/test_client_regress/views.py
@@ -19,15 +19,16 @@ def get_view(request):
19 19
     return HttpResponse("Hello world")
20 20
 get_view = login_required(get_view)
21 21
 
22  
-def request_data(request):
  22
+def request_data(request, template='base.html', data='sausage'):
23 23
     "A simple view that returns the request data in the context"
24  
-    return render_to_response('base.html', {
  24
+    return render_to_response(template, {
25 25
         'get-foo':request.GET.get('foo',None),
26 26
         'get-bar':request.GET.get('bar',None),
27 27
         'post-foo':request.POST.get('foo',None),
28 28
         'post-bar':request.POST.get('bar',None),
29 29
         'request-foo':request.REQUEST.get('foo',None),
30 30
         'request-bar':request.REQUEST.get('bar',None),
  31
+        'data': data,
31 32
     })
32 33
 
33 34
 def view_with_argument(request, name):
5  tests/templates/extended.html
... ...
@@ -0,0 +1,5 @@
  1
+{% extends "base.html" %}
  2
+{% block title %}Extended template{% endblock %}
  3
+{% block content %}
  4
+This is just a template extending the base.
  5
+{% endblock %}

0 notes on commit ee2f04d

Please sign in to comment.
Something went wrong with that request. Please try again.