diff options
Diffstat (limited to 'djangorestframework/tests')
| -rw-r--r-- | djangorestframework/tests/content.py | 110 | ||||
| -rw-r--r-- | djangorestframework/tests/mixins.py | 162 | ||||
| -rw-r--r-- | djangorestframework/tests/renderers.py | 3 | ||||
| -rw-r--r-- | djangorestframework/tests/views.py | 96 |
4 files changed, 294 insertions, 77 deletions
diff --git a/djangorestframework/tests/content.py b/djangorestframework/tests/content.py index 0764d12b..048586c8 100644 --- a/djangorestframework/tests/content.py +++ b/djangorestframework/tests/content.py @@ -18,7 +18,7 @@ class MockView(View): def post(self, request): if request.POST.get('example') is not None: return Response(status.OK) - + return Response(status.INTERNAL_SERVER_ERROR) urlpatterns = patterns('', @@ -103,104 +103,104 @@ class TestContentParsing(TestCase): 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()) - - 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_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' @@ -208,25 +208,25 @@ class TestContentParsingWithAuthentication(TestCase): 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.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") - - 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") + + # 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/mixins.py b/djangorestframework/tests/mixins.py index da7c4d86..65cf4a45 100644 --- a/djangorestframework/tests/mixins.py +++ b/djangorestframework/tests/mixins.py @@ -1,14 +1,17 @@ -"""Tests for the status module""" +"""Tests for the mixin module""" from django.test import TestCase +from django.utils import simplejson as json from djangorestframework import status from djangorestframework.compat import RequestFactory from django.contrib.auth.models import Group, User -from djangorestframework.mixins import CreateModelMixin +from djangorestframework.mixins import CreateModelMixin, PaginatorMixin from djangorestframework.resources import ModelResource +from djangorestframework.response import Response from djangorestframework.tests.models import CustomUser +from djangorestframework.views import View -class TestModelCreation(TestCase): +class TestModelCreation(TestCase): """Tests on CreateModelMixin""" def setUp(self): @@ -25,23 +28,26 @@ class TestModelCreation(TestCase): mixin = CreateModelMixin() mixin.resource = GroupResource mixin.CONTENT = form_data - + response = mixin.post(request) self.assertEquals(1, Group.objects.count()) self.assertEquals('foo', response.cleaned_content.name) - def test_creation_with_m2m_relation(self): class UserResource(ModelResource): model = User - + def url(self, instance): return "/users/%i" % instance.id group = Group(name='foo') group.save() - form_data = {'username': 'bar', 'password': 'baz', 'groups': [group.id]} + form_data = { + 'username': 'bar', + 'password': 'baz', + 'groups': [group.id] + } request = self.req.post('/groups', data=form_data) cleaned_data = dict(form_data) cleaned_data['groups'] = [group] @@ -53,18 +59,18 @@ class TestModelCreation(TestCase): self.assertEquals(1, User.objects.count()) self.assertEquals(1, response.cleaned_content.groups.count()) self.assertEquals('foo', response.cleaned_content.groups.all()[0].name) - + def test_creation_with_m2m_relation_through(self): """ Tests creation where the m2m relation uses a through table """ class UserResource(ModelResource): model = CustomUser - + def url(self, instance): return "/customusers/%i" % instance.id - - form_data = {'username': 'bar0', 'groups': []} + + form_data = {'username': 'bar0', 'groups': []} request = self.req.post('/groups', data=form_data) cleaned_data = dict(form_data) cleaned_data['groups'] = [] @@ -74,12 +80,12 @@ class TestModelCreation(TestCase): response = mixin.post(request) self.assertEquals(1, CustomUser.objects.count()) - self.assertEquals(0, response.cleaned_content.groups.count()) + self.assertEquals(0, response.cleaned_content.groups.count()) group = Group(name='foo1') group.save() - form_data = {'username': 'bar1', 'groups': [group.id]} + form_data = {'username': 'bar1', 'groups': [group.id]} request = self.req.post('/groups', data=form_data) cleaned_data = dict(form_data) cleaned_data['groups'] = [group] @@ -91,12 +97,11 @@ class TestModelCreation(TestCase): self.assertEquals(2, CustomUser.objects.count()) self.assertEquals(1, response.cleaned_content.groups.count()) self.assertEquals('foo1', response.cleaned_content.groups.all()[0].name) - - + group2 = Group(name='foo2') - group2.save() - - form_data = {'username': 'bar2', 'groups': [group.id, group2.id]} + group2.save() + + form_data = {'username': 'bar2', 'groups': [group.id, group2.id]} request = self.req.post('/groups', data=form_data) cleaned_data = dict(form_data) cleaned_data['groups'] = [group, group2] @@ -109,5 +114,124 @@ class TestModelCreation(TestCase): 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) - + +class MockPaginatorView(PaginatorMixin, View): + total = 60 + + def get(self, request): + return range(0, self.total) + + def post(self, request): + return Response(status.CREATED, {'status': 'OK'}) + + +class TestPagination(TestCase): + def setUp(self): + self.req = RequestFactory() + + def test_default_limit(self): + """ Tests if pagination works without overwriting the limit """ + request = self.req.get('/paginator') + response = MockPaginatorView.as_view()(request) + + content = json.loads(response.content) + + self.assertEqual(response.status_code, status.OK) + self.assertEqual(MockPaginatorView.total, content['total']) + self.assertEqual(MockPaginatorView.limit, content['per_page']) + + self.assertEqual(range(0, MockPaginatorView.limit), content['results']) + + def test_overwriting_limit(self): + """ Tests if the limit can be overwritten """ + limit = 10 + + request = self.req.get('/paginator') + response = MockPaginatorView.as_view(limit=limit)(request) + + content = json.loads(response.content) + + self.assertEqual(response.status_code, status.OK) + self.assertEqual(content['per_page'], limit) + + self.assertEqual(range(0, limit), content['results']) + + def test_limit_param(self): + """ Tests if the client can set the limit """ + from math import ceil + + limit = 5 + num_pages = int(ceil(MockPaginatorView.total / float(limit))) + + request = self.req.get('/paginator/?limit=%d' % limit) + response = MockPaginatorView.as_view()(request) + + content = json.loads(response.content) + + self.assertEqual(response.status_code, status.OK) + self.assertEqual(MockPaginatorView.total, content['total']) + self.assertEqual(limit, content['per_page']) + self.assertEqual(num_pages, content['pages']) + + def test_exceeding_limit(self): + """ Makes sure the client cannot exceed the default limit """ + from math import ceil + + limit = MockPaginatorView.limit + 10 + num_pages = int(ceil(MockPaginatorView.total / float(limit))) + + request = self.req.get('/paginator/?limit=%d' % limit) + response = MockPaginatorView.as_view()(request) + + content = json.loads(response.content) + + self.assertEqual(response.status_code, status.OK) + self.assertEqual(MockPaginatorView.total, content['total']) + self.assertNotEqual(limit, content['per_page']) + self.assertNotEqual(num_pages, content['pages']) + self.assertEqual(MockPaginatorView.limit, content['per_page']) + + def test_only_works_for_get(self): + """ 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) + + self.assertEqual(response.status_code, status.CREATED) + self.assertEqual(None, content.get('per_page')) + self.assertEqual('OK', content['status']) + + def test_non_int_page(self): + """ Tests that it can handle invalid values """ + request = self.req.get('/paginator/?page=spam') + response = MockPaginatorView.as_view()(request) + + self.assertEqual(response.status_code, status.NOT_FOUND) + + def test_page_range(self): + """ 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) + self.assertEqual(response.status_code, status.NOT_FOUND) + + request = self.req.get('/paginator/') + response = MockPaginatorView.as_view()(request) + content = json.loads(response.content) + self.assertEqual(response.status_code, status.OK) + self.assertEqual(range(0, MockPaginatorView.limit), content['results']) + + num_pages = content['pages'] + + request = self.req.get('/paginator/?page=%d' % num_pages) + response = MockPaginatorView.as_view()(request) + content = json.loads(response.content) + self.assertEqual(response.status_code, status.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) + self.assertEqual(response.status_code, status.NOT_FOUND) diff --git a/djangorestframework/tests/renderers.py b/djangorestframework/tests/renderers.py index 5b2d3556..d6a49984 100644 --- a/djangorestframework/tests/renderers.py +++ b/djangorestframework/tests/renderers.py @@ -228,6 +228,7 @@ if YAMLRenderer: (data, files) = parser.parse(StringIO(content)) self.assertEquals(obj, data) + class XMLRendererTestCase(TestCase): """ @@ -288,4 +289,4 @@ class XMLRendererTestCase(TestCase): def assertXMLContains(self, xml, string): self.assertTrue(xml.startswith('<?xml version="1.0" encoding="utf-8"?>\n<root>')) self.assertTrue(xml.endswith('</root>')) - self.assertTrue(string in xml, '%r not in %r' % (string, xml))
\ No newline at end of file + self.assertTrue(string in xml, '%r not in %r' % (string, xml)) diff --git a/djangorestframework/tests/views.py b/djangorestframework/tests/views.py index 598712d2..b0f9d6d4 100644 --- a/djangorestframework/tests/views.py +++ b/djangorestframework/tests/views.py @@ -1,17 +1,109 @@ from django.conf.urls.defaults import patterns, url from django.test import TestCase from django.test import Client +from django import forms +from django.db import models +from djangorestframework.views import View +from djangorestframework.parsers import JSONParser +from djangorestframework.resources import ModelResource +from djangorestframework.views import ListOrCreateModelView, InstanceModelView + +from StringIO import StringIO + + +class MockView(View): + """This is a basic mock view""" + pass + +class ResourceMockView(View): + """This is a resource-based mock view""" + + class MockForm(forms.Form): + foo = forms.BooleanField(required=False) + bar = forms.IntegerField(help_text='Must be an integer.') + baz = forms.CharField(max_length=32) + + form = MockForm + +class MockResource(ModelResource): + """This is a mock model-based resource""" + + class MockResourceModel(models.Model): + foo = models.BooleanField() + bar = models.IntegerField(help_text='Must be an integer.') + baz = models.CharField(max_length=32, help_text='Free text. Max length 32 chars.') + + model = MockResourceModel + fields = ('foo', 'bar', 'baz') urlpatterns = patterns('djangorestframework.utils.staticviews', url(r'^robots.txt$', 'deny_robots'), url(r'^favicon.ico$', 'favicon'), url(r'^accounts/login$', 'api_login'), url(r'^accounts/logout$', 'api_logout'), + url(r'^mock/$', MockView.as_view()), + url(r'^resourcemock/$', ResourceMockView.as_view()), + url(r'^model/$', ListOrCreateModelView.as_view(resource=MockResource)), + url(r'^model/(?P<pk>[^/]+)/$', InstanceModelView.as_view(resource=MockResource)), ) +class BaseViewTests(TestCase): + """Test the base view class of djangorestframework""" + urls = 'djangorestframework.tests.views' + + def test_options_method_simple_view(self): + response = self.client.options('/mock/') + self._verify_options_response(response, + name='Mock', + description='This is a basic mock view') + + def test_options_method_resource_view(self): + response = self.client.options('/resourcemock/') + self._verify_options_response(response, + name='Resource Mock', + description='This is a resource-based mock view', + fields={'foo':'BooleanField', + 'bar':'IntegerField', + 'baz':'CharField', + }) + + def test_options_method_model_resource_list_view(self): + response = self.client.options('/model/') + self._verify_options_response(response, + name='Mock List', + description='This is a mock model-based resource', + fields={'foo':'BooleanField', + 'bar':'IntegerField', + 'baz':'CharField', + }) + + def test_options_method_model_resource_detail_view(self): + response = self.client.options('/model/0/') + self._verify_options_response(response, + name='Mock Instance', + description='This is a mock model-based resource', + fields={'foo':'BooleanField', + 'bar':'IntegerField', + 'baz':'CharField', + }) + + def _verify_options_response(self, response, name, description, fields=None, status=200, + mime_type='application/json'): + self.assertEqual(response.status_code, status) + self.assertEqual(response['Content-Type'].split(';')[0], mime_type) + parser = JSONParser(None) + (data, files) = parser.parse(StringIO(response.content)) + self.assertTrue('application/json' in data['renders']) + self.assertEqual(name, data['name']) + self.assertEqual(description, data['description']) + if fields is None: + self.assertFalse(hasattr(data, 'fields')) + else: + self.assertEqual(data['fields'], fields) -class ViewTests(TestCase): + +class ExtraViewsTests(TestCase): """Test the extra views djangorestframework provides""" urls = 'djangorestframework.tests.views' @@ -39,5 +131,5 @@ class ViewTests(TestCase): self.assertEqual(response.status_code, 200) self.assertEqual(response['Content-Type'].split(';')[0], 'text/html') - # TODO: Add login/logout behaviour tests + |
