aboutsummaryrefslogtreecommitdiffstats
path: root/djangorestframework/tests
diff options
context:
space:
mode:
authorCraig Blaszczyk2011-12-11 18:30:43 +0000
committerCraig Blaszczyk2011-12-11 18:30:43 +0000
commite84bf2140c33b45d1d9d8325eeaf62a97c46495e (patch)
treed95d6755f787c8ab3d8c555315d514c067121bf9 /djangorestframework/tests
parent0632e946f977609ca6d6f4272f02c72dee1f49be (diff)
parent4f42303035c094a1d0c6128f0ccce1abfa6b72f4 (diff)
downloaddjango-rest-framework-e84bf2140c33b45d1d9d8325eeaf62a97c46495e.tar.bz2
fix merge
Diffstat (limited to 'djangorestframework/tests')
-rw-r--r--djangorestframework/tests/content.py110
-rw-r--r--djangorestframework/tests/mixins.py162
-rw-r--r--djangorestframework/tests/renderers.py3
-rw-r--r--djangorestframework/tests/views.py96
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
+