From ab0b72a7c1a17c6d85530514caa51ce5bd77b592 Mon Sep 17 00:00:00 2001 From: Sébastien Piquemal Date: Sun, 22 Jan 2012 21:28:34 +0200 Subject: .DATA, .FILES, overloaded HTTP method, content type and content available directly on the request - see #128 --- djangorestframework/tests/content.py | 233 ------------------------------ djangorestframework/tests/methods.py | 32 ----- djangorestframework/tests/renderers.py | 2 +- djangorestframework/tests/request.py | 250 +++++++++++++++++++++++++++++++++ 4 files changed, 251 insertions(+), 266 deletions(-) delete mode 100644 djangorestframework/tests/content.py create mode 100644 djangorestframework/tests/request.py (limited to 'djangorestframework/tests') diff --git a/djangorestframework/tests/content.py b/djangorestframework/tests/content.py deleted file mode 100644 index 6bae8feb..00000000 --- a/djangorestframework/tests/content.py +++ /dev/null @@ -1,233 +0,0 @@ -""" -Tests for content parsing, and form-overloaded content parsing. -""" -from django.conf.urls.defaults import patterns -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.mixins import RequestMixin -from djangorestframework.parsers import FormParser, MultiPartParser, \ - PlainTextParser, JSONParser -from djangorestframework.response import Response -from djangorestframework.views import View - -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.INTERNAL_SERVER_ERROR) - -urlpatterns = patterns('', - (r'^$', MockView.as_view()), -) - -class TestContentParsing(TestCase): - def setUp(self): - self.req = RequestFactory() - - def ensure_determines_no_content_GET(self, view): - """Ensure view.DATA returns None for GET request with no content.""" - view.request = self.req.get('/') - self.assertEqual(view.DATA, None) - - def ensure_determines_no_content_HEAD(self, view): - """Ensure view.DATA returns None for HEAD request.""" - view.request = self.req.head('/') - self.assertEqual(view.DATA, None) - - def ensure_determines_form_content_POST(self, view): - """Ensure view.DATA returns content for POST request with form content.""" - form_data = {'qwerty': 'uiop'} - view.parsers = (FormParser, MultiPartParser) - view.request = self.req.post('/', data=form_data) - self.assertEqual(view.DATA.items(), form_data.items()) - - def ensure_determines_non_form_content_POST(self, view): - """Ensure view.RAW_CONTENT returns content for POST request with non-form content.""" - content = 'qwerty' - content_type = 'text/plain' - view.parsers = (PlainTextParser,) - view.request = self.req.post('/', content, content_type=content_type) - self.assertEqual(view.DATA, content) - - def ensure_determines_form_content_PUT(self, view): - """Ensure view.RAW_CONTENT returns content for PUT request with form content.""" - form_data = {'qwerty': 'uiop'} - view.parsers = (FormParser, MultiPartParser) - view.request = self.req.put('/', data=form_data) - self.assertEqual(view.DATA.items(), form_data.items()) - - def ensure_determines_non_form_content_PUT(self, view): - """Ensure view.RAW_CONTENT returns content for PUT request with non-form content.""" - content = 'qwerty' - content_type = 'text/plain' - view.parsers = (PlainTextParser,) - view.request = self.req.post('/', content, content_type=content_type) - self.assertEqual(view.DATA, content) - - def test_standard_behaviour_determines_no_content_GET(self): - """Ensure view.DATA returns None for GET request with no content.""" - self.ensure_determines_no_content_GET(RequestMixin()) - - def test_standard_behaviour_determines_no_content_HEAD(self): - """Ensure view.DATA returns None for HEAD request.""" - self.ensure_determines_no_content_HEAD(RequestMixin()) - - def test_standard_behaviour_determines_form_content_POST(self): - """Ensure view.DATA returns content for POST request with form content.""" - self.ensure_determines_form_content_POST(RequestMixin()) - - def test_standard_behaviour_determines_non_form_content_POST(self): - """Ensure view.DATA returns content for POST request with non-form content.""" - self.ensure_determines_non_form_content_POST(RequestMixin()) - - def test_standard_behaviour_determines_form_content_PUT(self): - """Ensure view.DATA returns content for PUT request with form content.""" - self.ensure_determines_form_content_PUT(RequestMixin()) - - def test_standard_behaviour_determines_non_form_content_PUT(self): - """Ensure view.DATA returns content for PUT request with non-form content.""" - self.ensure_determines_non_form_content_PUT(RequestMixin()) - - def test_overloaded_behaviour_allows_content_tunnelling(self): - """Ensure request.DATA returns content for overloaded POST request""" - content = 'qwerty' - content_type = 'text/plain' - view = RequestMixin() - form_data = {view._CONTENT_PARAM: content, - view._CONTENTTYPE_PARAM: content_type} - view.request = self.req.post('/', form_data) - view.parsers = (PlainTextParser,) - self.assertEqual(view.DATA, content) - - def test_accessing_post_after_data_form(self): - """Ensures request.POST can be accessed after request.DATA in form request""" - form_data = {'qwerty': 'uiop'} - view = RequestMixin() - view.parsers = (FormParser, MultiPartParser) - view.request = self.req.post('/', data=form_data) - - self.assertEqual(view.DATA.items(), form_data.items()) - self.assertEqual(view.request.POST.items(), form_data.items()) - - @unittest.skip('This test was disabled some time ago for some reason') - def test_accessing_post_after_data_for_json(self): - """Ensures request.POST can be accessed after request.DATA in json request""" - from django.utils import simplejson as json - - data = {'qwerty': 'uiop'} - content = json.dumps(data) - content_type = 'application/json' - - view = RequestMixin() - view.parsers = (JSONParser,) - - view.request = self.req.post('/', content, content_type=content_type) - - self.assertEqual(view.DATA.items(), data.items()) - self.assertEqual(view.request.POST.items(), []) - - def test_accessing_post_after_data_for_overloaded_json(self): - """Ensures request.POST can be accessed after request.DATA in overloaded json request""" - from django.utils import simplejson as json - - data = {'qwerty': 'uiop'} - content = json.dumps(data) - content_type = 'application/json' - - view = RequestMixin() - view.parsers = (JSONParser,) - - form_data = {view._CONTENT_PARAM: content, - view._CONTENTTYPE_PARAM: content_type} - - view.request = self.req.post('/', data=form_data) - - self.assertEqual(view.DATA.items(), data.items()) - self.assertEqual(view.request.POST.items(), form_data.items()) - - def test_accessing_data_after_post_form(self): - """Ensures request.DATA can be accessed after request.POST in form request""" - form_data = {'qwerty': 'uiop'} - view = RequestMixin() - view.parsers = (FormParser, MultiPartParser) - view.request = self.req.post('/', data=form_data) - - self.assertEqual(view.request.POST.items(), form_data.items()) - self.assertEqual(view.DATA.items(), form_data.items()) - - def test_accessing_data_after_post_for_json(self): - """Ensures request.DATA can be accessed after request.POST in json request""" - from django.utils import simplejson as json - - data = {'qwerty': 'uiop'} - content = json.dumps(data) - content_type = 'application/json' - - view = RequestMixin() - view.parsers = (JSONParser,) - - view.request = self.req.post('/', content, content_type=content_type) - - post_items = view.request.POST.items() - - self.assertEqual(len(post_items), 1) - self.assertEqual(len(post_items[0]), 2) - self.assertEqual(post_items[0][0], content) - self.assertEqual(view.DATA.items(), data.items()) - - def test_accessing_data_after_post_for_overloaded_json(self): - """Ensures request.DATA can be accessed after request.POST in overloaded json request""" - from django.utils import simplejson as json - - data = {'qwerty': 'uiop'} - content = json.dumps(data) - content_type = 'application/json' - - view = RequestMixin() - view.parsers = (JSONParser,) - - form_data = {view._CONTENT_PARAM: content, - view._CONTENTTYPE_PARAM: content_type} - - view.request = self.req.post('/', data=form_data) - - self.assertEqual(view.request.POST.items(), form_data.items()) - self.assertEqual(view.DATA.items(), data.items()) - -class TestContentParsingWithAuthentication(TestCase): - urls = 'djangorestframework.tests.content' - - def setUp(self): - self.csrf_client = Client(enforce_csrf_checks=True) - self.username = 'john' - self.email = 'lennon@thebeatles.com' - self.password = 'password' - self.user = User.objects.create_user(self.username, self.email, self.password) - self.req = RequestFactory() - - def test_user_logged_in_authentication_has_post_when_not_logged_in(self): - """Ensures request.POST exists after UserLoggedInAuthentication when user doesn't log in""" - content = {'example': 'example'} - - response = self.client.post('/', content) - self.assertEqual(status.HTTP_200_OK, response.status_code, "POST data is malformed") - - response = self.csrf_client.post('/', content) - self.assertEqual(status.HTTP_200_OK, response.status_code, "POST data is malformed") - - # def test_user_logged_in_authentication_has_post_when_logged_in(self): - # """Ensures request.POST exists after UserLoggedInAuthentication when user does log in""" - # self.client.login(username='john', password='password') - # self.csrf_client.login(username='john', password='password') - # content = {'example': 'example'} - - # response = self.client.post('/', content) - # self.assertEqual(status.OK, response.status_code, "POST data is malformed") - - # response = self.csrf_client.post('/', content) - # self.assertEqual(status.OK, response.status_code, "POST data is malformed") diff --git a/djangorestframework/tests/methods.py b/djangorestframework/tests/methods.py index 4b90a21f..e69de29b 100644 --- a/djangorestframework/tests/methods.py +++ b/djangorestframework/tests/methods.py @@ -1,32 +0,0 @@ -from django.test import TestCase -from djangorestframework.compat import RequestFactory -from djangorestframework.mixins import RequestMixin - - -class TestMethodOverloading(TestCase): - def setUp(self): - self.req = RequestFactory() - - def test_standard_behaviour_determines_GET(self): - """GET requests identified""" - view = RequestMixin() - view.request = self.req.get('/') - self.assertEqual(view.method, 'GET') - - def test_standard_behaviour_determines_POST(self): - """POST requests identified""" - view = RequestMixin() - view.request = self.req.post('/') - self.assertEqual(view.method, 'POST') - - def test_overloaded_POST_behaviour_determines_overloaded_method(self): - """POST requests can be overloaded to another method by setting a reserved form field""" - view = RequestMixin() - view.request = self.req.post('/', {view._METHOD_PARAM: 'DELETE'}) - self.assertEqual(view.method, 'DELETE') - - def test_HEAD_is_a_valid_method(self): - """HEAD requests identified""" - view = RequestMixin() - view.request = self.req.head('/') - self.assertEqual(view.method, 'HEAD') diff --git a/djangorestframework/tests/renderers.py b/djangorestframework/tests/renderers.py index 84e4390b..adb46f7f 100644 --- a/djangorestframework/tests/renderers.py +++ b/djangorestframework/tests/renderers.py @@ -172,7 +172,7 @@ class RendererIntegrationTests(TestCase): self.assertEquals(resp.status_code, DUMMYSTATUS) _flat_repr = '{"foo": ["bar", "baz"]}' -_indented_repr = '{\n "foo": [\n "bar", \n "baz"\n ]\n}' +_indented_repr = '{\n "foo": [\n "bar",\n "baz"\n ]\n}' class JSONRendererTests(TestCase): diff --git a/djangorestframework/tests/request.py b/djangorestframework/tests/request.py new file mode 100644 index 00000000..7f3a485e --- /dev/null +++ b/djangorestframework/tests/request.py @@ -0,0 +1,250 @@ +""" +Tests for content parsing, and form-overloaded content parsing. +""" +from django.conf.urls.defaults import patterns +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.mixins import RequestMixin +from djangorestframework.parsers import FormParser, MultiPartParser, \ + PlainTextParser, JSONParser +from djangorestframework.response import Response +from djangorestframework.request import Request +from djangorestframework.views import View +from djangorestframework.request import request_class_factory + +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.INTERNAL_SERVER_ERROR) + +urlpatterns = patterns('', + (r'^$', MockView.as_view()), +) + +request_class = request_class_factory(RequestFactory().get('/')) + + +class RequestTestCase(TestCase): + + def tearDown(self): + request_class.parsers = () + + def build_request(self, method, *args, **kwargs): + factory = RequestFactory() + method = getattr(factory, method) + original_request = method(*args, **kwargs) + return request_class(original_request) + + +class TestMethodOverloading(RequestTestCase): + + def test_standard_behaviour_determines_GET(self): + """GET requests identified""" + request = self.build_request('get', '/') + self.assertEqual(request.method, 'GET') + + def test_standard_behaviour_determines_POST(self): + """POST requests identified""" + request = self.build_request('post', '/') + self.assertEqual(request.method, 'POST') + + def test_overloaded_POST_behaviour_determines_overloaded_method(self): + """POST requests can be overloaded to another method by setting a reserved form field""" + request = self.build_request('post', '/', {Request._METHOD_PARAM: 'DELETE'}) + self.assertEqual(request.method, 'DELETE') + + def test_HEAD_is_a_valid_method(self): + """HEAD requests identified""" + request = request = self.build_request('head', '/') + self.assertEqual(request.method, 'HEAD') + + +class TestContentParsing(RequestTestCase): + #TODO: is there any reason why many test cases documented as testing a PUT, + # in fact use a POST !? + + def tearDown(self): + request_class.parsers = () + + def build_request(self, method, *args, **kwargs): + factory = RequestFactory() + method = getattr(factory, method) + original_request = method(*args, **kwargs) + return request_class(original_request) + + def test_standard_behaviour_determines_no_content_GET(self): + """Ensure request.DATA returns None for GET request with no content.""" + request = self.build_request('get', '/') + self.assertEqual(request.DATA, None) + + def test_standard_behaviour_determines_no_content_HEAD(self): + """Ensure request.DATA returns None for HEAD request.""" + request = self.build_request('head', '/') + self.assertEqual(request.DATA, None) + + def test_standard_behaviour_determines_form_content_POST(self): + """Ensure request.DATA returns content for POST request with form content.""" + form_data = {'qwerty': 'uiop'} + request_class.parsers = (FormParser, MultiPartParser) + request = self.build_request('post', '/', data=form_data) + self.assertEqual(request.DATA.items(), form_data.items()) + + def test_standard_behaviour_determines_non_form_content_POST(self): + """Ensure request.DATA returns content for POST request with non-form content.""" + content = 'qwerty' + content_type = 'text/plain' + request_class.parsers = (PlainTextParser,) + request = self.build_request('post', '/', content, content_type=content_type) + self.assertEqual(request.DATA, content) + + def test_standard_behaviour_determines_form_content_PUT(self): + """Ensure request.DATA returns content for PUT request with form content.""" + form_data = {'qwerty': 'uiop'} + request_class.parsers = (FormParser, MultiPartParser) + request = self.build_request('put', '/', data=form_data) + self.assertEqual(request.DATA.items(), form_data.items()) + + def test_standard_behaviour_determines_non_form_content_PUT(self): + """Ensure request.DATA returns content for PUT request with non-form content.""" + content = 'qwerty' + content_type = 'text/plain' + request_class.parsers = (PlainTextParser,) + request = self.build_request('post', '/', content, content_type=content_type) + self.assertEqual(request.DATA, content) + + def test_overloaded_behaviour_allows_content_tunnelling(self): + """Ensure request.DATA returns content for overloaded POST request""" + content = 'qwerty' + content_type = 'text/plain' + form_data = {Request._CONTENT_PARAM: content, + Request._CONTENTTYPE_PARAM: content_type} + request_class.parsers = (PlainTextParser,) + request = self.build_request('post', '/', form_data) + self.assertEqual(request.DATA, content) + + def test_accessing_post_after_data_form(self): + """Ensures request.POST can be accessed after request.DATA in form request""" + form_data = {'qwerty': 'uiop'} + request_class.parsers = (FormParser, MultiPartParser) + request = self.build_request('post', '/', data=form_data) + + self.assertEqual(request.DATA.items(), form_data.items()) + self.assertEqual(request.POST.items(), form_data.items()) + + def test_accessing_post_after_data_for_json(self): + """Ensures request.POST can be accessed after request.DATA in json request""" + from django.utils import simplejson as json + + data = {'qwerty': 'uiop'} + content = json.dumps(data) + content_type = 'application/json' + + request_class.parsers = (JSONParser,) + + request = self.build_request('post', '/', content, content_type=content_type) + + self.assertEqual(request.DATA.items(), data.items()) + self.assertEqual(request.POST.items(), []) + + def test_accessing_post_after_data_for_overloaded_json(self): + """Ensures request.POST can be accessed after request.DATA in overloaded json request""" + from django.utils import simplejson as json + + data = {'qwerty': 'uiop'} + content = json.dumps(data) + content_type = 'application/json' + + request_class.parsers = (JSONParser,) + + form_data = {Request._CONTENT_PARAM: content, + Request._CONTENTTYPE_PARAM: content_type} + + request = self.build_request('post', '/', data=form_data) + + self.assertEqual(request.DATA.items(), data.items()) + self.assertEqual(request.POST.items(), form_data.items()) + + def test_accessing_data_after_post_form(self): + """Ensures request.DATA can be accessed after request.POST in form request""" + form_data = {'qwerty': 'uiop'} + request_class.parsers = (FormParser, MultiPartParser) + request = self.build_request('post', '/', data=form_data) + + self.assertEqual(request.POST.items(), form_data.items()) + self.assertEqual(request.DATA.items(), form_data.items()) + + def test_accessing_data_after_post_for_json(self): + """Ensures request.DATA can be accessed after request.POST in json request""" + from django.utils import simplejson as json + + data = {'qwerty': 'uiop'} + content = json.dumps(data) + content_type = 'application/json' + + request_class.parsers = (JSONParser,) + + request = self.build_request('post', '/', content, content_type=content_type) + + post_items = request.POST.items() + + self.assertEqual(len(post_items), 1) + self.assertEqual(len(post_items[0]), 2) + self.assertEqual(post_items[0][0], content) + self.assertEqual(request.DATA.items(), data.items()) + + def test_accessing_data_after_post_for_overloaded_json(self): + """Ensures request.DATA can be accessed after request.POST in overloaded json request""" + from django.utils import simplejson as json + + data = {'qwerty': 'uiop'} + content = json.dumps(data) + content_type = 'application/json' + + request_class.parsers = (JSONParser,) + + form_data = {Request._CONTENT_PARAM: content, + Request._CONTENTTYPE_PARAM: content_type} + + request = self.build_request('post', '/', data=form_data) + self.assertEqual(request.POST.items(), form_data.items()) + self.assertEqual(request.DATA.items(), data.items()) + + +class TestContentParsingWithAuthentication(TestCase): + urls = 'djangorestframework.tests.request' + + def setUp(self): + self.csrf_client = Client(enforce_csrf_checks=True) + self.username = 'john' + self.email = 'lennon@thebeatles.com' + self.password = 'password' + self.user = User.objects.create_user(self.username, self.email, self.password) + self.req = RequestFactory() + + def test_user_logged_in_authentication_has_post_when_not_logged_in(self): + """Ensures request.POST exists after UserLoggedInAuthentication when user doesn't log in""" + content = {'example': 'example'} + + response = self.client.post('/', content) + self.assertEqual(status.HTTP_200_OK, response.status_code, "POST data is malformed") + + response = self.csrf_client.post('/', content) + self.assertEqual(status.HTTP_200_OK, response.status_code, "POST data is malformed") + + # def test_user_logged_in_authentication_has_post_when_logged_in(self): + # """Ensures request.POST exists after UserLoggedInAuthentication when user does log in""" + # self.client.login(username='john', password='password') + # self.csrf_client.login(username='john', password='password') + # content = {'example': 'example'} + + # response = self.client.post('/', content) + # self.assertEqual(status.OK, response.status_code, "POST data is malformed") + + # response = self.csrf_client.post('/', content) + # self.assertEqual(status.OK, response.status_code, "POST data is malformed") -- cgit v1.2.3 From 8b72b7bf92ac6f0d021fcee5286505e75e075eff Mon Sep 17 00:00:00 2001 From: Sébastien Piquemal Date: Tue, 24 Jan 2012 19:16:41 +0200 Subject: corrected request example --- djangorestframework/tests/request.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'djangorestframework/tests') diff --git a/djangorestframework/tests/request.py b/djangorestframework/tests/request.py index 7f3a485e..6a0eae21 100644 --- a/djangorestframework/tests/request.py +++ b/djangorestframework/tests/request.py @@ -66,8 +66,6 @@ class TestMethodOverloading(RequestTestCase): class TestContentParsing(RequestTestCase): - #TODO: is there any reason why many test cases documented as testing a PUT, - # in fact use a POST !? def tearDown(self): request_class.parsers = () @@ -115,7 +113,7 @@ class TestContentParsing(RequestTestCase): content = 'qwerty' content_type = 'text/plain' request_class.parsers = (PlainTextParser,) - request = self.build_request('post', '/', content, content_type=content_type) + request = self.build_request('put', '/', content, content_type=content_type) self.assertEqual(request.DATA, content) def test_overloaded_behaviour_allows_content_tunnelling(self): -- cgit v1.2.3 From 5bb6301b7f53e3815ab1a81a5fa38721dc95b113 Mon Sep 17 00:00:00 2001 From: Sébastien Piquemal Date: Thu, 2 Feb 2012 18:19:44 +0200 Subject: Response as a subclass of HttpResponse - first draft, not quite there yet. --- djangorestframework/tests/accept.py | 13 +- djangorestframework/tests/authentication.py | 5 +- djangorestframework/tests/files.py | 9 +- djangorestframework/tests/mixins.py | 47 +++-- djangorestframework/tests/renderers.py | 193 ++----------------- djangorestframework/tests/request.py | 6 +- djangorestframework/tests/response.py | 281 ++++++++++++++++++++++++++-- djangorestframework/tests/reverse.py | 3 +- djangorestframework/tests/throttling.py | 3 +- djangorestframework/tests/validators.py | 20 +- 10 files changed, 335 insertions(+), 245 deletions(-) (limited to 'djangorestframework/tests') 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.+)$', 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('')) 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.+)$', 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') -- cgit v1.2.3 From ca96b4523b4c09489e4bfe726a894a5c6ada78aa Mon Sep 17 00:00:00 2001 From: Sébastien Piquemal Date: Tue, 7 Feb 2012 13:15:30 +0200 Subject: cleaned a bit Response/ResponseMixin code, added some documentation + renamed ErrorResponse to ImmediateResponse --- djangorestframework/tests/accept.py | 3 +- djangorestframework/tests/mixins.py | 4 +- djangorestframework/tests/renderers.py | 4 +- djangorestframework/tests/response.py | 71 +++++++++++++++++++++------------ djangorestframework/tests/validators.py | 22 +++++----- 5 files changed, 62 insertions(+), 42 deletions(-) (limited to 'djangorestframework/tests') diff --git a/djangorestframework/tests/accept.py b/djangorestframework/tests/accept.py index 2a02e04d..e7dfc303 100644 --- a/djangorestframework/tests/accept.py +++ b/djangorestframework/tests/accept.py @@ -23,9 +23,10 @@ class UserAgentMungingTest(TestCase): class MockView(View): permissions = () + response_class = Response def get(self, request): - return Response({'a':1, 'b':2, 'c':3}) + return self.response_class({'a':1, 'b':2, 'c':3}) self.req = RequestFactory() self.MockView = MockView diff --git a/djangorestframework/tests/mixins.py b/djangorestframework/tests/mixins.py index 7a1d2769..187ce719 100644 --- a/djangorestframework/tests/mixins.py +++ b/djangorestframework/tests/mixins.py @@ -6,7 +6,7 @@ from djangorestframework.compat import RequestFactory from django.contrib.auth.models import Group, User from djangorestframework.mixins import CreateModelMixin, PaginatorMixin, ReadModelMixin from djangorestframework.resources import ModelResource -from djangorestframework.response import Response, ErrorResponse +from djangorestframework.response import Response, ImmediateResponse from djangorestframework.tests.models import CustomUser from djangorestframework.tests.testcases import TestModelsTestCase from djangorestframework.views import View @@ -41,7 +41,7 @@ class TestModelRead(TestModelsTestCase): mixin = ReadModelMixin() mixin.resource = GroupResource - self.assertRaises(ErrorResponse, mixin.get, request, id=12345) + self.assertRaises(ImmediateResponse, mixin.get, request, id=12345) class TestModelCreation(TestModelsTestCase): diff --git a/djangorestframework/tests/renderers.py b/djangorestframework/tests/renderers.py index 461bc877..cc211dce 100644 --- a/djangorestframework/tests/renderers.py +++ b/djangorestframework/tests/renderers.py @@ -73,8 +73,8 @@ class MockGETView(View): urlpatterns = patterns('', - url(r'^jsonp/jsonrenderer$', MockGETView.as_view(renderers=[JSONRenderer, JSONPRenderer])), - url(r'^jsonp/nojsonrenderer$', MockGETView.as_view(renderers=[JSONPRenderer])), + url(r'^jsonp/jsonrenderer$', MockGETView.as_view(renderer_classes=[JSONRenderer, JSONPRenderer])), + url(r'^jsonp/nojsonrenderer$', MockGETView.as_view(renderer_classes=[JSONPRenderer])), ) diff --git a/djangorestframework/tests/response.py b/djangorestframework/tests/response.py index 5a01e356..b8cc5c1b 100644 --- a/djangorestframework/tests/response.py +++ b/djangorestframework/tests/response.py @@ -1,9 +1,10 @@ import json +import unittest from django.conf.urls.defaults import patterns, url from django.test import TestCase -from djangorestframework.response import Response, ErrorResponse +from djangorestframework.response import Response, ImmediateResponse from djangorestframework.mixins import ResponseMixin from djangorestframework.views import View from djangorestframework.compat import View as DjangoView @@ -17,13 +18,16 @@ from djangorestframework.renderers import BaseRenderer, JSONRenderer, YAMLRender class TestResponseDetermineRenderer(TestCase): def get_response(self, url='', accept_list=[], renderers=[]): - request = RequestFactory().get(url, HTTP_ACCEPT=','.join(accept_list)) + kwargs = {} + if accept_list is not None: + kwargs['HTTP_ACCEPT'] = HTTP_ACCEPT=','.join(accept_list) + request = RequestFactory().get(url, **kwargs) 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): """ @@ -32,6 +36,13 @@ class TestResponseDetermineRenderer(TestCase): 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_default(self): + """ + Test that determine_accept_list takes the default renderer if Accept is not specified. + """ + response = self.get_response(accept_list=None) + self.assertEqual(response._determine_accept_list(), ['*/*']) def test_determine_accept_list_overriden_header(self): """ @@ -47,38 +58,46 @@ class TestResponseDetermineRenderer(TestCase): 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') + 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) + response = self.get_response(accept_list=accept_list, renderers=(prenderer, jrenderer)) renderer, media_type = response._determine_renderer() self.assertEqual(media_type, 'application/pickle') - self.assertTrue(isinstance(renderer, PRenderer)) + self.assertTrue(renderer, prenderer) - renderers = (JRenderer,) - response = self.get_response(accept_list=accept_list, renderers=renderers) + response = self.get_response(accept_list=accept_list, renderers=(jrenderer,)) renderer, media_type = response._determine_renderer() self.assertEqual(media_type, 'application/json') - self.assertTrue(isinstance(renderer, JRenderer)) + self.assertTrue(renderer, jrenderer) + + def test_determine_renderer_default(self): + """ + Test determine renderer when Accept was not specified. + """ + prenderer = self.get_renderer_mock('application/pickle') + + response = self.get_response(accept_list=None, renderers=(prenderer,)) + renderer, media_type = response._determine_renderer() + self.assertEqual(media_type, '*/*') + self.assertTrue(renderer, prenderer) 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') + 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) + response = self.get_response(accept_list=accept_list, renderers=(prenderer,)) + self.assertRaises(ImmediateResponse, 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) + return Response(request=request, content=content, renderers=[r() for r in DEFAULT_RENDERERS]) def test_render(self): """ @@ -116,7 +135,7 @@ class RendererB(BaseRenderer): class MockView(ResponseMixin, DjangoView): - renderers = (RendererA, RendererB) + renderer_classes = (RendererA, RendererB) def get(self, request, **kwargs): response = Response(DUMMYCONTENT, status=DUMMYSTATUS) @@ -124,22 +143,22 @@ class MockView(ResponseMixin, DjangoView): class HTMLView(View): - renderers = (DocumentingHTMLRenderer, ) + renderer_classes = (DocumentingHTMLRenderer, ) def get(self, request, **kwargs): return Response('text') class HTMLView1(View): - renderers = (DocumentingHTMLRenderer, JSONRenderer) + renderer_classes = (DocumentingHTMLRenderer, JSONRenderer) def get(self, request, **kwargs): return Response('text') urlpatterns = patterns('', - url(r'^.*\.(?P.+)$', MockView.as_view(renderers=[RendererA, RendererB])), - url(r'^$', MockView.as_view(renderers=[RendererA, RendererB])), + url(r'^.*\.(?P.+)$', MockView.as_view(renderer_classes=[RendererA, RendererB])), + url(r'^$', MockView.as_view(renderer_classes=[RendererA, RendererB])), url(r'^html$', HTMLView.as_view()), url(r'^html1$', HTMLView1.as_view()), ) @@ -197,11 +216,11 @@ class RendererIntegrationTests(TestCase): 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) + @unittest.skip('can\'t pass because view is a simple Django view and response is an ImmediateResponse') + 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 diff --git a/djangorestframework/tests/validators.py b/djangorestframework/tests/validators.py index 1f384b4c..771b3125 100644 --- a/djangorestframework/tests/validators.py +++ b/djangorestframework/tests/validators.py @@ -2,7 +2,7 @@ from django import forms from django.db import models from django.test import TestCase from djangorestframework.resources import FormResource, ModelResource -from djangorestframework.response import ErrorResponse +from djangorestframework.response import ImmediateResponse from djangorestframework.views import View @@ -81,10 +81,10 @@ class TestNonFieldErrors(TestCase): content = {'field1': 'example1', 'field2': 'example2'} try: MockResource(view).validate_request(content, None) - except ErrorResponse, response: + except ImmediateResponse, response: self.assertEqual(response.raw_content, {'errors': [MockForm.ERROR_TEXT]}) else: - self.fail('ErrorResponse was not raised') + self.fail('ImmediateResponse was not raised') class TestFormValidation(TestCase): @@ -120,14 +120,14 @@ class TestFormValidation(TestCase): def validation_failure_raises_response_exception(self, validator): """If form validation fails a ResourceException 400 (Bad Request) should be raised.""" content = {} - self.assertRaises(ErrorResponse, validator.validate_request, content, None) + self.assertRaises(ImmediateResponse, validator.validate_request, content, None) def validation_does_not_allow_extra_fields_by_default(self, validator): """If some (otherwise valid) content includes fields that are not in the form then validation should fail. It might be okay on normal form submission, but for Web APIs we oughta get strict, as it'll help show up broken clients more easily (eg submitting content with a misnamed field)""" content = {'qwerty': 'uiop', 'extra': 'extra'} - self.assertRaises(ErrorResponse, validator.validate_request, content, None) + self.assertRaises(ImmediateResponse, validator.validate_request, content, None) def validation_allows_extra_fields_if_explicitly_set(self, validator): """If we include an allowed_extra_fields paramater on _validate, then allow fields with those names.""" @@ -154,7 +154,7 @@ class TestFormValidation(TestCase): content = {} try: validator.validate_request(content, None) - except ErrorResponse, response: + except ImmediateResponse, response: self.assertEqual(response.raw_content, {'field_errors': {'qwerty': ['This field is required.']}}) else: self.fail('ResourceException was not raised') @@ -164,7 +164,7 @@ class TestFormValidation(TestCase): content = {'qwerty': ''} try: validator.validate_request(content, None) - except ErrorResponse, response: + except ImmediateResponse, response: self.assertEqual(response.raw_content, {'field_errors': {'qwerty': ['This field is required.']}}) else: self.fail('ResourceException was not raised') @@ -174,7 +174,7 @@ class TestFormValidation(TestCase): content = {'qwerty': 'uiop', 'extra': 'extra'} try: validator.validate_request(content, None) - except ErrorResponse, response: + except ImmediateResponse, response: self.assertEqual(response.raw_content, {'field_errors': {'extra': ['This field does not exist.']}}) else: self.fail('ResourceException was not raised') @@ -184,7 +184,7 @@ class TestFormValidation(TestCase): content = {'qwerty': '', 'extra': 'extra'} try: validator.validate_request(content, None) - except ErrorResponse, response: + except ImmediateResponse, response: self.assertEqual(response.raw_content, {'field_errors': {'qwerty': ['This field is required.'], 'extra': ['This field does not exist.']}}) else: @@ -307,14 +307,14 @@ class TestModelFormValidator(TestCase): It might be okay on normal form submission, but for Web APIs we oughta get strict, as it'll help show up broken clients more easily (eg submitting content with a misnamed field)""" content = {'qwerty': 'example', 'uiop': 'example', 'readonly': 'read only', 'extra': 'extra'} - self.assertRaises(ErrorResponse, self.validator.validate_request, content, None) + self.assertRaises(ImmediateResponse, self.validator.validate_request, content, None) def test_validate_requires_fields_on_model_forms(self): """If some (otherwise valid) content includes fields that are not in the form then validation should fail. It might be okay on normal form submission, but for Web APIs we oughta get strict, as it'll help show up broken clients more easily (eg submitting content with a misnamed field)""" content = {'readonly': 'read only'} - self.assertRaises(ErrorResponse, self.validator.validate_request, content, None) + self.assertRaises(ImmediateResponse, self.validator.validate_request, content, None) def test_validate_does_not_require_blankable_fields_on_model_forms(self): """Test standard ModelForm validation behaviour - fields with blank=True are not required.""" -- cgit v1.2.3 From 21292d31e7ad5ec731c9ef3e471f90cb29054686 Mon Sep 17 00:00:00 2001 From: Sébastien Piquemal Date: Tue, 7 Feb 2012 15:38:54 +0200 Subject: cleaned Request/Response/mixins to have similar interface --- djangorestframework/tests/request.py | 108 +++++++++++++++++------------------ 1 file changed, 54 insertions(+), 54 deletions(-) (limited to 'djangorestframework/tests') diff --git a/djangorestframework/tests/request.py b/djangorestframework/tests/request.py index 77a34033..c92d3f5f 100644 --- a/djangorestframework/tests/request.py +++ b/djangorestframework/tests/request.py @@ -10,36 +10,19 @@ from djangorestframework.compat import RequestFactory from djangorestframework.mixins import RequestMixin from djangorestframework.parsers import FormParser, MultiPartParser, \ PlainTextParser, JSONParser +from djangorestframework.request import Request from djangorestframework.response import Response from djangorestframework.request import Request from djangorestframework.views import View -from djangorestframework.request import request_class_factory - -class MockView(View): - authentication = (UserLoggedInAuthentication,) - def post(self, request): - if request.POST.get('example') is not None: - return Response(status=status.HTTP_200_OK) - - return Response(status=status.INTERNAL_SERVER_ERROR) - -urlpatterns = patterns('', - (r'^$', MockView.as_view()), -) - -request_class = request_class_factory(RequestFactory().get('/')) class RequestTestCase(TestCase): - def tearDown(self): - request_class.parsers = () - def build_request(self, method, *args, **kwargs): factory = RequestFactory() method = getattr(factory, method) original_request = method(*args, **kwargs) - return request_class(original_request) + return Request(original_request) class TestMethodOverloading(RequestTestCase): @@ -67,14 +50,22 @@ class TestMethodOverloading(RequestTestCase): class TestContentParsing(RequestTestCase): - def tearDown(self): - request_class.parsers = () - def build_request(self, method, *args, **kwargs): factory = RequestFactory() + parsers = kwargs.pop('parsers', None) method = getattr(factory, method) original_request = method(*args, **kwargs) - return request_class(original_request) + rkwargs = {} + if parsers is not None: + rkwargs['parsers'] = parsers + request = Request(original_request, **rkwargs) + # TODO: Just a hack because the parsers need a view. This will be fixed in the future + class Obj(object): pass + obj = Obj() + obj.request = request + for p in request.parsers: + p.view = obj + return request def test_standard_behaviour_determines_no_content_GET(self): """Ensure request.DATA returns None for GET request with no content.""" @@ -89,31 +80,35 @@ class TestContentParsing(RequestTestCase): def test_standard_behaviour_determines_form_content_POST(self): """Ensure request.DATA returns content for POST request with form content.""" form_data = {'qwerty': 'uiop'} - request_class.parsers = (FormParser, MultiPartParser) - request = self.build_request('post', '/', data=form_data) + parsers = (FormParser(), MultiPartParser()) + + request = self.build_request('post', '/', data=form_data, parsers=parsers) self.assertEqual(request.DATA.items(), form_data.items()) def test_standard_behaviour_determines_non_form_content_POST(self): """Ensure request.DATA returns content for POST request with non-form content.""" content = 'qwerty' content_type = 'text/plain' - request_class.parsers = (PlainTextParser,) - request = self.build_request('post', '/', content, content_type=content_type) + parsers = (PlainTextParser(),) + + request = self.build_request('post', '/', content, content_type=content_type, parsers=parsers) self.assertEqual(request.DATA, content) def test_standard_behaviour_determines_form_content_PUT(self): """Ensure request.DATA returns content for PUT request with form content.""" form_data = {'qwerty': 'uiop'} - request_class.parsers = (FormParser, MultiPartParser) - request = self.build_request('put', '/', data=form_data) + parsers = (FormParser(), MultiPartParser()) + + request = self.build_request('put', '/', data=form_data, parsers=parsers) self.assertEqual(request.DATA.items(), form_data.items()) def test_standard_behaviour_determines_non_form_content_PUT(self): """Ensure request.DATA returns content for PUT request with non-form content.""" content = 'qwerty' content_type = 'text/plain' - request_class.parsers = (PlainTextParser,) - request = self.build_request('put', '/', content, content_type=content_type) + parsers = (PlainTextParser(),) + + request = self.build_request('put', '/', content, content_type=content_type, parsers=parsers) self.assertEqual(request.DATA, content) def test_overloaded_behaviour_allows_content_tunnelling(self): @@ -122,16 +117,17 @@ class TestContentParsing(RequestTestCase): content_type = 'text/plain' form_data = {Request._CONTENT_PARAM: content, Request._CONTENTTYPE_PARAM: content_type} - request_class.parsers = (PlainTextParser,) - request = self.build_request('post', '/', form_data) + parsers = (PlainTextParser(),) + + request = self.build_request('post', '/', form_data, parsers=parsers) self.assertEqual(request.DATA, content) def test_accessing_post_after_data_form(self): """Ensures request.POST can be accessed after request.DATA in form request""" form_data = {'qwerty': 'uiop'} - request_class.parsers = (FormParser, MultiPartParser) - request = self.build_request('post', '/', data=form_data) + parsers = (FormParser(), MultiPartParser()) + request = self.build_request('post', '/', data=form_data) self.assertEqual(request.DATA.items(), form_data.items()) self.assertEqual(request.POST.items(), form_data.items()) @@ -142,11 +138,9 @@ class TestContentParsing(RequestTestCase): data = {'qwerty': 'uiop'} content = json.dumps(data) content_type = 'application/json' + parsers = (JSONParser(),) - request_class.parsers = (JSONParser,) - - request = self.build_request('post', '/', content, content_type=content_type) - + request = self.build_request('post', '/', content, content_type=content_type, parsers=parsers) self.assertEqual(request.DATA.items(), data.items()) self.assertEqual(request.POST.items(), []) @@ -157,22 +151,19 @@ class TestContentParsing(RequestTestCase): data = {'qwerty': 'uiop'} content = json.dumps(data) content_type = 'application/json' - - request_class.parsers = (JSONParser,) - + parsers = (JSONParser(),) form_data = {Request._CONTENT_PARAM: content, Request._CONTENTTYPE_PARAM: content_type} - request = self.build_request('post', '/', data=form_data) - + request = self.build_request('post', '/', data=form_data, parsers=parsers) self.assertEqual(request.DATA.items(), data.items()) self.assertEqual(request.POST.items(), form_data.items()) def test_accessing_data_after_post_form(self): """Ensures request.DATA can be accessed after request.POST in form request""" form_data = {'qwerty': 'uiop'} - request_class.parsers = (FormParser, MultiPartParser) - request = self.build_request('post', '/', data=form_data) + parsers = (FormParser, MultiPartParser) + request = self.build_request('post', '/', data=form_data, parsers=parsers) self.assertEqual(request.POST.items(), form_data.items()) self.assertEqual(request.DATA.items(), form_data.items()) @@ -184,11 +175,9 @@ class TestContentParsing(RequestTestCase): data = {'qwerty': 'uiop'} content = json.dumps(data) content_type = 'application/json' + parsers = (JSONParser(),) - request_class.parsers = (JSONParser,) - - request = self.build_request('post', '/', content, content_type=content_type) - + request = self.build_request('post', '/', content, content_type=content_type, parsers=parsers) post_items = request.POST.items() self.assertEqual(len(post_items), 1) @@ -203,17 +192,28 @@ class TestContentParsing(RequestTestCase): data = {'qwerty': 'uiop'} content = json.dumps(data) content_type = 'application/json' - - request_class.parsers = (JSONParser,) - + parsers = (JSONParser(),) form_data = {Request._CONTENT_PARAM: content, Request._CONTENTTYPE_PARAM: content_type} - request = self.build_request('post', '/', data=form_data) + request = self.build_request('post', '/', data=form_data, parsers=parsers) self.assertEqual(request.POST.items(), form_data.items()) self.assertEqual(request.DATA.items(), data.items()) +class MockView(View): + authentication = (UserLoggedInAuthentication,) + def post(self, request): + if request.POST.get('example') is not None: + return Response(status=status.HTTP_200_OK) + + return Response(status=status.INTERNAL_SERVER_ERROR) + +urlpatterns = patterns('', + (r'^$', MockView.as_view()), +) + + class TestContentParsingWithAuthentication(TestCase): urls = 'djangorestframework.tests.request' -- cgit v1.2.3 From b33579a7a18c2cbc6e3789d4a7dc78c82fb0fe80 Mon Sep 17 00:00:00 2001 From: Sébastien Piquemal Date: Fri, 10 Feb 2012 11:05:20 +0200 Subject: attempt at fixing the examples --- djangorestframework/tests/mixins.py | 2 +- djangorestframework/tests/response.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'djangorestframework/tests') diff --git a/djangorestframework/tests/mixins.py b/djangorestframework/tests/mixins.py index 187ce719..3f5835aa 100644 --- a/djangorestframework/tests/mixins.py +++ b/djangorestframework/tests/mixins.py @@ -31,7 +31,7 @@ class TestModelRead(TestModelsTestCase): mixin.resource = GroupResource response = mixin.get(request, id=group.id) - self.assertEquals(group.name, response.name) + self.assertEquals(group.name, response.raw_content.name) def test_read_404(self): class GroupResource(ModelResource): diff --git a/djangorestframework/tests/response.py b/djangorestframework/tests/response.py index b8cc5c1b..95603680 100644 --- a/djangorestframework/tests/response.py +++ b/djangorestframework/tests/response.py @@ -139,7 +139,8 @@ class MockView(ResponseMixin, DjangoView): def get(self, request, **kwargs): response = Response(DUMMYCONTENT, status=DUMMYSTATUS) - return self.prepare_response(response) + self.response = self.prepare_response(response) + return self.response class HTMLView(View): -- cgit v1.2.3