diff options
Diffstat (limited to 'djangorestframework/tests')
23 files changed, 0 insertions, 2849 deletions
diff --git a/djangorestframework/tests/__init__.py b/djangorestframework/tests/__init__.py deleted file mode 100644 index f664c5c1..00000000 --- a/djangorestframework/tests/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Force import of all modules in this package in order to get the standard test runner to pick up the tests. Yowzers.""" -import os - -modules = [filename.rsplit('.', 1)[0] - for filename in os.listdir(os.path.dirname(__file__)) - if filename.endswith('.py') and not filename.startswith('_')] -__test__ = dict() - -for module in modules: - exec("from djangorestframework.tests.%s import __doc__ as module_doc" % module) - exec("from djangorestframework.tests.%s import *" % module) - __test__[module] = module_doc or "" - diff --git a/djangorestframework/tests/accept.py b/djangorestframework/tests/accept.py deleted file mode 100644 index 7f4eb320..00000000 --- a/djangorestframework/tests/accept.py +++ /dev/null @@ -1,86 +0,0 @@ -from django.conf.urls.defaults import patterns, url, include -from django.test import TestCase -from djangorestframework.compat import RequestFactory -from djangorestframework.views import View - - -# See: http://www.useragentstring.com/ -MSIE_9_USER_AGENT = 'Mozilla/5.0 (Windows; U; MSIE 9.0; WIndows NT 9.0; en-US))' -MSIE_8_USER_AGENT = 'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; Media Center PC 4.0; SLCC1; .NET CLR 3.0.04320)' -MSIE_7_USER_AGENT = 'Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)' -FIREFOX_4_0_USER_AGENT = 'Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.3) Gecko/20100401 Firefox/4.0 (.NET CLR 3.5.30729)' -CHROME_11_0_USER_AGENT = 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.17 (KHTML, like Gecko) Chrome/11.0.655.0 Safari/534.17' -SAFARI_5_0_USER_AGENT = 'Mozilla/5.0 (X11; U; Linux x86_64; en-ca) AppleWebKit/531.2+ (KHTML, like Gecko) Version/5.0 Safari/531.2+' -OPERA_11_0_MSIE_USER_AGENT = 'Mozilla/4.0 (compatible; MSIE 8.0; X11; Linux x86_64; pl) Opera 11.00' -OPERA_11_0_OPERA_USER_AGENT = 'Opera/9.80 (X11; Linux x86_64; U; pl) Presto/2.7.62 Version/11.00' - - -urlpatterns = patterns('', - url(r'^api', include('djangorestframework.urls', namespace='djangorestframework')) -) - - -class UserAgentMungingTest(TestCase): - """ - We need to fake up the accept headers when we deal with MSIE. Blergh. - http://www.gethifi.com/blog/browser-rest-http-accept-headers - """ - - urls = 'djangorestframework.tests.accept' - - def setUp(self): - - class MockView(View): - permissions = () - - def get(self, request): - return {'a':1, 'b':2, 'c':3} - - self.req = RequestFactory() - self.MockView = MockView - self.view = MockView.as_view() - - def test_munge_msie_accept_header(self): - """Send MSIE user agent strings and ensure that we get an HTML response, - even if we set a */* accept header.""" - 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 = self.view(req) - self.assertEqual(resp['Content-Type'], 'text/html') - - def test_dont_munge_msie_with_x_requested_with_header(self): - """Send MSIE user agent strings, and an X-Requested-With header, and - ensure that we get a JSON response if we set a */* Accept header.""" - 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, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - resp = self.view(req) - self.assertEqual(resp['Content-Type'], 'application/json') - - 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) - - 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) - self.assertEqual(resp['Content-Type'], 'application/json') - - def test_dont_munge_nice_browsers_accept_header(self): - """Send Non-MSIE user agent strings and ensure that we get a JSON response, - if we set a */* Accept header. (Other browsers will correctly set the Accept header)""" - for user_agent in (FIREFOX_4_0_USER_AGENT, - CHROME_11_0_USER_AGENT, - SAFARI_5_0_USER_AGENT, - OPERA_11_0_MSIE_USER_AGENT, - OPERA_11_0_OPERA_USER_AGENT): - req = self.req.get('/', HTTP_ACCEPT='*/*', HTTP_USER_AGENT=user_agent) - resp = self.view(req) - self.assertEqual(resp['Content-Type'], 'application/json') - diff --git a/djangorestframework/tests/authentication.py b/djangorestframework/tests/authentication.py deleted file mode 100644 index 3dac7ee3..00000000 --- a/djangorestframework/tests/authentication.py +++ /dev/null @@ -1,105 +0,0 @@ -from django.conf.urls.defaults import patterns -from django.contrib.auth.models import User -from django.test import Client, TestCase - -from django.utils import simplejson as json - -from djangorestframework.views import View -from djangorestframework import permissions - -import base64 - - -class MockView(View): - permissions = (permissions.IsAuthenticated,) - - def post(self, request): - return {'a': 1, 'b': 2, 'c': 3} - - def put(self, request): - return {'a': 1, 'b': 2, 'c': 3} - -urlpatterns = patterns('', - (r'^$', MockView.as_view()), -) - - -class BasicAuthTests(TestCase): - """Basic authentication""" - urls = 'djangorestframework.tests.authentication' - - 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) - - def test_post_form_passing_basic_auth(self): - """Ensure POSTing json over basic auth with correct credentials passes and does not require CSRF""" - auth = 'Basic %s' % base64.encodestring('%s:%s' % (self.username, self.password)).strip() - response = self.csrf_client.post('/', {'example': 'example'}, HTTP_AUTHORIZATION=auth) - self.assertEqual(response.status_code, 200) - - def test_post_json_passing_basic_auth(self): - """Ensure POSTing form over basic auth with correct credentials passes and does not require CSRF""" - auth = 'Basic %s' % base64.encodestring('%s:%s' % (self.username, self.password)).strip() - response = self.csrf_client.post('/', json.dumps({'example': 'example'}), 'application/json', HTTP_AUTHORIZATION=auth) - self.assertEqual(response.status_code, 200) - - def test_post_form_failing_basic_auth(self): - """Ensure POSTing form over basic auth without correct credentials fails""" - response = self.csrf_client.post('/', {'example': 'example'}) - self.assertEqual(response.status_code, 403) - - def test_post_json_failing_basic_auth(self): - """Ensure POSTing json over basic auth without correct credentials fails""" - response = self.csrf_client.post('/', json.dumps({'example': 'example'}), 'application/json') - self.assertEqual(response.status_code, 403) - - -class SessionAuthTests(TestCase): - """User session authentication""" - urls = 'djangorestframework.tests.authentication' - - def setUp(self): - self.csrf_client = Client(enforce_csrf_checks=True) - self.non_csrf_client = Client(enforce_csrf_checks=False) - self.username = 'john' - self.email = 'lennon@thebeatles.com' - self.password = 'password' - self.user = User.objects.create_user(self.username, self.email, self.password) - - def tearDown(self): - self.csrf_client.logout() - - def test_post_form_session_auth_failing_csrf(self): - """ - Ensure POSTing form over session authentication without CSRF token fails. - """ - self.csrf_client.login(username=self.username, password=self.password) - response = self.csrf_client.post('/', {'example': 'example'}) - self.assertEqual(response.status_code, 403) - - def test_post_form_session_auth_passing(self): - """ - Ensure POSTing form over session authentication with logged in user and CSRF token passes. - """ - self.non_csrf_client.login(username=self.username, password=self.password) - response = self.non_csrf_client.post('/', {'example': 'example'}) - self.assertEqual(response.status_code, 200) - - # def test_put_form_session_auth_passing(self): - # """ - # Ensure PUTting form over session authentication with logged in user and CSRF token passes. - # """ - # self.non_csrf_client.login(username=self.username, password=self.password) - # response = self.non_csrf_client.put('/', {'example': 'example'}) - # self.assertEqual(response.status_code, 200) - - def test_post_form_session_auth_failing(self): - """ - Ensure POSTing form over session authentication without logged in user fails. - """ - response = self.csrf_client.post('/', {'example': 'example'}) - self.assertEqual(response.status_code, 403) diff --git a/djangorestframework/tests/breadcrumbs.py b/djangorestframework/tests/breadcrumbs.py deleted file mode 100644 index d7473c6a..00000000 --- a/djangorestframework/tests/breadcrumbs.py +++ /dev/null @@ -1,67 +0,0 @@ -from django.conf.urls.defaults import patterns, url -from django.test import TestCase -from djangorestframework.utils.breadcrumbs import get_breadcrumbs -from djangorestframework.views import View - -class Root(View): - pass - -class ResourceRoot(View): - pass - -class ResourceInstance(View): - pass - -class NestedResourceRoot(View): - pass - -class NestedResourceInstance(View): - pass - -urlpatterns = patterns('', - url(r'^$', Root.as_view()), - url(r'^resource/$', ResourceRoot.as_view()), - url(r'^resource/(?P<key>[0-9]+)$', ResourceInstance.as_view()), - url(r'^resource/(?P<key>[0-9]+)/$', NestedResourceRoot.as_view()), - url(r'^resource/(?P<key>[0-9]+)/(?P<other>[A-Za-z]+)$', NestedResourceInstance.as_view()), -) - - -class BreadcrumbTests(TestCase): - """Tests the breadcrumb functionality used by the HTML renderer.""" - - urls = 'djangorestframework.tests.breadcrumbs' - - def test_root_breadcrumbs(self): - url = '/' - self.assertEqual(get_breadcrumbs(url), [('Root', '/')]) - - def test_resource_root_breadcrumbs(self): - url = '/resource/' - self.assertEqual(get_breadcrumbs(url), [('Root', '/'), - ('Resource Root', '/resource/')]) - - def test_resource_instance_breadcrumbs(self): - url = '/resource/123' - self.assertEqual(get_breadcrumbs(url), [('Root', '/'), - ('Resource Root', '/resource/'), - ('Resource Instance', '/resource/123')]) - - def test_nested_resource_breadcrumbs(self): - url = '/resource/123/' - self.assertEqual(get_breadcrumbs(url), [('Root', '/'), - ('Resource Root', '/resource/'), - ('Resource Instance', '/resource/123'), - ('Nested Resource Root', '/resource/123/')]) - - def test_nested_resource_instance_breadcrumbs(self): - url = '/resource/123/abc' - self.assertEqual(get_breadcrumbs(url), [('Root', '/'), - ('Resource Root', '/resource/'), - ('Resource Instance', '/resource/123'), - ('Nested Resource Root', '/resource/123/'), - ('Nested Resource Instance', '/resource/123/abc')]) - - def test_broken_url_breadcrumbs_handled_gracefully(self): - url = '/foobar' - self.assertEqual(get_breadcrumbs(url), [('Root', '/')]) diff --git a/djangorestframework/tests/content.py b/djangorestframework/tests/content.py deleted file mode 100644 index e5d98e32..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/description.py b/djangorestframework/tests/description.py deleted file mode 100644 index 212b4ca4..00000000 --- a/djangorestframework/tests/description.py +++ /dev/null @@ -1,111 +0,0 @@ -from django.test import TestCase -from djangorestframework.views import View -from djangorestframework.compat import apply_markdown - -# We check that docstrings get nicely un-indented. -DESCRIPTION = """an example docstring -==================== - -* list -* list - -another header --------------- - - code block - -indented - -# hash style header #""" - -# If markdown is installed we also test it's working -# (and that our wrapped forces '=' to h2 and '-' to h3) - -# We support markdown < 2.1 and markdown >= 2.1 -MARKED_DOWN_lt_21 = """<h2>an example docstring</h2> -<ul> -<li>list</li> -<li>list</li> -</ul> -<h3>another header</h3> -<pre><code>code block -</code></pre> -<p>indented</p> -<h2 id="hash_style_header">hash style header</h2>""" - -MARKED_DOWN_gte_21 = """<h2 id="an-example-docstring">an example docstring</h2> -<ul> -<li>list</li> -<li>list</li> -</ul> -<h3 id="another-header">another header</h3> -<pre><code>code block -</code></pre> -<p>indented</p> -<h2 id="hash-style-header">hash style header</h2>""" - - -class TestViewNamesAndDescriptions(TestCase): - def test_resource_name_uses_classname_by_default(self): - """Ensure Resource names are based on the classname by default.""" - class MockView(View): - pass - self.assertEquals(MockView().get_name(), 'Mock') - - def test_resource_name_can_be_set_explicitly(self): - """Ensure Resource names can be set using the 'get_name' method.""" - example = 'Some Other Name' - class MockView(View): - def get_name(self): - return example - self.assertEquals(MockView().get_name(), example) - - def test_resource_description_uses_docstring_by_default(self): - """Ensure Resource names are based on the docstring by default.""" - class MockView(View): - """an example docstring - ==================== - - * list - * list - - another header - -------------- - - code block - - indented - - # hash style header #""" - - self.assertEquals(MockView().get_description(), DESCRIPTION) - - def test_resource_description_can_be_set_explicitly(self): - """Ensure Resource descriptions can be set using the 'get_description' method.""" - example = 'Some other description' - class MockView(View): - """docstring""" - def get_description(self): - return example - self.assertEquals(MockView().get_description(), example) - - def test_resource_description_does_not_require_docstring(self): - """Ensure that empty docstrings do not affect the Resource's description if it has been set using the 'get_description' method.""" - example = 'Some other description' - class MockView(View): - def get_description(self): - return example - self.assertEquals(MockView().get_description(), example) - - def test_resource_description_can_be_empty(self): - """Ensure that if a resource has no doctring or 'description' class attribute, then it's description is the empty string.""" - class MockView(View): - pass - self.assertEquals(MockView().get_description(), '') - - def test_markdown(self): - """Ensure markdown to HTML works as expected""" - if apply_markdown: - gte_21_match = apply_markdown(DESCRIPTION) == MARKED_DOWN_gte_21 - lt_21_match = apply_markdown(DESCRIPTION) == MARKED_DOWN_lt_21 - self.assertTrue(gte_21_match or lt_21_match) diff --git a/djangorestframework/tests/files.py b/djangorestframework/tests/files.py deleted file mode 100644 index d3b1cc56..00000000 --- a/djangorestframework/tests/files.py +++ /dev/null @@ -1,32 +0,0 @@ -from django.test import TestCase -from django import forms -from djangorestframework.compat import RequestFactory -from djangorestframework.views import View -from djangorestframework.resources import FormResource -import StringIO - -class UploadFilesTests(TestCase): - """Check uploading of files""" - def setUp(self): - self.factory = RequestFactory() - - def test_upload_file(self): - - class FileForm(forms.Form): - file = forms.FileField() - - class MockView(View): - permissions = () - form = FileForm - - def post(self, request, *args, **kwargs): - return {'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"}') - diff --git a/djangorestframework/tests/methods.py b/djangorestframework/tests/methods.py deleted file mode 100644 index 4b90a21f..00000000 --- a/djangorestframework/tests/methods.py +++ /dev/null @@ -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/mixins.py b/djangorestframework/tests/mixins.py deleted file mode 100644 index 8268fdca..00000000 --- a/djangorestframework/tests/mixins.py +++ /dev/null @@ -1,291 +0,0 @@ -"""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, PaginatorMixin, ReadModelMixin -from djangorestframework.resources import ModelResource -from djangorestframework.response import Response, ErrorResponse -from djangorestframework.tests.models import CustomUser -from djangorestframework.tests.testcases import TestModelsTestCase -from djangorestframework.views import View - - -class TestModelRead(TestModelsTestCase): - """Tests on ReadModelMixin""" - - def setUp(self): - super(TestModelRead, self).setUp() - self.req = RequestFactory() - - def test_read(self): - Group.objects.create(name='other group') - group = Group.objects.create(name='my group') - - class GroupResource(ModelResource): - model = Group - - request = self.req.get('/groups') - mixin = ReadModelMixin() - mixin.resource = GroupResource - - response = mixin.get(request, id=group.id) - self.assertEquals(group.name, response.name) - - def test_read_404(self): - class GroupResource(ModelResource): - model = Group - - request = self.req.get('/groups') - mixin = ReadModelMixin() - mixin.resource = GroupResource - - self.assertRaises(ErrorResponse, mixin.get, request, id=12345) - - -class TestModelCreation(TestModelsTestCase): - """Tests on CreateModelMixin""" - - def setUp(self): - super(TestModelsTestCase, self).setUp() - self.req = RequestFactory() - - def test_creation(self): - self.assertEquals(0, Group.objects.count()) - - class GroupResource(ModelResource): - model = Group - - form_data = {'name': 'foo'} - request = self.req.post('/groups', data=form_data) - 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] - } - request = self.req.post('/groups', data=form_data) - cleaned_data = dict(form_data) - cleaned_data['groups'] = [group] - mixin = CreateModelMixin() - mixin.resource = UserResource - mixin.CONTENT = cleaned_data - - 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) - - 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': []} - request = self.req.post('/groups', data=form_data) - cleaned_data = dict(form_data) - cleaned_data['groups'] = [] - mixin = CreateModelMixin() - mixin.resource = UserResource - mixin.CONTENT = cleaned_data - - response = mixin.post(request) - self.assertEquals(1, CustomUser.objects.count()) - self.assertEquals(0, response.cleaned_content.groups.count()) - - group = Group(name='foo1') - group.save() - - form_data = {'username': 'bar1', 'groups': [group.id]} - request = self.req.post('/groups', data=form_data) - cleaned_data = dict(form_data) - cleaned_data['groups'] = [group] - mixin = CreateModelMixin() - mixin.resource = UserResource - mixin.CONTENT = cleaned_data - - 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) - - group2 = Group(name='foo2') - 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] - mixin = CreateModelMixin() - mixin.resource = UserResource - mixin.CONTENT = cleaned_data - - 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) - - -class MockPaginatorView(PaginatorMixin, View): - total = 60 - - def get(self, request): - return range(0, self.total) - - def post(self, request): - return Response(status.HTTP_201_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.HTTP_200_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.HTTP_200_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.HTTP_200_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.HTTP_200_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.HTTP_201_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.HTTP_404_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.HTTP_404_NOT_FOUND) - - request = self.req.get('/paginator/') - response = MockPaginatorView.as_view()(request) - content = json.loads(response.content) - self.assertEqual(response.status_code, status.HTTP_200_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.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) - self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) - - def test_existing_query_parameters_are_preserved(self): - """ Tests that existing query parameters are preserved when - generating next/previous page links """ - request = self.req.get('/paginator/?foo=bar&another=something') - response = MockPaginatorView.as_view()(request) - content = json.loads(response.content) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertTrue('foo=bar' in content['next']) - self.assertTrue('another=something' in content['next']) - self.assertTrue('page=2' in content['next']) - - def test_duplicate_parameters_are_not_created(self): - """ Regression: ensure duplicate "page" parameters are not added to - paginated URLs. So page 1 should contain ?page=2, not ?page=1&page=2 """ - request = self.req.get('/paginator/?page=1') - response = MockPaginatorView.as_view()(request) - content = json.loads(response.content) - self.assertTrue('page=2' in content['next']) - self.assertFalse('page=1' in content['next']) diff --git a/djangorestframework/tests/models.py b/djangorestframework/tests/models.py deleted file mode 100644 index 4cae68b6..00000000 --- a/djangorestframework/tests/models.py +++ /dev/null @@ -1,28 +0,0 @@ -from django.db import models -from django.contrib.auth.models import Group - -class CustomUser(models.Model): - """ - A custom user model, which uses a 'through' table for the foreign key - """ - username = models.CharField(max_length=255, unique=True) - groups = models.ManyToManyField( - to=Group, blank=True, null=True, through='UserGroupMap' - ) - - @models.permalink - def get_absolute_url(self): - return ('custom_user', (), { - 'pk': self.id - }) - - -class UserGroupMap(models.Model): - user = models.ForeignKey(to=CustomUser) - group = models.ForeignKey(to=Group) - - @models.permalink - def get_absolute_url(self): - return ('user_group_map', (), { - 'pk': self.id - }) diff --git a/djangorestframework/tests/modelviews.py b/djangorestframework/tests/modelviews.py deleted file mode 100644 index ccd8513f..00000000 --- a/djangorestframework/tests/modelviews.py +++ /dev/null @@ -1,90 +0,0 @@ -from django.conf.urls.defaults import patterns, url -from django.forms import ModelForm -from django.contrib.auth.models import Group, User -from djangorestframework.resources import ModelResource -from djangorestframework.views import ListOrCreateModelView, InstanceModelView -from djangorestframework.tests.models import CustomUser -from djangorestframework.tests.testcases import TestModelsTestCase - - -class GroupResource(ModelResource): - model = Group - - -class UserForm(ModelForm): - class Meta: - model = User - exclude = ('last_login', 'date_joined') - - -class UserResource(ModelResource): - model = User - form = UserForm - - -class CustomUserResource(ModelResource): - model = CustomUser - -urlpatterns = patterns('', - url(r'^users/$', ListOrCreateModelView.as_view(resource=UserResource), name='users'), - url(r'^users/(?P<id>[0-9]+)/$', InstanceModelView.as_view(resource=UserResource)), - url(r'^customusers/$', ListOrCreateModelView.as_view(resource=CustomUserResource), name='customusers'), - url(r'^customusers/(?P<id>[0-9]+)/$', InstanceModelView.as_view(resource=CustomUserResource)), - url(r'^groups/$', ListOrCreateModelView.as_view(resource=GroupResource), name='groups'), - url(r'^groups/(?P<id>[0-9]+)/$', InstanceModelView.as_view(resource=GroupResource)), -) - - -class ModelViewTests(TestModelsTestCase): - """Test the model views djangorestframework provides""" - urls = 'djangorestframework.tests.modelviews' - - def test_creation(self): - """Ensure that a model object can be created""" - self.assertEqual(0, Group.objects.count()) - - response = self.client.post('/groups/', {'name': 'foo'}) - - self.assertEqual(response.status_code, 201) - self.assertEqual(1, Group.objects.count()) - self.assertEqual('foo', Group.objects.all()[0].name) - - def test_creation_with_m2m_relation(self): - """Ensure that a model object with a m2m relation can be created""" - group = Group(name='foo') - group.save() - self.assertEqual(0, User.objects.count()) - - response = self.client.post('/users/', {'username': 'bar', 'password': 'baz', 'groups': [group.id]}) - - self.assertEqual(response.status_code, 201) - self.assertEqual(1, User.objects.count()) - - user = User.objects.all()[0] - self.assertEqual('bar', user.username) - self.assertEqual('baz', user.password) - self.assertEqual(1, user.groups.count()) - - group = user.groups.all()[0] - self.assertEqual('foo', group.name) - - def test_creation_with_m2m_relation_through(self): - """ - Ensure that a model object with a m2m relation can be created where that - relation uses a through table - """ - group = Group(name='foo') - group.save() - self.assertEqual(0, User.objects.count()) - - response = self.client.post('/customusers/', {'username': 'bar', 'groups': [group.id]}) - - self.assertEqual(response.status_code, 201) - self.assertEqual(1, CustomUser.objects.count()) - - user = CustomUser.objects.all()[0] - self.assertEqual('bar', user.username) - self.assertEqual(1, user.groups.count()) - - group = user.groups.all()[0] - self.assertEqual('foo', group.name) diff --git a/djangorestframework/tests/oauthentication.py b/djangorestframework/tests/oauthentication.py deleted file mode 100644 index 29f2c44e..00000000 --- a/djangorestframework/tests/oauthentication.py +++ /dev/null @@ -1,212 +0,0 @@ -import time - -from django.conf.urls.defaults import patterns, url, include -from django.contrib.auth.models import User -from django.test import Client, TestCase - -from djangorestframework.views import View - -# Since oauth2 / django-oauth-plus are optional dependancies, we don't want to -# always run these tests. - -# Unfortunatly we can't skip tests easily until 2.7, se we'll just do this for now. -try: - import oauth2 as oauth - from oauth_provider.decorators import oauth_required - from oauth_provider.models import Resource, Consumer, Token - -except ImportError: - pass - -else: - # Alrighty, we're good to go here. - class ClientView(View): - def get(self, request): - return {'resource': 'Protected!'} - - urlpatterns = patterns('', - url(r'^$', oauth_required(ClientView.as_view())), - url(r'^oauth/', include('oauth_provider.urls')), - url(r'^restframework/', include('djangorestframework.urls', namespace='djangorestframework')), - ) - - - class OAuthTests(TestCase): - """ - OAuth authentication: - * the user would like to access his API data from a third-party website - * the third-party website proposes a link to get that API data - * the user is redirected to the API and must log in if not authenticated - * the API displays a webpage to confirm that the user trusts the third-party website - * if confirmed, the user is redirected to the third-party website through the callback view - * the third-party website is able to retrieve data from the API - """ - urls = 'djangorestframework.tests.oauthentication' - - def setUp(self): - self.client = Client() - self.username = 'john' - self.email = 'lennon@thebeatles.com' - self.password = 'password' - self.user = User.objects.create_user(self.username, self.email, self.password) - - # OAuth requirements - self.resource = Resource(name='data', url='/') - self.resource.save() - self.CONSUMER_KEY = 'dpf43f3p2l4k3l03' - self.CONSUMER_SECRET = 'kd94hf93k423kf44' - self.consumer = Consumer(key=self.CONSUMER_KEY, secret=self.CONSUMER_SECRET, - name='api.example.com', user=self.user) - self.consumer.save() - - def test_oauth_invalid_and_anonymous_access(self): - """ - Verify that the resource is protected and the OAuth authorization view - require the user to be logged in. - """ - response = self.client.get('/') - self.assertEqual(response.content, 'Invalid request parameters.') - self.assertEqual(response.status_code, 401) - response = self.client.get('/oauth/authorize/', follow=True) - self.assertRedirects(response, '/accounts/login/?next=/oauth/authorize/') - - def test_oauth_authorize_access(self): - """ - Verify that once logged in, the user can access the authorization page - but can't display the page because the request token is not specified. - """ - self.client.login(username=self.username, password=self.password) - response = self.client.get('/oauth/authorize/', follow=True) - self.assertEqual(response.content, 'No request token specified.') - - def _create_request_token_parameters(self): - """ - A shortcut to create request's token parameters. - """ - return { - 'oauth_consumer_key': self.CONSUMER_KEY, - 'oauth_signature_method': 'PLAINTEXT', - 'oauth_signature': '%s&' % self.CONSUMER_SECRET, - 'oauth_timestamp': str(int(time.time())), - 'oauth_nonce': 'requestnonce', - 'oauth_version': '1.0', - 'oauth_callback': 'http://api.example.com/request_token_ready', - 'scope': 'data', - } - - def test_oauth_request_token_retrieval(self): - """ - Verify that the request token can be retrieved by the server. - """ - response = self.client.get("/oauth/request_token/", - self._create_request_token_parameters()) - self.assertEqual(response.status_code, 200) - token = list(Token.objects.all())[-1] - self.failIf(token.key not in response.content) - self.failIf(token.secret not in response.content) - - def test_oauth_user_request_authorization(self): - """ - Verify that the user can access the authorization page once logged in - and the request token has been retrieved. - """ - # Setup - response = self.client.get("/oauth/request_token/", - self._create_request_token_parameters()) - token = list(Token.objects.all())[-1] - - # Starting the test here - self.client.login(username=self.username, password=self.password) - parameters = {'oauth_token': token.key,} - response = self.client.get("/oauth/authorize/", parameters) - self.assertEqual(response.status_code, 200) - self.failIf(not response.content.startswith('Fake authorize view for api.example.com with params: oauth_token=')) - self.assertEqual(token.is_approved, 0) - parameters['authorize_access'] = 1 # fake authorization by the user - response = self.client.post("/oauth/authorize/", parameters) - self.assertEqual(response.status_code, 302) - self.failIf(not response['Location'].startswith('http://api.example.com/request_token_ready?oauth_verifier=')) - token = Token.objects.get(key=token.key) - self.failIf(token.key not in response['Location']) - self.assertEqual(token.is_approved, 1) - - def _create_access_token_parameters(self, token): - """ - A shortcut to create access' token parameters. - """ - return { - 'oauth_consumer_key': self.CONSUMER_KEY, - 'oauth_token': token.key, - 'oauth_signature_method': 'PLAINTEXT', - 'oauth_signature': '%s&%s' % (self.CONSUMER_SECRET, token.secret), - 'oauth_timestamp': str(int(time.time())), - 'oauth_nonce': 'accessnonce', - 'oauth_version': '1.0', - 'oauth_verifier': token.verifier, - 'scope': 'data', - } - - def test_oauth_access_token_retrieval(self): - """ - Verify that the request token can be retrieved by the server. - """ - # Setup - response = self.client.get("/oauth/request_token/", - self._create_request_token_parameters()) - token = list(Token.objects.all())[-1] - self.client.login(username=self.username, password=self.password) - parameters = {'oauth_token': token.key,} - response = self.client.get("/oauth/authorize/", parameters) - parameters['authorize_access'] = 1 # fake authorization by the user - response = self.client.post("/oauth/authorize/", parameters) - token = Token.objects.get(key=token.key) - - # Starting the test here - response = self.client.get("/oauth/access_token/", self._create_access_token_parameters(token)) - self.assertEqual(response.status_code, 200) - self.failIf(not response.content.startswith('oauth_token_secret=')) - access_token = list(Token.objects.filter(token_type=Token.ACCESS))[-1] - self.failIf(access_token.key not in response.content) - self.failIf(access_token.secret not in response.content) - self.assertEqual(access_token.user.username, 'john') - - def _create_access_parameters(self, access_token): - """ - A shortcut to create access' parameters. - """ - parameters = { - 'oauth_consumer_key': self.CONSUMER_KEY, - 'oauth_token': access_token.key, - 'oauth_signature_method': 'HMAC-SHA1', - 'oauth_timestamp': str(int(time.time())), - 'oauth_nonce': 'accessresourcenonce', - 'oauth_version': '1.0', - } - oauth_request = oauth.Request.from_token_and_callback(access_token, - http_url='http://testserver/', parameters=parameters) - signature_method = oauth.SignatureMethod_HMAC_SHA1() - signature = signature_method.sign(oauth_request, self.consumer, access_token) - parameters['oauth_signature'] = signature - return parameters - - def test_oauth_protected_resource_access(self): - """ - Verify that the request token can be retrieved by the server. - """ - # Setup - response = self.client.get("/oauth/request_token/", - self._create_request_token_parameters()) - token = list(Token.objects.all())[-1] - self.client.login(username=self.username, password=self.password) - parameters = {'oauth_token': token.key,} - response = self.client.get("/oauth/authorize/", parameters) - parameters['authorize_access'] = 1 # fake authorization by the user - response = self.client.post("/oauth/authorize/", parameters) - token = Token.objects.get(key=token.key) - response = self.client.get("/oauth/access_token/", self._create_access_token_parameters(token)) - access_token = list(Token.objects.filter(token_type=Token.ACCESS))[-1] - - # Starting the test here - response = self.client.get("/", self._create_access_token_parameters(access_token)) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.content, '{"resource": "Protected!"}') diff --git a/djangorestframework/tests/package.py b/djangorestframework/tests/package.py deleted file mode 100644 index d18128f7..00000000 --- a/djangorestframework/tests/package.py +++ /dev/null @@ -1,11 +0,0 @@ -"""Tests for the djangorestframework package setup.""" -from django.test import TestCase -import djangorestframework - -class TestVersion(TestCase): - """Simple sanity test to check the VERSION exists""" - - def test_version(self): - """Ensure the VERSION exists.""" - djangorestframework.VERSION - diff --git a/djangorestframework/tests/parsers.py b/djangorestframework/tests/parsers.py deleted file mode 100644 index 1ecc1760..00000000 --- a/djangorestframework/tests/parsers.py +++ /dev/null @@ -1,210 +0,0 @@ -# """ -# .. -# >>> from djangorestframework.parsers import FormParser -# >>> from djangorestframework.compat import RequestFactory -# >>> from djangorestframework.views import View -# >>> from StringIO import StringIO -# >>> from urllib import urlencode -# >>> req = RequestFactory().get('/') -# >>> some_view = View() -# >>> some_view.request = req # Make as if this request had been dispatched -# -# FormParser -# ============ -# -# Data flatening -# ---------------- -# -# Here is some example data, which would eventually be sent along with a post request : -# -# >>> inpt = urlencode([ -# ... ('key1', 'bla1'), -# ... ('key2', 'blo1'), ('key2', 'blo2'), -# ... ]) -# -# Default behaviour for :class:`parsers.FormParser`, is to return a single value for each parameter : -# -# >>> (data, files) = FormParser(some_view).parse(StringIO(inpt)) -# >>> data == {'key1': 'bla1', 'key2': 'blo1'} -# True -# -# However, you can customize this behaviour by subclassing :class:`parsers.FormParser`, and overriding :meth:`parsers.FormParser.is_a_list` : -# -# >>> class MyFormParser(FormParser): -# ... -# ... def is_a_list(self, key, val_list): -# ... return len(val_list) > 1 -# -# This new parser only flattens the lists of parameters that contain a single value. -# -# >>> (data, files) = MyFormParser(some_view).parse(StringIO(inpt)) -# >>> data == {'key1': 'bla1', 'key2': ['blo1', 'blo2']} -# True -# -# .. note:: The same functionality is available for :class:`parsers.MultiPartParser`. -# -# Submitting an empty list -# -------------------------- -# -# When submitting an empty select multiple, like this one :: -# -# <select multiple="multiple" name="key2"></select> -# -# The browsers usually strip the parameter completely. A hack to avoid this, and therefore being able to submit an empty select multiple, is to submit a value that tells the server that the list is empty :: -# -# <select multiple="multiple" name="key2"><option value="_empty"></select> -# -# :class:`parsers.FormParser` provides the server-side implementation for this hack. Considering the following posted data : -# -# >>> inpt = urlencode([ -# ... ('key1', 'blo1'), ('key1', '_empty'), -# ... ('key2', '_empty'), -# ... ]) -# -# :class:`parsers.FormParser` strips the values ``_empty`` from all the lists. -# -# >>> (data, files) = MyFormParser(some_view).parse(StringIO(inpt)) -# >>> data == {'key1': 'blo1'} -# True -# -# Oh ... but wait a second, the parameter ``key2`` isn't even supposed to be a list, so the parser just stripped it. -# -# >>> class MyFormParser(FormParser): -# ... -# ... def is_a_list(self, key, val_list): -# ... return key == 'key2' -# ... -# >>> (data, files) = MyFormParser(some_view).parse(StringIO(inpt)) -# >>> data == {'key1': 'blo1', 'key2': []} -# True -# -# Better like that. Note that you can configure something else than ``_empty`` for the empty value by setting :attr:`parsers.FormParser.EMPTY_VALUE`. -# """ -# import httplib, mimetypes -# from tempfile import TemporaryFile -# from django.test import TestCase -# from djangorestframework.compat import RequestFactory -# from djangorestframework.parsers import MultiPartParser -# from djangorestframework.views import View -# from StringIO import StringIO -# -# def encode_multipart_formdata(fields, files): -# """For testing multipart parser. -# fields is a sequence of (name, value) elements for regular form fields. -# files is a sequence of (name, filename, value) elements for data to be uploaded as files -# Return (content_type, body).""" -# BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$' -# CRLF = '\r\n' -# L = [] -# for (key, value) in fields: -# L.append('--' + BOUNDARY) -# L.append('Content-Disposition: form-data; name="%s"' % key) -# L.append('') -# L.append(value) -# for (key, filename, value) in files: -# L.append('--' + BOUNDARY) -# L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename)) -# L.append('Content-Type: %s' % get_content_type(filename)) -# L.append('') -# L.append(value) -# L.append('--' + BOUNDARY + '--') -# L.append('') -# body = CRLF.join(L) -# content_type = 'multipart/form-data; boundary=%s' % BOUNDARY -# return content_type, body -# -# def get_content_type(filename): -# return mimetypes.guess_type(filename)[0] or 'application/octet-stream' -# -#class TestMultiPartParser(TestCase): -# def setUp(self): -# self.req = RequestFactory() -# self.content_type, self.body = encode_multipart_formdata([('key1', 'val1'), ('key1', 'val2')], -# [('file1', 'pic.jpg', 'blablabla'), ('file1', 't.txt', 'blobloblo')]) -# -# def test_multipartparser(self): -# """Ensure that MultiPartParser can parse multipart/form-data that contains a mix of several files and parameters.""" -# post_req = RequestFactory().post('/', self.body, content_type=self.content_type) -# view = View() -# view.request = post_req -# (data, files) = MultiPartParser(view).parse(StringIO(self.body)) -# self.assertEqual(data['key1'], 'val1') -# self.assertEqual(files['file1'].read(), 'blablabla') - -from StringIO import StringIO -from cgi import parse_qs -from django import forms -from django.test import TestCase -from djangorestframework.parsers import FormParser -from djangorestframework.parsers import XMLParser -import datetime - -class Form(forms.Form): - field1 = forms.CharField(max_length=3) - field2 = forms.CharField() - -class TestFormParser(TestCase): - def setUp(self): - self.string = "field1=abc&field2=defghijk" - - def test_parse(self): - """ Make sure the `QueryDict` works OK """ - parser = FormParser(None) - - stream = StringIO(self.string) - (data, files) = parser.parse(stream) - - self.assertEqual(Form(data).is_valid(), True) - -class TestXMLParser(TestCase): - def setUp(self): - self._input = StringIO( - '<?xml version="1.0" encoding="utf-8"?>' - '<root>' - '<field_a>121.0</field_a>' - '<field_b>dasd</field_b>' - '<field_c></field_c>' - '<field_d>2011-12-25 12:45:00</field_d>' - '</root>' - ) - self._data = { - 'field_a': 121, - 'field_b': 'dasd', - 'field_c': None, - 'field_d': datetime.datetime(2011, 12, 25, 12, 45, 00) - } - self._complex_data_input = StringIO( - '<?xml version="1.0" encoding="utf-8"?>' - '<root>' - '<creation_date>2011-12-25 12:45:00</creation_date>' - '<sub_data_list>' - '<list-item><sub_id>1</sub_id><sub_name>first</sub_name></list-item>' - '<list-item><sub_id>2</sub_id><sub_name>second</sub_name></list-item>' - '</sub_data_list>' - '<name>name</name>' - '</root>' - ) - self._complex_data = { - "creation_date": datetime.datetime(2011, 12, 25, 12, 45, 00), - "name": "name", - "sub_data_list": [ - { - "sub_id": 1, - "sub_name": "first" - }, - { - "sub_id": 2, - "sub_name": "second" - } - ] - } - - def test_parse(self): - parser = XMLParser(None) - (data, files) = parser.parse(self._input) - self.assertEqual(data, self._data) - - def test_complex_data_parse(self): - parser = XMLParser(None) - (data, files) = parser.parse(self._complex_data_input) - self.assertEqual(data, self._complex_data) diff --git a/djangorestframework/tests/renderers.py b/djangorestframework/tests/renderers.py deleted file mode 100644 index 3ed5ab28..00000000 --- a/djangorestframework/tests/renderers.py +++ /dev/null @@ -1,412 +0,0 @@ -import re - -from django.conf.urls.defaults import patterns, url, include -from django.test import TestCase - -from djangorestframework import status -from djangorestframework.views import View -from djangorestframework.compat import View as DjangoView -from djangorestframework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer, \ - XMLRenderer, JSONPRenderer, DocumentingHTMLRenderer -from djangorestframework.parsers import JSONParser, YAMLParser, XMLParser -from djangorestframework.mixins import ResponseMixin -from djangorestframework.response import Response - -from StringIO import StringIO -import datetime -from decimal import Decimal - -DUMMYSTATUS = status.HTTP_200_OK -DUMMYCONTENT = 'dummycontent' - -RENDERER_A_SERIALIZER = lambda x: 'Renderer A: %s' % x -RENDERER_B_SERIALIZER = lambda x: 'Renderer B: %s' % x - - -class RendererA(BaseRenderer): - media_type = 'mock/renderera' - format = "formata" - - def render(self, obj=None, media_type=None): - return RENDERER_A_SERIALIZER(obj) - - -class RendererB(BaseRenderer): - media_type = 'mock/rendererb' - format = "formatb" - - def render(self, obj=None, media_type=None): - return RENDERER_B_SERIALIZER(obj) - - -class MockView(ResponseMixin, DjangoView): - renderers = (RendererA, RendererB) - - def get(self, request, **kwargs): - response = Response(DUMMYSTATUS, DUMMYCONTENT) - return self.render(response) - - -class MockGETView(View): - - def get(self, request, **kwargs): - return {'foo': ['bar', 'baz']} - - -class HTMLView(View): - renderers = (DocumentingHTMLRenderer, ) - - def get(self, request, **kwargs): - return 'text' - - -class HTMLView1(View): - renderers = (DocumentingHTMLRenderer, JSONRenderer) - - def get(self, request, **kwargs): - return 'text' - -urlpatterns = patterns('', - url(r'^.*\.(?P<format>.+)$', MockView.as_view(renderers=[RendererA, RendererB])), - url(r'^$', MockView.as_view(renderers=[RendererA, RendererB])), - url(r'^jsonp/jsonrenderer$', MockGETView.as_view(renderers=[JSONRenderer, JSONPRenderer])), - url(r'^jsonp/nojsonrenderer$', MockGETView.as_view(renderers=[JSONPRenderer])), - url(r'^html$', HTMLView.as_view()), - url(r'^html1$', HTMLView1.as_view()), - url(r'^api', include('djangorestframework.urls', namespace='djangorestframework')) -) - - -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}' - - -def strip_trailing_whitespace(content): - """ - Seems to be some inconsistencies re. trailing whitespace with - different versions of the json lib. - """ - return re.sub(' +\n', '\n', content) - -class JSONRendererTests(TestCase): - """ - Tests specific to the JSON Renderer - """ - - def test_without_content_type_args(self): - """ - Test basic JSON rendering. - """ - obj = {'foo': ['bar', 'baz']} - renderer = JSONRenderer(None) - content = renderer.render(obj, 'application/json') - # Fix failing test case which depends on version of JSON library. - self.assertEquals(content, _flat_repr) - - def test_with_content_type_args(self): - """ - Test JSON rendering with additional content type arguments supplied. - """ - obj = {'foo': ['bar', 'baz']} - renderer = JSONRenderer(None) - content = renderer.render(obj, 'application/json; indent=2') - self.assertEquals(strip_trailing_whitespace(content), _indented_repr) - - def test_render_and_parse(self): - """ - Test rendering and then parsing returns the original object. - IE obj -> render -> parse -> obj. - """ - obj = {'foo': ['bar', 'baz']} - - renderer = JSONRenderer(None) - parser = JSONParser(None) - - content = renderer.render(obj, 'application/json') - (data, files) = parser.parse(StringIO(content)) - self.assertEquals(obj, data) - - -class JSONPRendererTests(TestCase): - """ - Tests specific to the JSONP Renderer - """ - - urls = 'djangorestframework.tests.renderers' - - def test_without_callback_with_json_renderer(self): - """ - Test JSONP rendering with View JSON Renderer. - """ - resp = self.client.get('/jsonp/jsonrenderer', - HTTP_ACCEPT='application/json-p') - self.assertEquals(resp.status_code, 200) - self.assertEquals(resp['Content-Type'], 'application/json-p') - self.assertEquals(resp.content, 'callback(%s);' % _flat_repr) - - def test_without_callback_without_json_renderer(self): - """ - Test JSONP rendering without View JSON Renderer. - """ - resp = self.client.get('/jsonp/nojsonrenderer', - HTTP_ACCEPT='application/json-p') - self.assertEquals(resp.status_code, 200) - self.assertEquals(resp['Content-Type'], 'application/json-p') - self.assertEquals(resp.content, 'callback(%s);' % _flat_repr) - - def test_with_callback(self): - """ - Test JSONP rendering with callback function name. - """ - callback_func = 'myjsonpcallback' - resp = self.client.get('/jsonp/nojsonrenderer?callback=' + callback_func, - HTTP_ACCEPT='application/json-p') - self.assertEquals(resp.status_code, 200) - self.assertEquals(resp['Content-Type'], 'application/json-p') - self.assertEquals(resp.content, '%s(%s);' % (callback_func, _flat_repr)) - - -if YAMLRenderer: - _yaml_repr = 'foo: [bar, baz]\n' - - class YAMLRendererTests(TestCase): - """ - Tests specific to the JSON Renderer - """ - - def test_render(self): - """ - Test basic YAML rendering. - """ - obj = {'foo': ['bar', 'baz']} - renderer = YAMLRenderer(None) - content = renderer.render(obj, 'application/yaml') - self.assertEquals(content, _yaml_repr) - - def test_render_and_parse(self): - """ - Test rendering and then parsing returns the original object. - IE obj -> render -> parse -> obj. - """ - obj = {'foo': ['bar', 'baz']} - - renderer = YAMLRenderer(None) - parser = YAMLParser(None) - - content = renderer.render(obj, 'application/yaml') - (data, files) = parser.parse(StringIO(content)) - self.assertEquals(obj, data) - - - -class XMLRendererTestCase(TestCase): - """ - Tests specific to the XML Renderer - """ - - _complex_data = { - "creation_date": datetime.datetime(2011, 12, 25, 12, 45, 00), - "name": "name", - "sub_data_list": [ - { - "sub_id": 1, - "sub_name": "first" - }, - { - "sub_id": 2, - "sub_name": "second" - } - ] - } - - def test_render_string(self): - """ - Test XML rendering. - """ - renderer = XMLRenderer(None) - content = renderer.render({'field': 'astring'}, 'application/xml') - self.assertXMLContains(content, '<field>astring</field>') - - def test_render_integer(self): - """ - Test XML rendering. - """ - renderer = XMLRenderer(None) - content = renderer.render({'field': 111}, 'application/xml') - self.assertXMLContains(content, '<field>111</field>') - - def test_render_datetime(self): - """ - Test XML rendering. - """ - renderer = XMLRenderer(None) - content = renderer.render({ - 'field': datetime.datetime(2011, 12, 25, 12, 45, 00) - }, 'application/xml') - self.assertXMLContains(content, '<field>2011-12-25 12:45:00</field>') - - def test_render_float(self): - """ - Test XML rendering. - """ - renderer = XMLRenderer(None) - content = renderer.render({'field': 123.4}, 'application/xml') - self.assertXMLContains(content, '<field>123.4</field>') - - def test_render_decimal(self): - """ - Test XML rendering. - """ - renderer = XMLRenderer(None) - content = renderer.render({'field': Decimal('111.2')}, 'application/xml') - self.assertXMLContains(content, '<field>111.2</field>') - - def test_render_none(self): - """ - Test XML rendering. - """ - renderer = XMLRenderer(None) - content = renderer.render({'field': None}, 'application/xml') - self.assertXMLContains(content, '<field></field>') - - def test_render_complex_data(self): - """ - Test XML rendering. - """ - renderer = XMLRenderer(None) - content = renderer.render(self._complex_data, 'application/xml') - self.assertXMLContains(content, '<sub_name>first</sub_name>') - self.assertXMLContains(content, '<sub_name>second</sub_name>') - - def test_render_and_parse_complex_data(self): - """ - Test XML rendering. - """ - renderer = XMLRenderer(None) - content = StringIO(renderer.render(self._complex_data, 'application/xml')) - - parser = XMLParser(None) - complex_data_out, dummy = parser.parse(content) - error_msg = "complex data differs!IN:\n %s \n\n OUT:\n %s" % (repr(self._complex_data), repr(complex_data_out)) - self.assertEqual(self._complex_data, complex_data_out, error_msg) - - 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)) - - -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/response.py b/djangorestframework/tests/response.py deleted file mode 100644 index d973deb4..00000000 --- a/djangorestframework/tests/response.py +++ /dev/null @@ -1,19 +0,0 @@ -# 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') - diff --git a/djangorestframework/tests/reverse.py b/djangorestframework/tests/reverse.py deleted file mode 100644 index 01ba19b9..00000000 --- a/djangorestframework/tests/reverse.py +++ /dev/null @@ -1,52 +0,0 @@ -from django.conf.urls.defaults import patterns, url -from django.test import TestCase -from django.utils import simplejson as json - -from djangorestframework.renderers import JSONRenderer -from djangorestframework.reverse import reverse, reverse_lazy -from djangorestframework.views import View - - -class ReverseView(View): - """ - Mock resource which simply returns a URL, so that we can ensure - that reversed URLs are fully qualified. - """ - renderers = (JSONRenderer, ) - - def get(self, request): - return reverse('reverse', request=request) - - -class LazyView(View): - """ - Mock resource which simply returns a URL, so that we can ensure - that reversed URLs are fully qualified. - """ - renderers = (JSONRenderer, ) - - def get(self, request): - return reverse_lazy('lazy', request=request) - - -urlpatterns = patterns('', - url(r'^reverse$', ReverseView.as_view(), name='reverse'), - url(r'^lazy$', LazyView.as_view(), name='lazy'), -) - - -class ReverseTests(TestCase): - """ - Tests for fully qualifed URLs when using `reverse`. - """ - urls = 'djangorestframework.tests.reverse' - - def test_reversed_urls_are_fully_qualified(self): - response = self.client.get('/reverse') - self.assertEqual(json.loads(response.content), - 'http://testserver/reverse') - - #def test_reversed_lazy_urls_are_fully_qualified(self): - # response = self.client.get('/lazy') - # self.assertEqual(json.loads(response.content), - # 'http://testserver/lazy') diff --git a/djangorestframework/tests/serializer.py b/djangorestframework/tests/serializer.py deleted file mode 100644 index 1a4eaa10..00000000 --- a/djangorestframework/tests/serializer.py +++ /dev/null @@ -1,160 +0,0 @@ -"""Tests for the resource module""" -from django.db import models -from django.test import TestCase -from django.utils.translation import ugettext_lazy -from djangorestframework.serializer import Serializer - -import datetime -import decimal - -class TestObjectToData(TestCase): - """ - Tests for the Serializer class. - """ - - def setUp(self): - self.serializer = Serializer() - self.serialize = self.serializer.serialize - - def test_decimal(self): - """Decimals need to be converted to a string representation.""" - self.assertEquals(self.serialize(decimal.Decimal('1.5')), decimal.Decimal('1.5')) - - def test_function(self): - """Functions with no arguments should be called.""" - def foo(): - return 1 - self.assertEquals(self.serialize(foo), 1) - - def test_method(self): - """Methods with only a ``self`` argument should be called.""" - class Foo(object): - def foo(self): - return 1 - self.assertEquals(self.serialize(Foo().foo), 1) - - def test_datetime(self): - """datetime objects are left as-is.""" - now = datetime.datetime.now() - self.assertEquals(self.serialize(now), now) - - def test_dict_method_name_collision(self): - """dict with key that collides with dict method name""" - self.assertEquals(self.serialize({'items': 'foo'}), {'items': u'foo'}) - self.assertEquals(self.serialize({'keys': 'foo'}), {'keys': u'foo'}) - self.assertEquals(self.serialize({'values': 'foo'}), {'values': u'foo'}) - - def test_ugettext_lazy(self): - self.assertEquals(self.serialize(ugettext_lazy('foobar')), u'foobar') - - -class TestFieldNesting(TestCase): - """ - Test nesting the fields in the Serializer class - """ - def setUp(self): - self.serializer = Serializer() - self.serialize = self.serializer.serialize - - class M1(models.Model): - field1 = models.CharField(max_length=256) - field2 = models.CharField(max_length=256) - - class M2(models.Model): - field = models.OneToOneField(M1) - - class M3(models.Model): - field = models.ForeignKey(M1) - - self.m1 = M1(field1='foo', field2='bar') - self.m2 = M2(field=self.m1) - self.m3 = M3(field=self.m1) - - - def test_tuple_nesting(self): - """ - Test tuple nesting on `fields` attr - """ - class SerializerM2(Serializer): - fields = (('field', ('field1',)),) - - class SerializerM3(Serializer): - fields = (('field', ('field2',)),) - - self.assertEqual(SerializerM2().serialize(self.m2), {'field': {'field1': u'foo'}}) - self.assertEqual(SerializerM3().serialize(self.m3), {'field': {'field2': u'bar'}}) - - - def test_serializer_class_nesting(self): - """ - Test related model serialization - """ - class NestedM2(Serializer): - fields = ('field1', ) - - class NestedM3(Serializer): - fields = ('field2', ) - - class SerializerM2(Serializer): - fields = [('field', NestedM2)] - - class SerializerM3(Serializer): - fields = [('field', NestedM3)] - - self.assertEqual(SerializerM2().serialize(self.m2), {'field': {'field1': u'foo'}}) - self.assertEqual(SerializerM3().serialize(self.m3), {'field': {'field2': u'bar'}}) - - # def test_serializer_no_fields(self): - # """ - # Test related serializer works when the fields attr isn't present. Fix for - # #178. - # """ - # class NestedM2(Serializer): - # fields = ('field1', ) - - # class NestedM3(Serializer): - # fields = ('field2', ) - - # class SerializerM2(Serializer): - # include = [('field', NestedM2)] - # exclude = ('id', ) - - # class SerializerM3(Serializer): - # fields = [('field', NestedM3)] - - # self.assertEqual(SerializerM2().serialize(self.m2), {'field': {'field1': u'foo'}}) - # self.assertEqual(SerializerM3().serialize(self.m3), {'field': {'field2': u'bar'}}) - - def test_serializer_classname_nesting(self): - """ - Test related model serialization - """ - class SerializerM2(Serializer): - fields = [('field', 'NestedM2')] - - class SerializerM3(Serializer): - fields = [('field', 'NestedM3')] - - class NestedM2(Serializer): - fields = ('field1', ) - - class NestedM3(Serializer): - fields = ('field2', ) - - self.assertEqual(SerializerM2().serialize(self.m2), {'field': {'field1': u'foo'}}) - self.assertEqual(SerializerM3().serialize(self.m3), {'field': {'field2': u'bar'}}) - - def test_serializer_overridden_hook_method(self): - """ - Test serializing a model instance which overrides a class method on the - serializer. Checks for correct behaviour in odd edge case. - """ - class SerializerM2(Serializer): - fields = ('overridden', ) - - def overridden(self): - return False - - self.m2.overridden = True - self.assertEqual(SerializerM2().serialize_model(self.m2), - {'overridden': True}) diff --git a/djangorestframework/tests/status.py b/djangorestframework/tests/status.py deleted file mode 100644 index 53ecae11..00000000 --- a/djangorestframework/tests/status.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Tests for the status module""" -from django.test import TestCase -from djangorestframework import status - - -class TestStatus(TestCase): - """Simple sanity test to check the status module""" - - def test_status(self): - """Ensure the status module is present and correct.""" - self.assertEquals(200, status.HTTP_200_OK) - self.assertEquals(404, status.HTTP_404_NOT_FOUND) diff --git a/djangorestframework/tests/testcases.py b/djangorestframework/tests/testcases.py deleted file mode 100644 index 51b4afbc..00000000 --- a/djangorestframework/tests/testcases.py +++ /dev/null @@ -1,63 +0,0 @@ -# http://djangosnippets.org/snippets/1011/ -from django.conf import settings -from django.core.management import call_command -from django.db.models import loading -from django.test import TestCase - -NO_SETTING = ('!', None) - -class TestSettingsManager(object): - """ - A class which can modify some Django settings temporarily for a - test and then revert them to their original values later. - - Automatically handles resyncing the DB if INSTALLED_APPS is - modified. - - """ - def __init__(self): - self._original_settings = {} - - def set(self, **kwargs): - for k,v in kwargs.iteritems(): - self._original_settings.setdefault(k, getattr(settings, k, - NO_SETTING)) - setattr(settings, k, v) - if 'INSTALLED_APPS' in kwargs: - self.syncdb() - - def syncdb(self): - loading.cache.loaded = False - call_command('syncdb', verbosity=0) - - def revert(self): - for k,v in self._original_settings.iteritems(): - if v == NO_SETTING: - delattr(settings, k) - else: - setattr(settings, k, v) - if 'INSTALLED_APPS' in self._original_settings: - self.syncdb() - self._original_settings = {} - - -class SettingsTestCase(TestCase): - """ - A subclass of the Django TestCase with a settings_manager - attribute which is an instance of TestSettingsManager. - - Comes with a tearDown() method that calls - self.settings_manager.revert(). - - """ - def __init__(self, *args, **kwargs): - super(SettingsTestCase, self).__init__(*args, **kwargs) - self.settings_manager = TestSettingsManager() - - def tearDown(self): - self.settings_manager.revert() - -class TestModelsTestCase(SettingsTestCase): - def setUp(self, *args, **kwargs): - installed_apps = tuple(settings.INSTALLED_APPS) + ('djangorestframework.tests',) - self.settings_manager.set(INSTALLED_APPS=installed_apps) diff --git a/djangorestframework/tests/throttling.py b/djangorestframework/tests/throttling.py deleted file mode 100644 index 7fdc6491..00000000 --- a/djangorestframework/tests/throttling.py +++ /dev/null @@ -1,148 +0,0 @@ -""" -Tests for the throttling implementations in the permissions module. -""" - -from django.test import TestCase -from django.contrib.auth.models import User -from django.core.cache import cache - -from djangorestframework.compat import RequestFactory -from djangorestframework.views import View -from djangorestframework.permissions import PerUserThrottling, PerViewThrottling, PerResourceThrottling -from djangorestframework.resources import FormResource - -class MockView(View): - permissions = ( PerUserThrottling, ) - throttle = '3/sec' - - def get(self, request): - return 'foo' - -class MockView_PerViewThrottling(MockView): - permissions = ( PerViewThrottling, ) - -class MockView_PerResourceThrottling(MockView): - permissions = ( PerResourceThrottling, ) - resource = FormResource - -class MockView_MinuteThrottling(MockView): - throttle = '3/min' - - - -class ThrottlingTests(TestCase): - urls = 'djangorestframework.tests.throttling' - - def setUp(self): - """ - Reset the cache so that no throttles will be active - """ - cache.clear() - self.factory = RequestFactory() - - def test_requests_are_throttled(self): - """ - Ensure request rate is limited - """ - request = self.factory.get('/') - for dummy in range(4): - response = MockView.as_view()(request) - self.assertEqual(503, response.status_code) - - def set_throttle_timer(self, view, value): - """ - Explicitly set the timer, overriding time.time() - """ - view.permissions[0].timer = lambda self: value - - def test_request_throttling_expires(self): - """ - Ensure request rate is limited for a limited duration only - """ - self.set_throttle_timer(MockView, 0) - - request = self.factory.get('/') - for dummy in range(4): - response = MockView.as_view()(request) - self.assertEqual(503, response.status_code) - - # Advance the timer by one second - self.set_throttle_timer(MockView, 1) - - response = MockView.as_view()(request) - self.assertEqual(200, response.status_code) - - def ensure_is_throttled(self, view, expect): - request = self.factory.get('/') - request.user = User.objects.create(username='a') - for dummy in range(3): - view.as_view()(request) - request.user = User.objects.create(username='b') - response = view.as_view()(request) - self.assertEqual(expect, response.status_code) - - def test_request_throttling_is_per_user(self): - """ - Ensure request rate is only limited per user, not globally for - PerUserThrottles - """ - self.ensure_is_throttled(MockView, 200) - - def test_request_throttling_is_per_view(self): - """ - Ensure request rate is limited globally per View for PerViewThrottles - """ - self.ensure_is_throttled(MockView_PerViewThrottling, 503) - - def test_request_throttling_is_per_resource(self): - """ - Ensure request rate is limited globally per Resource for PerResourceThrottles - """ - self.ensure_is_throttled(MockView_PerResourceThrottling, 503) - - - def ensure_response_header_contains_proper_throttle_field(self, view, expected_headers): - """ - Ensure the response returns an X-Throttle field with status and next attributes - set properly. - """ - request = self.factory.get('/') - for timer, expect in expected_headers: - self.set_throttle_timer(view, timer) - response = view.as_view()(request) - self.assertEquals(response['X-Throttle'], expect) - - def test_seconds_fields(self): - """ - Ensure for second based throttles. - """ - self.ensure_response_header_contains_proper_throttle_field(MockView, - ((0, 'status=SUCCESS; next=0.33 sec'), - (0, 'status=SUCCESS; next=0.50 sec'), - (0, 'status=SUCCESS; next=1.00 sec'), - (0, 'status=FAILURE; next=1.00 sec') - )) - - def test_minutes_fields(self): - """ - Ensure for minute based throttles. - """ - self.ensure_response_header_contains_proper_throttle_field(MockView_MinuteThrottling, - ((0, 'status=SUCCESS; next=20.00 sec'), - (0, 'status=SUCCESS; next=30.00 sec'), - (0, 'status=SUCCESS; next=60.00 sec'), - (0, 'status=FAILURE; next=60.00 sec') - )) - - def test_next_rate_remains_constant_if_followed(self): - """ - If a client follows the recommended next request rate, - the throttling rate should stay constant. - """ - self.ensure_response_header_contains_proper_throttle_field(MockView_MinuteThrottling, - ((0, 'status=SUCCESS; next=20.00 sec'), - (20, 'status=SUCCESS; next=20.00 sec'), - (40, 'status=SUCCESS; next=20.00 sec'), - (60, 'status=SUCCESS; next=20.00 sec'), - (80, 'status=SUCCESS; next=20.00 sec') - )) diff --git a/djangorestframework/tests/validators.py b/djangorestframework/tests/validators.py deleted file mode 100644 index 15d92231..00000000 --- a/djangorestframework/tests/validators.py +++ /dev/null @@ -1,325 +0,0 @@ -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.views import View - - -class TestDisabledValidations(TestCase): - """Tests on FormValidator with validation disabled by setting form to None""" - - def test_disabled_form_validator_returns_content_unchanged(self): - """If the view's form attribute is None then FormValidator(view).validate_request(content, None) - should just return the content unmodified.""" - class DisabledFormResource(FormResource): - form = None - - class MockView(View): - resource = DisabledFormResource - - view = MockView() - content = {'qwerty': 'uiop'} - self.assertEqual(FormResource(view).validate_request(content, None), content) - - def test_disabled_form_validator_get_bound_form_returns_none(self): - """If the view's form attribute is None on then - FormValidator(view).get_bound_form(content) should just return None.""" - class DisabledFormResource(FormResource): - form = None - - class MockView(View): - resource = DisabledFormResource - - view = MockView() - content = {'qwerty': 'uiop'} - self.assertEqual(FormResource(view).get_bound_form(content), None) - - def test_disabled_model_form_validator_returns_content_unchanged(self): - """If the view's form is None and does not have a Resource with a model set then - ModelFormValidator(view).validate_request(content, None) should just return the content unmodified.""" - - class DisabledModelFormView(View): - resource = ModelResource - - view = DisabledModelFormView() - content = {'qwerty': 'uiop'} - self.assertEqual(ModelResource(view).get_bound_form(content), None) - - def test_disabled_model_form_validator_get_bound_form_returns_none(self): - """If the form attribute is None on FormValidatorMixin then get_bound_form(content) should just return None.""" - class DisabledModelFormView(View): - resource = ModelResource - - view = DisabledModelFormView() - content = {'qwerty': 'uiop'} - self.assertEqual(ModelResource(view).get_bound_form(content), None) - - -class TestNonFieldErrors(TestCase): - """Tests against form validation errors caused by non-field errors. (eg as might be caused by some custom form validation)""" - - def test_validate_failed_due_to_non_field_error_returns_appropriate_message(self): - """If validation fails with a non-field error, ensure the response a non-field error""" - class MockForm(forms.Form): - field1 = forms.CharField(required=False) - field2 = forms.CharField(required=False) - ERROR_TEXT = 'You may not supply both field1 and field2' - - def clean(self): - if 'field1' in self.cleaned_data and 'field2' in self.cleaned_data: - raise forms.ValidationError(self.ERROR_TEXT) - return self.cleaned_data - - class MockResource(FormResource): - form = MockForm - - class MockView(View): - pass - - view = MockView() - 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]}) - else: - self.fail('ErrorResponse was not raised') - - -class TestFormValidation(TestCase): - """Tests which check basic form validation. - Also includes the same set of tests with a ModelFormValidator for which the form has been explicitly set. - (ModelFormValidator should behave as FormValidator if a form is set rather than relying on the default ModelForm)""" - def setUp(self): - class MockForm(forms.Form): - qwerty = forms.CharField(required=True) - - class MockFormResource(FormResource): - form = MockForm - - class MockModelResource(ModelResource): - form = MockForm - - class MockFormView(View): - resource = MockFormResource - - class MockModelFormView(View): - resource = MockModelResource - - self.MockFormResource = MockFormResource - self.MockModelResource = MockModelResource - self.MockFormView = MockFormView - self.MockModelFormView = MockModelFormView - - def validation_returns_content_unchanged_if_already_valid_and_clean(self, validator): - """If the content is already valid and clean then validate(content) should just return the content unmodified.""" - content = {'qwerty': 'uiop'} - self.assertEqual(validator.validate_request(content, None), content) - - 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) - - 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) - - 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.""" - content = {'qwerty': 'uiop', 'extra': 'extra'} - validator._validate(content, None, allowed_extra_fields=('extra',)) - - def validation_allows_unknown_fields_if_explicitly_allowed(self, validator): - """If we set ``unknown_form_fields`` on the form resource, then don't - raise errors on unexpected request data""" - content = {'qwerty': 'uiop', 'extra': 'extra'} - validator.allow_unknown_form_fields = True - self.assertEqual({'qwerty': u'uiop'}, - validator.validate_request(content, None), - "Resource didn't accept unknown fields.") - validator.allow_unknown_form_fields = False - - def validation_does_not_require_extra_fields_if_explicitly_set(self, validator): - """If we include an allowed_extra_fields paramater on _validate, then do not fail if we do not have fields with those names.""" - content = {'qwerty': 'uiop'} - self.assertEqual(validator._validate(content, None, allowed_extra_fields=('extra',)), content) - - def validation_failed_due_to_no_content_returns_appropriate_message(self, validator): - """If validation fails due to no content, ensure the response contains a single non-field error""" - content = {} - try: - validator.validate_request(content, None) - except ErrorResponse, exc: - self.assertEqual(exc.response.raw_content, {'field_errors': {'qwerty': ['This field is required.']}}) - else: - self.fail('ResourceException was not raised') - - def validation_failed_due_to_field_error_returns_appropriate_message(self, validator): - """If validation fails due to a field error, ensure the response contains a single field error""" - content = {'qwerty': ''} - try: - validator.validate_request(content, None) - except ErrorResponse, exc: - self.assertEqual(exc.response.raw_content, {'field_errors': {'qwerty': ['This field is required.']}}) - else: - self.fail('ResourceException was not raised') - - def validation_failed_due_to_invalid_field_returns_appropriate_message(self, validator): - """If validation fails due to an invalid field, ensure the response contains a single field error""" - 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.']}}) - else: - self.fail('ResourceException was not raised') - - def validation_failed_due_to_multiple_errors_returns_appropriate_message(self, validator): - """If validation for multiple reasons, ensure the response contains each error""" - 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.'], - 'extra': ['This field does not exist.']}}) - else: - self.fail('ResourceException was not raised') - - # Tests on FormResource - - def test_form_validation_returns_content_unchanged_if_already_valid_and_clean(self): - validator = self.MockFormResource(self.MockFormView()) - self.validation_returns_content_unchanged_if_already_valid_and_clean(validator) - - def test_form_validation_failure_raises_response_exception(self): - validator = self.MockFormResource(self.MockFormView()) - self.validation_failure_raises_response_exception(validator) - - def test_validation_does_not_allow_extra_fields_by_default(self): - validator = self.MockFormResource(self.MockFormView()) - self.validation_does_not_allow_extra_fields_by_default(validator) - - def test_validation_allows_extra_fields_if_explicitly_set(self): - validator = self.MockFormResource(self.MockFormView()) - self.validation_allows_extra_fields_if_explicitly_set(validator) - - def test_validation_allows_unknown_fields_if_explicitly_allowed(self): - validator = self.MockFormResource(self.MockFormView()) - self.validation_allows_unknown_fields_if_explicitly_allowed(validator) - - def test_validation_does_not_require_extra_fields_if_explicitly_set(self): - validator = self.MockFormResource(self.MockFormView()) - self.validation_does_not_require_extra_fields_if_explicitly_set(validator) - - def test_validation_failed_due_to_no_content_returns_appropriate_message(self): - validator = self.MockFormResource(self.MockFormView()) - self.validation_failed_due_to_no_content_returns_appropriate_message(validator) - - def test_validation_failed_due_to_field_error_returns_appropriate_message(self): - validator = self.MockFormResource(self.MockFormView()) - self.validation_failed_due_to_field_error_returns_appropriate_message(validator) - - def test_validation_failed_due_to_invalid_field_returns_appropriate_message(self): - validator = self.MockFormResource(self.MockFormView()) - self.validation_failed_due_to_invalid_field_returns_appropriate_message(validator) - - def test_validation_failed_due_to_multiple_errors_returns_appropriate_message(self): - validator = self.MockFormResource(self.MockFormView()) - self.validation_failed_due_to_multiple_errors_returns_appropriate_message(validator) - - # Same tests on ModelResource - - def test_modelform_validation_returns_content_unchanged_if_already_valid_and_clean(self): - validator = self.MockModelResource(self.MockModelFormView()) - self.validation_returns_content_unchanged_if_already_valid_and_clean(validator) - - def test_modelform_validation_failure_raises_response_exception(self): - validator = self.MockModelResource(self.MockModelFormView()) - self.validation_failure_raises_response_exception(validator) - - def test_modelform_validation_does_not_allow_extra_fields_by_default(self): - validator = self.MockModelResource(self.MockModelFormView()) - self.validation_does_not_allow_extra_fields_by_default(validator) - - def test_modelform_validation_allows_extra_fields_if_explicitly_set(self): - validator = self.MockModelResource(self.MockModelFormView()) - self.validation_allows_extra_fields_if_explicitly_set(validator) - - def test_modelform_validation_does_not_require_extra_fields_if_explicitly_set(self): - validator = self.MockModelResource(self.MockModelFormView()) - self.validation_does_not_require_extra_fields_if_explicitly_set(validator) - - def test_modelform_validation_failed_due_to_no_content_returns_appropriate_message(self): - validator = self.MockModelResource(self.MockModelFormView()) - self.validation_failed_due_to_no_content_returns_appropriate_message(validator) - - def test_modelform_validation_failed_due_to_field_error_returns_appropriate_message(self): - validator = self.MockModelResource(self.MockModelFormView()) - self.validation_failed_due_to_field_error_returns_appropriate_message(validator) - - def test_modelform_validation_failed_due_to_invalid_field_returns_appropriate_message(self): - validator = self.MockModelResource(self.MockModelFormView()) - self.validation_failed_due_to_invalid_field_returns_appropriate_message(validator) - - def test_modelform_validation_failed_due_to_multiple_errors_returns_appropriate_message(self): - validator = self.MockModelResource(self.MockModelFormView()) - self.validation_failed_due_to_multiple_errors_returns_appropriate_message(validator) - - -class TestModelFormValidator(TestCase): - """Tests specific to ModelFormValidatorMixin""" - - def setUp(self): - """Create a validator for a model with two fields and a property.""" - class MockModel(models.Model): - qwerty = models.CharField(max_length=256) - uiop = models.CharField(max_length=256, blank=True) - - @property - def readonly(self): - return 'read only' - - class MockResource(ModelResource): - model = MockModel - - class MockView(View): - resource = MockResource - - self.validator = MockResource(MockView) - - def test_property_fields_are_allowed_on_model_forms(self): - """Validation on ModelForms may include property fields that exist on the Model to be included in the input.""" - content = {'qwerty': 'example', 'uiop': 'example', 'readonly': 'read only'} - self.assertEqual(self.validator.validate_request(content, None), content) - - def test_property_fields_are_not_required_on_model_forms(self): - """Validation on ModelForms does not require property fields that exist on the Model to be included in the input.""" - content = {'qwerty': 'example', 'uiop': 'example'} - self.assertEqual(self.validator.validate_request(content, None), content) - - def test_extra_fields_not_allowed_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 = {'qwerty': 'example', 'uiop': 'example', 'readonly': 'read only', 'extra': 'extra'} - self.assertRaises(ErrorResponse, 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) - - def test_validate_does_not_require_blankable_fields_on_model_forms(self): - """Test standard ModelForm validation behaviour - fields with blank=True are not required.""" - content = {'qwerty': 'example', 'readonly': 'read only'} - self.validator.validate_request(content, None) - - def test_model_form_validator_uses_model_forms(self): - self.assertTrue(isinstance(self.validator.get_bound_form(), forms.ModelForm)) diff --git a/djangorestframework/tests/views.py b/djangorestframework/tests/views.py deleted file mode 100644 index 418b4b16..00000000 --- a/djangorestframework/tests/views.py +++ /dev/null @@ -1,137 +0,0 @@ -from django.core.urlresolvers import reverse -from django.conf.urls.defaults import patterns, url, include -from django.http import HttpResponse -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 MockViewFinal(View): - """View with final() override""" - - def final(self, request, response, *args, **kwargs): - return HttpResponse('{"test": "passed"}', content_type="application/json") - -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('', - url(r'^mock/$', MockView.as_view()), - url(r'^mock/final/$', MockViewFinal.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)), - url(r'^restframework/', include('djangorestframework.urls', namespace='djangorestframework')), -) - -class BaseViewTests(TestCase): - """Test the base view class of djangorestframework""" - urls = 'djangorestframework.tests.views' - - def test_view_call_final(self): - response = self.client.options('/mock/final/') - self.assertEqual(response['Content-Type'].split(';')[0], "application/json") - parser = JSONParser(None) - (data, files) = parser.parse(StringIO(response.content)) - self.assertEqual(data['test'], 'passed') - - 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 ExtraViewsTests(TestCase): - """Test the extra views djangorestframework provides""" - urls = 'djangorestframework.tests.views' - - def test_login_view(self): - """Ensure the login view exists""" - response = self.client.get(reverse('djangorestframework:login')) - self.assertEqual(response.status_code, 200) - self.assertEqual(response['Content-Type'].split(';')[0], 'text/html') - - def test_logout_view(self): - """Ensure the logout view exists""" - response = self.client.get(reverse('djangorestframework:logout')) - self.assertEqual(response.status_code, 200) - self.assertEqual(response['Content-Type'].split(';')[0], 'text/html') - - # TODO: Add login/logout behaviour tests - |
