aboutsummaryrefslogtreecommitdiffstats
path: root/djangorestframework/tests
diff options
context:
space:
mode:
authorSébastien Piquemal2012-02-02 18:19:44 +0200
committerSébastien Piquemal2012-02-02 18:19:44 +0200
commit5bb6301b7f53e3815ab1a81a5fa38721dc95b113 (patch)
tree27d53698a374ac62c4a3be41b23173775c92f207 /djangorestframework/tests
parent5f59d90645dfddc293bbbbc4ca9b4c3f3125b590 (diff)
downloaddjango-rest-framework-5bb6301b7f53e3815ab1a81a5fa38721dc95b113.tar.bz2
Response as a subclass of HttpResponse - first draft, not quite there yet.
Diffstat (limited to 'djangorestframework/tests')
-rw-r--r--djangorestframework/tests/accept.py13
-rw-r--r--djangorestframework/tests/authentication.py5
-rw-r--r--djangorestframework/tests/files.py9
-rw-r--r--djangorestframework/tests/mixins.py47
-rw-r--r--djangorestframework/tests/renderers.py193
-rw-r--r--djangorestframework/tests/request.py6
-rw-r--r--djangorestframework/tests/response.py281
-rw-r--r--djangorestframework/tests/reverse.py3
-rw-r--r--djangorestframework/tests/throttling.py3
-rw-r--r--djangorestframework/tests/validators.py20
10 files changed, 335 insertions, 245 deletions
diff --git a/djangorestframework/tests/accept.py b/djangorestframework/tests/accept.py
index d66f6fb0..2a02e04d 100644
--- a/djangorestframework/tests/accept.py
+++ b/djangorestframework/tests/accept.py
@@ -1,6 +1,8 @@
from django.test import TestCase
+
from djangorestframework.compat import RequestFactory
from djangorestframework.views import View
+from djangorestframework.response import Response
# See: http://www.useragentstring.com/
@@ -23,7 +25,7 @@ class UserAgentMungingTest(TestCase):
permissions = ()
def get(self, request):
- return {'a':1, 'b':2, 'c':3}
+ return Response({'a':1, 'b':2, 'c':3})
self.req = RequestFactory()
self.MockView = MockView
@@ -37,18 +39,22 @@ class UserAgentMungingTest(TestCase):
MSIE_7_USER_AGENT):
req = self.req.get('/', HTTP_ACCEPT='*/*', HTTP_USER_AGENT=user_agent)
resp = self.view(req)
+ resp.render()
self.assertEqual(resp['Content-Type'], 'text/html')
-
+
def test_dont_rewrite_msie_accept_header(self):
"""Turn off _IGNORE_IE_ACCEPT_HEADER, send MSIE user agent strings and ensure
that we get a JSON response if we set a */* accept header."""
- view = self.MockView.as_view(_IGNORE_IE_ACCEPT_HEADER=False)
+ class IgnoreIEAcceptResponse(Response):
+ _IGNORE_IE_ACCEPT_HEADER=False
+ view = self.MockView.as_view(response_class=IgnoreIEAcceptResponse)
for user_agent in (MSIE_9_USER_AGENT,
MSIE_8_USER_AGENT,
MSIE_7_USER_AGENT):
req = self.req.get('/', HTTP_ACCEPT='*/*', HTTP_USER_AGENT=user_agent)
resp = view(req)
+ resp.render()
self.assertEqual(resp['Content-Type'], 'application/json')
def test_dont_munge_nice_browsers_accept_header(self):
@@ -61,5 +67,6 @@ class UserAgentMungingTest(TestCase):
OPERA_11_0_OPERA_USER_AGENT):
req = self.req.get('/', HTTP_ACCEPT='*/*', HTTP_USER_AGENT=user_agent)
resp = self.view(req)
+ resp.render()
self.assertEqual(resp['Content-Type'], 'application/json')
diff --git a/djangorestframework/tests/authentication.py b/djangorestframework/tests/authentication.py
index 303bf96b..25410b04 100644
--- a/djangorestframework/tests/authentication.py
+++ b/djangorestframework/tests/authentication.py
@@ -3,6 +3,7 @@ from django.contrib.auth.models import User
from django.test import Client, TestCase
from django.utils import simplejson as json
+from django.http import HttpResponse
from djangorestframework.views import View
from djangorestframework import permissions
@@ -14,10 +15,10 @@ class MockView(View):
permissions = (permissions.IsAuthenticated,)
def post(self, request):
- return {'a': 1, 'b': 2, 'c': 3}
+ return HttpResponse({'a': 1, 'b': 2, 'c': 3})
def put(self, request):
- return {'a': 1, 'b': 2, 'c': 3}
+ return HttpResponse({'a': 1, 'b': 2, 'c': 3})
urlpatterns = patterns('',
(r'^$', MockView.as_view()),
diff --git a/djangorestframework/tests/files.py b/djangorestframework/tests/files.py
index d3b1cc56..bbdff70b 100644
--- a/djangorestframework/tests/files.py
+++ b/djangorestframework/tests/files.py
@@ -1,8 +1,11 @@
from django.test import TestCase
from django import forms
+
from djangorestframework.compat import RequestFactory
from djangorestframework.views import View
from djangorestframework.resources import FormResource
+from djangorestframework.response import Response
+
import StringIO
class UploadFilesTests(TestCase):
@@ -20,13 +23,13 @@ class UploadFilesTests(TestCase):
form = FileForm
def post(self, request, *args, **kwargs):
- return {'FILE_NAME': self.CONTENT['file'].name,
- 'FILE_CONTENT': self.CONTENT['file'].read()}
+ return Response({'FILE_NAME': self.CONTENT['file'].name,
+ 'FILE_CONTENT': self.CONTENT['file'].read()})
file = StringIO.StringIO('stuff')
file.name = 'stuff.txt'
request = self.factory.post('/', {'file': file})
view = MockView.as_view()
response = view(request)
- self.assertEquals(response.content, '{"FILE_CONTENT": "stuff", "FILE_NAME": "stuff.txt"}')
+ self.assertEquals(response.raw_content, {"FILE_CONTENT": "stuff", "FILE_NAME": "stuff.txt"})
diff --git a/djangorestframework/tests/mixins.py b/djangorestframework/tests/mixins.py
index a7512efc..7a1d2769 100644
--- a/djangorestframework/tests/mixins.py
+++ b/djangorestframework/tests/mixins.py
@@ -65,7 +65,7 @@ class TestModelCreation(TestModelsTestCase):
response = mixin.post(request)
self.assertEquals(1, Group.objects.count())
- self.assertEquals('foo', response.cleaned_content.name)
+ self.assertEquals('foo', response.raw_content.name)
def test_creation_with_m2m_relation(self):
class UserResource(ModelResource):
@@ -91,8 +91,8 @@ class TestModelCreation(TestModelsTestCase):
response = mixin.post(request)
self.assertEquals(1, User.objects.count())
- self.assertEquals(1, response.cleaned_content.groups.count())
- self.assertEquals('foo', response.cleaned_content.groups.all()[0].name)
+ self.assertEquals(1, response.raw_content.groups.count())
+ self.assertEquals('foo', response.raw_content.groups.all()[0].name)
def test_creation_with_m2m_relation_through(self):
"""
@@ -114,7 +114,7 @@ class TestModelCreation(TestModelsTestCase):
response = mixin.post(request)
self.assertEquals(1, CustomUser.objects.count())
- self.assertEquals(0, response.cleaned_content.groups.count())
+ self.assertEquals(0, response.raw_content.groups.count())
group = Group(name='foo1')
group.save()
@@ -129,8 +129,8 @@ class TestModelCreation(TestModelsTestCase):
response = mixin.post(request)
self.assertEquals(2, CustomUser.objects.count())
- self.assertEquals(1, response.cleaned_content.groups.count())
- self.assertEquals('foo1', response.cleaned_content.groups.all()[0].name)
+ self.assertEquals(1, response.raw_content.groups.count())
+ self.assertEquals('foo1', response.raw_content.groups.all()[0].name)
group2 = Group(name='foo2')
group2.save()
@@ -145,19 +145,19 @@ class TestModelCreation(TestModelsTestCase):
response = mixin.post(request)
self.assertEquals(3, CustomUser.objects.count())
- self.assertEquals(2, response.cleaned_content.groups.count())
- self.assertEquals('foo1', response.cleaned_content.groups.all()[0].name)
- self.assertEquals('foo2', response.cleaned_content.groups.all()[1].name)
+ self.assertEquals(2, response.raw_content.groups.count())
+ self.assertEquals('foo1', response.raw_content.groups.all()[0].name)
+ self.assertEquals('foo2', response.raw_content.groups.all()[1].name)
class MockPaginatorView(PaginatorMixin, View):
total = 60
def get(self, request):
- return range(0, self.total)
+ return Response(range(0, self.total))
def post(self, request):
- return Response(status.HTTP_201_CREATED, {'status': 'OK'})
+ return Response({'status': 'OK'}, status=status.HTTP_201_CREATED)
class TestPagination(TestCase):
@@ -168,8 +168,7 @@ class TestPagination(TestCase):
""" Tests if pagination works without overwriting the limit """
request = self.req.get('/paginator')
response = MockPaginatorView.as_view()(request)
-
- content = json.loads(response.content)
+ content = response.raw_content
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(MockPaginatorView.total, content['total'])
@@ -183,8 +182,7 @@ class TestPagination(TestCase):
request = self.req.get('/paginator')
response = MockPaginatorView.as_view(limit=limit)(request)
-
- content = json.loads(response.content)
+ content = response.raw_content
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(content['per_page'], limit)
@@ -200,8 +198,7 @@ class TestPagination(TestCase):
request = self.req.get('/paginator/?limit=%d' % limit)
response = MockPaginatorView.as_view()(request)
-
- content = json.loads(response.content)
+ content = response.raw_content
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(MockPaginatorView.total, content['total'])
@@ -217,8 +214,7 @@ class TestPagination(TestCase):
request = self.req.get('/paginator/?limit=%d' % limit)
response = MockPaginatorView.as_view()(request)
-
- content = json.loads(response.content)
+ content = response.raw_content
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(MockPaginatorView.total, content['total'])
@@ -230,8 +226,7 @@ class TestPagination(TestCase):
""" Pagination should only work for GET requests """
request = self.req.post('/paginator', data={'content': 'spam'})
response = MockPaginatorView.as_view()(request)
-
- content = json.loads(response.content)
+ content = response.raw_content
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(None, content.get('per_page'))
@@ -248,12 +243,12 @@ class TestPagination(TestCase):
""" Tests that the page range is handle correctly """
request = self.req.get('/paginator/?page=0')
response = MockPaginatorView.as_view()(request)
- content = json.loads(response.content)
+ content = response.raw_content
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
request = self.req.get('/paginator/')
response = MockPaginatorView.as_view()(request)
- content = json.loads(response.content)
+ content = response.raw_content
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(range(0, MockPaginatorView.limit), content['results'])
@@ -261,13 +256,13 @@ class TestPagination(TestCase):
request = self.req.get('/paginator/?page=%d' % num_pages)
response = MockPaginatorView.as_view()(request)
- content = json.loads(response.content)
+ content = response.raw_content
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(range(MockPaginatorView.limit*(num_pages-1), MockPaginatorView.total), content['results'])
request = self.req.get('/paginator/?page=%d' % (num_pages + 1,))
response = MockPaginatorView.as_view()(request)
- content = json.loads(response.content)
+ content = response.raw_content
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
def test_existing_query_parameters_are_preserved(self):
@@ -275,7 +270,7 @@ class TestPagination(TestCase):
generating next/previous page links """
request = self.req.get('/paginator/?foo=bar&another=something')
response = MockPaginatorView.as_view()(request)
- content = json.loads(response.content)
+ content = response.raw_content
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertTrue('foo=bar' in content['next'])
self.assertTrue('another=something' in content['next'])
diff --git a/djangorestframework/tests/renderers.py b/djangorestframework/tests/renderers.py
index 9a02d0a9..461bc877 100644
--- a/djangorestframework/tests/renderers.py
+++ b/djangorestframework/tests/renderers.py
@@ -1,177 +1,20 @@
import re
+from django.test import TestCase
+
from django.conf.urls.defaults import patterns, url
from django.test import TestCase
-from djangorestframework import status
+from djangorestframework.response import Response
from djangorestframework.views import View
-from djangorestframework.compat import View as DjangoView
from djangorestframework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer, \
XMLRenderer, JSONPRenderer, DocumentingHTMLRenderer
from djangorestframework.parsers import JSONParser, YAMLParser, XMLParser
-from djangorestframework.mixins import ResponseMixin
-from djangorestframework.response import Response
from StringIO import StringIO
import datetime
from decimal import Decimal
-DUMMYSTATUS = status.HTTP_200_OK
-DUMMYCONTENT = 'dummycontent'
-
-RENDERER_A_SERIALIZER = lambda x: 'Renderer A: %s' % x
-RENDERER_B_SERIALIZER = lambda x: 'Renderer B: %s' % x
-
-
-class RendererA(BaseRenderer):
- media_type = 'mock/renderera'
- format = "formata"
-
- def render(self, obj=None, media_type=None):
- return RENDERER_A_SERIALIZER(obj)
-
-
-class RendererB(BaseRenderer):
- media_type = 'mock/rendererb'
- format = "formatb"
-
- def render(self, obj=None, media_type=None):
- return RENDERER_B_SERIALIZER(obj)
-
-
-class MockView(ResponseMixin, DjangoView):
- renderers = (RendererA, RendererB)
-
- def get(self, request, **kwargs):
- response = Response(DUMMYSTATUS, DUMMYCONTENT)
- return self.render(response)
-
-
-class MockGETView(View):
-
- def get(self, request, **kwargs):
- return {'foo': ['bar', 'baz']}
-
-
-class HTMLView(View):
- renderers = (DocumentingHTMLRenderer, )
-
- def get(self, request, **kwargs):
- return 'text'
-
-
-class HTMLView1(View):
- renderers = (DocumentingHTMLRenderer, JSONRenderer)
-
- def get(self, request, **kwargs):
- return 'text'
-
-urlpatterns = patterns('',
- url(r'^.*\.(?P<format>.+)$', MockView.as_view(renderers=[RendererA, RendererB])),
- url(r'^$', MockView.as_view(renderers=[RendererA, RendererB])),
- url(r'^jsonp/jsonrenderer$', MockGETView.as_view(renderers=[JSONRenderer, JSONPRenderer])),
- url(r'^jsonp/nojsonrenderer$', MockGETView.as_view(renderers=[JSONPRenderer])),
- url(r'^html$', HTMLView.as_view()),
- url(r'^html1$', HTMLView1.as_view()),
-)
-
-
-class RendererIntegrationTests(TestCase):
- """
- End-to-end testing of renderers using an RendererMixin on a generic view.
- """
-
- urls = 'djangorestframework.tests.renderers'
-
- def test_default_renderer_serializes_content(self):
- """If the Accept header is not set the default renderer should serialize the response."""
- resp = self.client.get('/')
- self.assertEquals(resp['Content-Type'], RendererA.media_type)
- self.assertEquals(resp.content, RENDERER_A_SERIALIZER(DUMMYCONTENT))
- self.assertEquals(resp.status_code, DUMMYSTATUS)
-
- def test_head_method_serializes_no_content(self):
- """No response must be included in HEAD requests."""
- resp = self.client.head('/')
- self.assertEquals(resp.status_code, DUMMYSTATUS)
- self.assertEquals(resp['Content-Type'], RendererA.media_type)
- self.assertEquals(resp.content, '')
-
- def test_default_renderer_serializes_content_on_accept_any(self):
- """If the Accept header is set to */* the default renderer should serialize the response."""
- resp = self.client.get('/', HTTP_ACCEPT='*/*')
- self.assertEquals(resp['Content-Type'], RendererA.media_type)
- self.assertEquals(resp.content, RENDERER_A_SERIALIZER(DUMMYCONTENT))
- self.assertEquals(resp.status_code, DUMMYSTATUS)
-
- def test_specified_renderer_serializes_content_default_case(self):
- """If the Accept header is set the specified renderer should serialize the response.
- (In this case we check that works for the default renderer)"""
- resp = self.client.get('/', HTTP_ACCEPT=RendererA.media_type)
- self.assertEquals(resp['Content-Type'], RendererA.media_type)
- self.assertEquals(resp.content, RENDERER_A_SERIALIZER(DUMMYCONTENT))
- self.assertEquals(resp.status_code, DUMMYSTATUS)
-
- def test_specified_renderer_serializes_content_non_default_case(self):
- """If the Accept header is set the specified renderer should serialize the response.
- (In this case we check that works for a non-default renderer)"""
- resp = self.client.get('/', HTTP_ACCEPT=RendererB.media_type)
- self.assertEquals(resp['Content-Type'], RendererB.media_type)
- self.assertEquals(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
- self.assertEquals(resp.status_code, DUMMYSTATUS)
-
- def test_specified_renderer_serializes_content_on_accept_query(self):
- """The '_accept' query string should behave in the same way as the Accept header."""
- resp = self.client.get('/?_accept=%s' % RendererB.media_type)
- self.assertEquals(resp['Content-Type'], RendererB.media_type)
- self.assertEquals(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
- self.assertEquals(resp.status_code, DUMMYSTATUS)
-
- def test_unsatisfiable_accept_header_on_request_returns_406_status(self):
- """If the Accept header is unsatisfiable we should return a 406 Not Acceptable response."""
- resp = self.client.get('/', HTTP_ACCEPT='foo/bar')
- self.assertEquals(resp.status_code, status.HTTP_406_NOT_ACCEPTABLE)
-
- def test_specified_renderer_serializes_content_on_format_query(self):
- """If a 'format' query is specified, the renderer with the matching
- format attribute should serialize the response."""
- resp = self.client.get('/?format=%s' % RendererB.format)
- self.assertEquals(resp['Content-Type'], RendererB.media_type)
- self.assertEquals(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
- self.assertEquals(resp.status_code, DUMMYSTATUS)
-
- def test_specified_renderer_serializes_content_on_format_kwargs(self):
- """If a 'format' keyword arg is specified, the renderer with the matching
- format attribute should serialize the response."""
- resp = self.client.get('/something.formatb')
- self.assertEquals(resp['Content-Type'], RendererB.media_type)
- self.assertEquals(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
- self.assertEquals(resp.status_code, DUMMYSTATUS)
-
- def test_specified_renderer_is_used_on_format_query_with_matching_accept(self):
- """If both a 'format' query and a matching Accept header specified,
- the renderer with the matching format attribute should serialize the response."""
- resp = self.client.get('/?format=%s' % RendererB.format,
- HTTP_ACCEPT=RendererB.media_type)
- self.assertEquals(resp['Content-Type'], RendererB.media_type)
- self.assertEquals(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
- self.assertEquals(resp.status_code, DUMMYSTATUS)
-
- def test_conflicting_format_query_and_accept_ignores_accept(self):
- """If a 'format' query is specified that does not match the Accept
- header, we should only honor the 'format' query string."""
- resp = self.client.get('/?format=%s' % RendererB.format,
- HTTP_ACCEPT='dummy')
- self.assertEquals(resp['Content-Type'], RendererB.media_type)
- self.assertEquals(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
- self.assertEquals(resp.status_code, DUMMYSTATUS)
-
- def test_bla(self):
- resp = self.client.get('/?format=formatb',
- HTTP_ACCEPT='text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8')
- self.assertEquals(resp['Content-Type'], RendererB.media_type)
- self.assertEquals(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
- self.assertEquals(resp.status_code, DUMMYSTATUS)
_flat_repr = '{"foo": ["bar", "baz"]}'
_indented_repr = '{\n "foo": [\n "bar",\n "baz"\n ]\n}'
@@ -223,6 +66,18 @@ class JSONRendererTests(TestCase):
self.assertEquals(obj, data)
+class MockGETView(View):
+
+ def get(self, request, **kwargs):
+ return Response({'foo': ['bar', 'baz']})
+
+
+urlpatterns = patterns('',
+ url(r'^jsonp/jsonrenderer$', MockGETView.as_view(renderers=[JSONRenderer, JSONPRenderer])),
+ url(r'^jsonp/nojsonrenderer$', MockGETView.as_view(renderers=[JSONPRenderer])),
+)
+
+
class JSONPRendererTests(TestCase):
"""
Tests specific to the JSONP Renderer
@@ -391,21 +246,3 @@ class XMLRendererTestCase(TestCase):
self.assertTrue(xml.endswith('</root>'))
self.assertTrue(string in xml, '%r not in %r' % (string, xml))
-
-class Issue122Tests(TestCase):
- """
- Tests that covers #122.
- """
- urls = 'djangorestframework.tests.renderers'
-
- def test_only_html_renderer(self):
- """
- Test if no infinite recursion occurs.
- """
- resp = self.client.get('/html')
-
- def test_html_renderer_is_first(self):
- """
- Test if no infinite recursion occurs.
- """
- resp = self.client.get('/html1')
diff --git a/djangorestframework/tests/request.py b/djangorestframework/tests/request.py
index 6a0eae21..77a34033 100644
--- a/djangorestframework/tests/request.py
+++ b/djangorestframework/tests/request.py
@@ -6,7 +6,7 @@ from django.contrib.auth.models import User
from django.test import TestCase, Client
from djangorestframework import status
from djangorestframework.authentication import UserLoggedInAuthentication
-from djangorestframework.compat import RequestFactory, unittest
+from djangorestframework.compat import RequestFactory
from djangorestframework.mixins import RequestMixin
from djangorestframework.parsers import FormParser, MultiPartParser, \
PlainTextParser, JSONParser
@@ -19,9 +19,9 @@ class MockView(View):
authentication = (UserLoggedInAuthentication,)
def post(self, request):
if request.POST.get('example') is not None:
- return Response(status.HTTP_200_OK)
+ return Response(status=status.HTTP_200_OK)
- return Response(status.INTERNAL_SERVER_ERROR)
+ return Response(status=status.INTERNAL_SERVER_ERROR)
urlpatterns = patterns('',
(r'^$', MockView.as_view()),
diff --git a/djangorestframework/tests/response.py b/djangorestframework/tests/response.py
index d973deb4..5a01e356 100644
--- a/djangorestframework/tests/response.py
+++ b/djangorestframework/tests/response.py
@@ -1,19 +1,264 @@
-# Right now we expect this test to fail - I'm just going to leave it commented out.
-# Looking forward to actually being able to raise ExpectedFailure sometime!
-#
-#from django.test import TestCase
-#from djangorestframework.response import Response
-#
-#
-#class TestResponse(TestCase):
-#
-# # Interface tests
-#
-# # This is mainly to remind myself that the Response interface needs to change slightly
-# def test_response_interface(self):
-# """Ensure the Response interface is as expected."""
-# response = Response()
-# getattr(response, 'status')
-# getattr(response, 'content')
-# getattr(response, 'headers')
+import json
+from django.conf.urls.defaults import patterns, url
+from django.test import TestCase
+
+from djangorestframework.response import Response, ErrorResponse
+from djangorestframework.mixins import ResponseMixin
+from djangorestframework.views import View
+from djangorestframework.compat import View as DjangoView
+from djangorestframework.renderers import BaseRenderer, DEFAULT_RENDERERS
+from djangorestframework.compat import RequestFactory
+from djangorestframework import status
+from djangorestframework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer, \
+ XMLRenderer, JSONPRenderer, DocumentingHTMLRenderer
+
+
+class TestResponseDetermineRenderer(TestCase):
+
+ def get_response(self, url='', accept_list=[], renderers=[]):
+ request = RequestFactory().get(url, HTTP_ACCEPT=','.join(accept_list))
+ return Response(request=request, renderers=renderers)
+
+ def get_renderer_mock(self, media_type):
+ return type('RendererMock', (BaseRenderer,), {
+ 'media_type': media_type,
+ })
+
+ def test_determine_accept_list_accept_header(self):
+ """
+ Test that determine_accept_list takes the Accept header.
+ """
+ accept_list = ['application/pickle', 'application/json']
+ response = self.get_response(accept_list=accept_list)
+ self.assertEqual(response._determine_accept_list(), accept_list)
+
+ def test_determine_accept_list_overriden_header(self):
+ """
+ Test Accept header overriding.
+ """
+ accept_list = ['application/pickle', 'application/json']
+ response = self.get_response(url='?_accept=application/x-www-form-urlencoded',
+ accept_list=accept_list)
+ self.assertEqual(response._determine_accept_list(), ['application/x-www-form-urlencoded'])
+
+ def test_determine_renderer(self):
+ """
+ Test that right renderer is chosen, in the order of Accept list.
+ """
+ accept_list = ['application/pickle', 'application/json']
+ PRenderer = self.get_renderer_mock('application/pickle')
+ JRenderer = self.get_renderer_mock('application/json')
+
+ renderers = (PRenderer, JRenderer)
+ response = self.get_response(accept_list=accept_list, renderers=renderers)
+ renderer, media_type = response._determine_renderer()
+ self.assertEqual(media_type, 'application/pickle')
+ self.assertTrue(isinstance(renderer, PRenderer))
+
+ renderers = (JRenderer,)
+ response = self.get_response(accept_list=accept_list, renderers=renderers)
+ renderer, media_type = response._determine_renderer()
+ self.assertEqual(media_type, 'application/json')
+ self.assertTrue(isinstance(renderer, JRenderer))
+
+ def test_determine_renderer_no_renderer(self):
+ """
+ Test determine renderer when no renderer can satisfy the Accept list.
+ """
+ accept_list = ['application/json']
+ PRenderer = self.get_renderer_mock('application/pickle')
+
+ renderers = (PRenderer,)
+ response = self.get_response(accept_list=accept_list, renderers=renderers)
+ self.assertRaises(ErrorResponse, response._determine_renderer)
+
+
+class TestResponseRenderContent(TestCase):
+
+ def get_response(self, url='', accept_list=[], content=None):
+ request = RequestFactory().get(url, HTTP_ACCEPT=','.join(accept_list))
+ return Response(request=request, content=content, renderers=DEFAULT_RENDERERS)
+
+ def test_render(self):
+ """
+ Test rendering simple data to json.
+ """
+ content = {'a': 1, 'b': [1, 2, 3]}
+ content_type = 'application/json'
+ response = self.get_response(accept_list=[content_type], content=content)
+ response.render()
+ self.assertEqual(json.loads(response.content), content)
+ self.assertEqual(response['Content-Type'], content_type)
+
+
+DUMMYSTATUS = status.HTTP_200_OK
+DUMMYCONTENT = 'dummycontent'
+
+RENDERER_A_SERIALIZER = lambda x: 'Renderer A: %s' % x
+RENDERER_B_SERIALIZER = lambda x: 'Renderer B: %s' % x
+
+
+class RendererA(BaseRenderer):
+ media_type = 'mock/renderera'
+ format = "formata"
+
+ def render(self, obj=None, media_type=None):
+ return RENDERER_A_SERIALIZER(obj)
+
+
+class RendererB(BaseRenderer):
+ media_type = 'mock/rendererb'
+ format = "formatb"
+
+ def render(self, obj=None, media_type=None):
+ return RENDERER_B_SERIALIZER(obj)
+
+
+class MockView(ResponseMixin, DjangoView):
+ renderers = (RendererA, RendererB)
+
+ def get(self, request, **kwargs):
+ response = Response(DUMMYCONTENT, status=DUMMYSTATUS)
+ return self.prepare_response(response)
+
+
+class HTMLView(View):
+ renderers = (DocumentingHTMLRenderer, )
+
+ def get(self, request, **kwargs):
+ return Response('text')
+
+
+class HTMLView1(View):
+ renderers = (DocumentingHTMLRenderer, JSONRenderer)
+
+ def get(self, request, **kwargs):
+ return Response('text')
+
+
+urlpatterns = patterns('',
+ url(r'^.*\.(?P<format>.+)$', MockView.as_view(renderers=[RendererA, RendererB])),
+ url(r'^$', MockView.as_view(renderers=[RendererA, RendererB])),
+ url(r'^html$', HTMLView.as_view()),
+ url(r'^html1$', HTMLView1.as_view()),
+)
+
+
+# TODO: Clean tests bellow - remove duplicates with above, better unit testing, ...
+class RendererIntegrationTests(TestCase):
+ """
+ End-to-end testing of renderers using an ResponseMixin on a generic view.
+ """
+
+ urls = 'djangorestframework.tests.response'
+
+ def test_default_renderer_serializes_content(self):
+ """If the Accept header is not set the default renderer should serialize the response."""
+ resp = self.client.get('/')
+ self.assertEquals(resp['Content-Type'], RendererA.media_type)
+ self.assertEquals(resp.content, RENDERER_A_SERIALIZER(DUMMYCONTENT))
+ self.assertEquals(resp.status_code, DUMMYSTATUS)
+
+ def test_head_method_serializes_no_content(self):
+ """No response must be included in HEAD requests."""
+ resp = self.client.head('/')
+ self.assertEquals(resp.status_code, DUMMYSTATUS)
+ self.assertEquals(resp['Content-Type'], RendererA.media_type)
+ self.assertEquals(resp.content, '')
+
+ def test_default_renderer_serializes_content_on_accept_any(self):
+ """If the Accept header is set to */* the default renderer should serialize the response."""
+ resp = self.client.get('/', HTTP_ACCEPT='*/*')
+ self.assertEquals(resp['Content-Type'], RendererA.media_type)
+ self.assertEquals(resp.content, RENDERER_A_SERIALIZER(DUMMYCONTENT))
+ self.assertEquals(resp.status_code, DUMMYSTATUS)
+
+ def test_specified_renderer_serializes_content_default_case(self):
+ """If the Accept header is set the specified renderer should serialize the response.
+ (In this case we check that works for the default renderer)"""
+ resp = self.client.get('/', HTTP_ACCEPT=RendererA.media_type)
+ self.assertEquals(resp['Content-Type'], RendererA.media_type)
+ self.assertEquals(resp.content, RENDERER_A_SERIALIZER(DUMMYCONTENT))
+ self.assertEquals(resp.status_code, DUMMYSTATUS)
+
+ def test_specified_renderer_serializes_content_non_default_case(self):
+ """If the Accept header is set the specified renderer should serialize the response.
+ (In this case we check that works for a non-default renderer)"""
+ resp = self.client.get('/', HTTP_ACCEPT=RendererB.media_type)
+ self.assertEquals(resp['Content-Type'], RendererB.media_type)
+ self.assertEquals(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
+ self.assertEquals(resp.status_code, DUMMYSTATUS)
+
+ def test_specified_renderer_serializes_content_on_accept_query(self):
+ """The '_accept' query string should behave in the same way as the Accept header."""
+ resp = self.client.get('/?_accept=%s' % RendererB.media_type)
+ self.assertEquals(resp['Content-Type'], RendererB.media_type)
+ self.assertEquals(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
+ self.assertEquals(resp.status_code, DUMMYSTATUS)
+
+# TODO: can't pass because view is a simple Django view and response is an ErrorResponse
+# def test_unsatisfiable_accept_header_on_request_returns_406_status(self):
+# """If the Accept header is unsatisfiable we should return a 406 Not Acceptable response."""
+# resp = self.client.get('/', HTTP_ACCEPT='foo/bar')
+# self.assertEquals(resp.status_code, status.HTTP_406_NOT_ACCEPTABLE)
+
+ def test_specified_renderer_serializes_content_on_format_query(self):
+ """If a 'format' query is specified, the renderer with the matching
+ format attribute should serialize the response."""
+ resp = self.client.get('/?format=%s' % RendererB.format)
+ self.assertEquals(resp['Content-Type'], RendererB.media_type)
+ self.assertEquals(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
+ self.assertEquals(resp.status_code, DUMMYSTATUS)
+
+ def test_specified_renderer_serializes_content_on_format_kwargs(self):
+ """If a 'format' keyword arg is specified, the renderer with the matching
+ format attribute should serialize the response."""
+ resp = self.client.get('/something.formatb')
+ self.assertEquals(resp['Content-Type'], RendererB.media_type)
+ self.assertEquals(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
+ self.assertEquals(resp.status_code, DUMMYSTATUS)
+
+ def test_specified_renderer_is_used_on_format_query_with_matching_accept(self):
+ """If both a 'format' query and a matching Accept header specified,
+ the renderer with the matching format attribute should serialize the response."""
+ resp = self.client.get('/?format=%s' % RendererB.format,
+ HTTP_ACCEPT=RendererB.media_type)
+ self.assertEquals(resp['Content-Type'], RendererB.media_type)
+ self.assertEquals(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
+ self.assertEquals(resp.status_code, DUMMYSTATUS)
+
+ def test_conflicting_format_query_and_accept_ignores_accept(self):
+ """If a 'format' query is specified that does not match the Accept
+ header, we should only honor the 'format' query string."""
+ resp = self.client.get('/?format=%s' % RendererB.format,
+ HTTP_ACCEPT='dummy')
+ self.assertEquals(resp['Content-Type'], RendererB.media_type)
+ self.assertEquals(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
+ self.assertEquals(resp.status_code, DUMMYSTATUS)
+
+ def test_bla(self):
+ resp = self.client.get('/?format=formatb',
+ HTTP_ACCEPT='text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8')
+ self.assertEquals(resp['Content-Type'], RendererB.media_type)
+ self.assertEquals(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
+ self.assertEquals(resp.status_code, DUMMYSTATUS)
+
+
+class Issue122Tests(TestCase):
+ """
+ Tests that covers #122.
+ """
+ urls = 'djangorestframework.tests.response'
+
+ def test_only_html_renderer(self):
+ """
+ Test if no infinite recursion occurs.
+ """
+ resp = self.client.get('/html')
+
+ def test_html_renderer_is_first(self):
+ """
+ Test if no infinite recursion occurs.
+ """
+ resp = self.client.get('/html1')
diff --git a/djangorestframework/tests/reverse.py b/djangorestframework/tests/reverse.py
index 2d1ca79e..c49caca0 100644
--- a/djangorestframework/tests/reverse.py
+++ b/djangorestframework/tests/reverse.py
@@ -4,6 +4,7 @@ from django.test import TestCase
from django.utils import simplejson as json
from djangorestframework.views import View
+from djangorestframework.response import Response
class MockView(View):
@@ -11,7 +12,7 @@ class MockView(View):
permissions = ()
def get(self, request):
- return reverse('another')
+ return Response(reverse('another'))
urlpatterns = patterns('',
url(r'^$', MockView.as_view()),
diff --git a/djangorestframework/tests/throttling.py b/djangorestframework/tests/throttling.py
index 7fdc6491..393c3ec8 100644
--- a/djangorestframework/tests/throttling.py
+++ b/djangorestframework/tests/throttling.py
@@ -10,13 +10,14 @@ from djangorestframework.compat import RequestFactory
from djangorestframework.views import View
from djangorestframework.permissions import PerUserThrottling, PerViewThrottling, PerResourceThrottling
from djangorestframework.resources import FormResource
+from djangorestframework.response import Response
class MockView(View):
permissions = ( PerUserThrottling, )
throttle = '3/sec'
def get(self, request):
- return 'foo'
+ return Response('foo')
class MockView_PerViewThrottling(MockView):
permissions = ( PerViewThrottling, )
diff --git a/djangorestframework/tests/validators.py b/djangorestframework/tests/validators.py
index 15d92231..1f384b4c 100644
--- a/djangorestframework/tests/validators.py
+++ b/djangorestframework/tests/validators.py
@@ -81,8 +81,8 @@ class TestNonFieldErrors(TestCase):
content = {'field1': 'example1', 'field2': 'example2'}
try:
MockResource(view).validate_request(content, None)
- except ErrorResponse, exc:
- self.assertEqual(exc.response.raw_content, {'errors': [MockForm.ERROR_TEXT]})
+ except ErrorResponse, response:
+ self.assertEqual(response.raw_content, {'errors': [MockForm.ERROR_TEXT]})
else:
self.fail('ErrorResponse was not raised')
@@ -154,8 +154,8 @@ class TestFormValidation(TestCase):
content = {}
try:
validator.validate_request(content, None)
- except ErrorResponse, exc:
- self.assertEqual(exc.response.raw_content, {'field_errors': {'qwerty': ['This field is required.']}})
+ except ErrorResponse, response:
+ self.assertEqual(response.raw_content, {'field_errors': {'qwerty': ['This field is required.']}})
else:
self.fail('ResourceException was not raised')
@@ -164,8 +164,8 @@ class TestFormValidation(TestCase):
content = {'qwerty': ''}
try:
validator.validate_request(content, None)
- except ErrorResponse, exc:
- self.assertEqual(exc.response.raw_content, {'field_errors': {'qwerty': ['This field is required.']}})
+ except ErrorResponse, response:
+ self.assertEqual(response.raw_content, {'field_errors': {'qwerty': ['This field is required.']}})
else:
self.fail('ResourceException was not raised')
@@ -174,8 +174,8 @@ class TestFormValidation(TestCase):
content = {'qwerty': 'uiop', 'extra': 'extra'}
try:
validator.validate_request(content, None)
- except ErrorResponse, exc:
- self.assertEqual(exc.response.raw_content, {'field_errors': {'extra': ['This field does not exist.']}})
+ except ErrorResponse, response:
+ self.assertEqual(response.raw_content, {'field_errors': {'extra': ['This field does not exist.']}})
else:
self.fail('ResourceException was not raised')
@@ -184,8 +184,8 @@ class TestFormValidation(TestCase):
content = {'qwerty': '', 'extra': 'extra'}
try:
validator.validate_request(content, None)
- except ErrorResponse, exc:
- self.assertEqual(exc.response.raw_content, {'field_errors': {'qwerty': ['This field is required.'],
+ except ErrorResponse, response:
+ self.assertEqual(response.raw_content, {'field_errors': {'qwerty': ['This field is required.'],
'extra': ['This field does not exist.']}})
else:
self.fail('ResourceException was not raised')