Django

Code

Changeset 9398

Show
Ignore:
Timestamp:
11/12/08 05:22:05 (2 months ago)
Author:
russellm
Message:

Fixed #9351 -- Modified the test client to pass on URL encoded parameters to the underlying views. Thanks to sime for the suggestion.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/test/client.py

    r9397 r9398  
    11import urllib 
     2from urlparse import urlparse, urlunparse 
    23import sys 
    34import os 
     
    261262        Requests a response from the server using GET. 
    262263        """ 
     264        parsed = urlparse(path) 
    263265        r = { 
    264266            'CONTENT_TYPE':    'text/html; charset=utf-8', 
    265             'PATH_INFO':       urllib.unquote(path), 
    266             'QUERY_STRING':    urlencode(data, doseq=True)
     267            'PATH_INFO':       urllib.unquote(parsed.path), 
     268            'QUERY_STRING':    urlencode(data, doseq=True) or parsed.query
    267269            'REQUEST_METHOD': 'GET', 
    268270            'wsgi.input':      FakePayload('') 
     
    281283            post_data = data 
    282284 
     285        parsed = urlparse(path) 
    283286        r = { 
    284287            'CONTENT_LENGTH': len(post_data), 
    285288            'CONTENT_TYPE':   content_type, 
    286             'PATH_INFO':      urllib.unquote(path), 
     289            'PATH_INFO':      urllib.unquote(parsed.path), 
     290            'QUERY_STRING':   parsed.query, 
    287291            'REQUEST_METHOD': 'POST', 
    288292            'wsgi.input':     FakePayload(post_data), 
     
    296300        Request a response from the server using HEAD. 
    297301        """ 
     302        parsed = urlparse(path) 
    298303        r = { 
    299304            'CONTENT_TYPE':    'text/html; charset=utf-8', 
    300             'PATH_INFO':       urllib.unquote(path), 
    301             'QUERY_STRING':    urlencode(data, doseq=True)
     305            'PATH_INFO':       urllib.unquote(parsed.path), 
     306            'QUERY_STRING':    urlencode(data, doseq=True) or parsed.query
    302307            'REQUEST_METHOD': 'HEAD', 
    303308            'wsgi.input':      FakePayload('') 
     
    311316        Request a response from the server using OPTIONS. 
    312317        """ 
    313         r = { 
    314             'PATH_INFO':       urllib.unquote(path), 
    315             'QUERY_STRING':    urlencode(data, doseq=True), 
     318        parsed = urlparse(path) 
     319        r = { 
     320            'PATH_INFO':       urllib.unquote(parsed.path), 
     321            'QUERY_STRING':    urlencode(data, doseq=True) or parsed.query, 
    316322            'REQUEST_METHOD': 'OPTIONS', 
    317323            'wsgi.input':      FakePayload('') 
     
    329335        else: 
    330336            post_data = data 
     337 
     338        parsed = urlparse(path) 
    331339        r = { 
    332340            'CONTENT_LENGTH': len(post_data), 
    333341            'CONTENT_TYPE':   content_type, 
    334             'PATH_INFO':      urllib.unquote(path), 
    335             'QUERY_STRING':   urlencode(data, doseq=True)
     342            'PATH_INFO':      urllib.unquote(parsed.path), 
     343            'QUERY_STRING':   urlencode(data, doseq=True) or parsed.query
    336344            'REQUEST_METHOD': 'PUT', 
    337345            'wsgi.input':     FakePayload(post_data), 
     
    345353        Send a DELETE request to the server. 
    346354        """ 
    347         r = { 
    348             'PATH_INFO':       urllib.unquote(path), 
    349             'QUERY_STRING':    urlencode(data, doseq=True), 
     355        parsed = urlparse(path) 
     356        r = { 
     357            'PATH_INFO':       urllib.unquote(parsed.path), 
     358            'QUERY_STRING':    urlencode(data, doseq=True) or parsed.query, 
    350359            'REQUEST_METHOD': 'DELETE', 
    351360            'wsgi.input':      FakePayload('') 
  • django/trunk/docs/topics/testing.txt

    r9332 r9398  
    494494            /customers/details/?name=fred&age=7 
    495495 
     496        .. versionadded:: development 
     497 
     498        If you already have the GET arguments in URL-encoded form, you can 
     499        use that encoding instead of using the data argument. For example, 
     500        the previous GET request could also be posed as:: 
     501 
     502        >>> c = Client() 
     503        >>> c.get('/customers/details/?name=fred&age=7') 
     504 
     505        If you provide URL both an encoded GET data and a data argument, 
     506        the data argument will take precedence. 
     507 
    496508    .. method:: Client.post(path, data={}, content_type=MULTIPART_CONTENT) 
    497509 
     
    544556        Note that you should manually close the file after it has been provided 
    545557        to ``post()``. 
     558 
     559        .. versionadded:: development 
     560 
     561        If the URL you request with a POST contains encoded parameters, these 
     562        parameters will be made available in the request.GET data. For example, 
     563        if you were to make the request:: 
     564 
     565        >>> c.post('/login/?vistor=true', {'name': 'fred', 'passwd': 'secret'}) 
     566 
     567        ... the view handling this request could interrogate request.POST 
     568        to retrieve the username and password, and could interrogate request.GET 
     569        to determine if the user was a visitor. 
    546570 
    547571    .. method:: Client.head(path, data={}) 
  • django/trunk/tests/regressiontests/test_client_regress/models.py

    r9188 r9398  
    310310        except SuspiciousOperation: 
    311311            self.fail("Staff should be able to visit this page") 
    312      
     312 
    313313class TemplateExceptionTests(TestCase): 
    314314    def setUp(self): 
    315315        self.old_templates = settings.TEMPLATE_DIRS 
    316316        settings.TEMPLATE_DIRS = () 
    317          
     317 
    318318    def tearDown(self): 
    319319        settings.TEMPLATE_DIRS = self.old_templates 
    320          
     320 
    321321    def test_no_404_template(self): 
    322         "Missing templates are correctly reported by test client"     
     322        "Missing templates are correctly reported by test client" 
    323323        try: 
    324324            response = self.client.get("/no_such_view/") 
     
    335335        except TemplateSyntaxError: 
    336336            pass 
    337          
     337 
    338338# We need two different tests to check URLconf substitution -  one to check 
    339339# it was changed, and another one (without self.urls) to check it was reverted on 
     
    422422        self.assertEqual(response.status_code, 200) 
    423423        self.assertEqual(response.content, 'request method: DELETE') 
     424 
     425class QueryStringTests(TestCase): 
     426    def test_get_like_requests(self): 
     427        for method_name in ('get','head','options','put','delete'): 
     428            # A GET-like request can pass a query string as data 
     429            method = getattr(self.client, method_name) 
     430            response = method("/test_client_regress/request_data/", data={'foo':'whiz'}) 
     431            self.assertEqual(response.context['get-foo'], 'whiz') 
     432            self.assertEqual(response.context['request-foo'], 'whiz') 
     433 
     434            # A GET-like request can pass a query string as part of the URL 
     435            response = method("/test_client_regress/request_data/?foo=whiz") 
     436            self.assertEqual(response.context['get-foo'], 'whiz') 
     437            self.assertEqual(response.context['request-foo'], 'whiz') 
     438 
     439            # Data provided in the URL to a GET-like request is overridden by actual form data 
     440            response = method("/test_client_regress/request_data/?foo=whiz", data={'foo':'bang'}) 
     441            self.assertEqual(response.context['get-foo'], 'bang') 
     442            self.assertEqual(response.context['request-foo'], 'bang') 
     443 
     444            response = method("/test_client_regress/request_data/?foo=whiz", data={'bar':'bang'}) 
     445            self.assertEqual(response.context['get-foo'], None) 
     446            self.assertEqual(response.context['get-bar'], 'bang') 
     447            self.assertEqual(response.context['request-foo'], None) 
     448            self.assertEqual(response.context['request-bar'], 'bang') 
     449 
     450    def test_post_like_requests(self): 
     451        # A POST-like request can pass a query string as data 
     452        response = self.client.post("/test_client_regress/request_data/", data={'foo':'whiz'}) 
     453        self.assertEqual(response.context['get-foo'], None) 
     454        self.assertEqual(response.context['post-foo'], 'whiz') 
     455 
     456        # A POST-like request can pass a query string as part of the URL 
     457        response = self.client.post("/test_client_regress/request_data/?foo=whiz") 
     458        self.assertEqual(response.context['get-foo'], 'whiz') 
     459        self.assertEqual(response.context['post-foo'], None) 
     460        self.assertEqual(response.context['request-foo'], 'whiz') 
     461 
     462        # POST data provided in the URL augments actual form data 
     463        response = self.client.post("/test_client_regress/request_data/?foo=whiz", data={'foo':'bang'}) 
     464        self.assertEqual(response.context['get-foo'], 'whiz') 
     465        self.assertEqual(response.context['post-foo'], 'bang') 
     466        self.assertEqual(response.context['request-foo'], 'bang') 
     467 
     468        response = self.client.post("/test_client_regress/request_data/?foo=whiz", data={'bar':'bang'}) 
     469        self.assertEqual(response.context['get-foo'], 'whiz') 
     470        self.assertEqual(response.context['get-bar'], None) 
     471        self.assertEqual(response.context['post-foo'], None) 
     472        self.assertEqual(response.context['post-bar'], 'bang') 
     473        self.assertEqual(response.context['request-foo'], 'whiz') 
     474        self.assertEqual(response.context['request-bar'], 'bang') 
  • django/trunk/tests/regressiontests/test_client_regress/urls.py

    r9188 r9398  
    66    (r'^staff_only/$', views.staff_only_view), 
    77    (r'^get_view/$', views.get_view), 
     8    (r'^request_data/$', views.request_data), 
    89    url(r'^arg_view/(?P<name>.+)/$', views.view_with_argument, name='arg_view'), 
    910    (r'^login_protected_redirect_view/$', views.login_protected_redirect_view), 
  • django/trunk/tests/regressiontests/test_client_regress/views.py

    r9188 r9398  
    22from django.http import HttpResponse, HttpResponseRedirect 
    33from django.core.exceptions import SuspiciousOperation 
     4from django.shortcuts import render_to_response 
    45 
    56def no_template_view(request): 
     
    1819    return HttpResponse("Hello world") 
    1920get_view = login_required(get_view) 
     21 
     22def request_data(request): 
     23    "A simple view that returns the request data in the context" 
     24    return render_to_response('base.html', { 
     25        'get-foo':request.GET.get('foo',None), 
     26        'get-bar':request.GET.get('bar',None), 
     27        'post-foo':request.POST.get('foo',None), 
     28        'post-bar':request.POST.get('bar',None), 
     29        'request-foo':request.REQUEST.get('foo',None), 
     30        'request-bar':request.REQUEST.get('bar',None), 
     31    }) 
    2032 
    2133def view_with_argument(request, name):