Commit 4525a0c4 authored by Andy McKay's avatar Andy McKay Committed by Tim Graham
Browse files

Fixed #24773 -- Added a json() method on test client responses.

parent 46ce72e8
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
from __future__ import unicode_literals

import json
import mimetypes
import os
import re
@@ -473,6 +474,8 @@ class Client(RequestFactory):
            response.templates = data.get("templates", [])
            response.context = data.get("context")

            response.json = curry(self._parse_json, response)

            # Attach the ResolverMatch instance to the response
            response.resolver_match = SimpleLazyObject(
                lambda: urlresolvers.resolve(request['PATH_INFO']))
@@ -641,6 +644,11 @@ class Client(RequestFactory):
        logout(request)
        self.cookies = SimpleCookie()

    def _parse_json(self, response, **extra):
        if 'application/json' not in response.get('Content-Type'):
            raise ValueError('Content-Type header is "{0}", not "application/json"'.format(response.get('Content-Type')))
        return json.loads(response.content.decode(), **extra)

    def _handle_redirects(self, response, **extra):
        "Follows any redirects by requesting responses from the server using GET."

+2 −1
Original line number Diff line number Diff line
@@ -289,7 +289,8 @@ Requests and Responses
Tests
^^^^^

* ...
* Added the :meth:`json() <django.test.Response.json>` method to test client
  responses to give access to the response body as JSON.

URLs
^^^^
+14 −0
Original line number Diff line number Diff line
@@ -425,6 +425,20 @@ Specifically, a ``Response`` object has the following attributes:
            >>> response.context['name']
            'Arthur'

    .. method:: json(**kwargs)

        .. versionadded:: 1.9

        The body of the response, parsed as JSON. Extra keyword arguments are
        passed to :func:`json.loads`. For example::

            >>> response = client.get('/foo/')
            >>> response.json()['name']
            'Arthur'

        If the ``Content-Type`` header is not ``"application/json"``, then a
        :exc:`ValueError` will be raised when trying to parse the response.

    .. attribute:: request

        The request data that stimulated the response.
+10 −0
Original line number Diff line number Diff line
@@ -1270,6 +1270,16 @@ class RequestMethodStringDataTests(SimpleTestCase):
        response = self.client.head('/body/', data='', content_type='application/json')
        self.assertEqual(response.content, b'')

    def test_json(self):
        response = self.client.get('/json_response/')
        self.assertEqual(response.json(), {'key': 'value'})

    def test_json_wrong_header(self):
        response = self.client.get('/body/')
        msg = 'Content-Type header is "text/html; charset=utf-8", not "application/json"'
        with self.assertRaisesMessage(ValueError, msg):
            self.assertEqual(response.json(), {'key': 'value'})


@override_settings(ROOT_URLCONF='test_client_regress.urls',)
class QueryStringTests(SimpleTestCase):
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ urlpatterns = [
    url(r'^request_methods/$', views.request_methods_view),
    url(r'^check_unicode/$', views.return_unicode),
    url(r'^check_binary/$', views.return_undecodable_binary),
    url(r'^json_response/$', views.return_json_response),
    url(r'^parse_unicode_json/$', views.return_json_file),
    url(r'^check_headers/$', views.check_headers),
    url(r'^check_headers_redirect/$', RedirectView.as_view(url='/check_headers/')),
Loading