From fd3f538e9f9ef5d4d929c107b9619e0735e426f1 Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Thu, 4 Apr 2013 21:48:23 +0100
Subject: Fix up view name/description tests
---
rest_framework/tests/description.py | 63 ++++++++++++++-----------------------
1 file changed, 23 insertions(+), 40 deletions(-)
(limited to 'rest_framework/tests')
diff --git a/rest_framework/tests/description.py b/rest_framework/tests/description.py
index 5b3315bc..52c1a34c 100644
--- a/rest_framework/tests/description.py
+++ b/rest_framework/tests/description.py
@@ -4,6 +4,7 @@ from __future__ import unicode_literals
from django.test import TestCase
from rest_framework.views import APIView
from rest_framework.compat import apply_markdown
+from rest_framework.utils.formatting import get_view_name, get_view_description
# We check that docstrings get nicely un-indented.
DESCRIPTION = """an example docstring
@@ -49,22 +50,16 @@ MARKED_DOWN_gte_21 = """
an example docstring
class TestViewNamesAndDescriptions(TestCase):
- def test_resource_name_uses_classname_by_default(self):
- """Ensure Resource names are based on the classname by default."""
+ def test_view_name_uses_class_name(self):
+ """
+ Ensure view names are based on the class name.
+ """
class MockView(APIView):
pass
- self.assertEqual(MockView().get_name(), 'Mock')
+ self.assertEqual(get_view_name(MockView), '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(APIView):
- def get_name(self):
- return example
- self.assertEqual(MockView().get_name(), example)
-
- def test_resource_description_uses_docstring_by_default(self):
- """Ensure Resource names are based on the docstring by default."""
+ def test_view_description_uses_docstring(self):
+ """Ensure view descriptions are based on the docstring."""
class MockView(APIView):
"""an example docstring
====================
@@ -81,44 +76,32 @@ class TestViewNamesAndDescriptions(TestCase):
# hash style header #"""
- self.assertEqual(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(APIView):
- """docstring"""
- def get_description(self):
- return example
- self.assertEqual(MockView().get_description(), example)
+ self.assertEqual(get_view_description(MockView), DESCRIPTION)
- def test_resource_description_supports_unicode(self):
+ def test_view_description_supports_unicode(self):
+ """
+ Unicode in docstrings should be respected.
+ """
class MockView(APIView):
"""Проверка"""
pass
- self.assertEqual(MockView().get_description(), "Проверка")
-
-
- 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(APIView):
- def get_description(self):
- return example
- self.assertEqual(MockView().get_description(), example)
+ self.assertEqual(get_view_description(MockView), "Проверка")
- 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."""
+ def test_view_description_can_be_empty(self):
+ """
+ Ensure that if a view has no docstring,
+ then it's description is the empty string.
+ """
class MockView(APIView):
pass
- self.assertEqual(MockView().get_description(), '')
+ self.assertEqual(get_view_description(MockView), '')
def test_markdown(self):
- """Ensure markdown to HTML works as expected"""
+ """
+ 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
--
cgit v1.2.3
From dc45bc7bfad64a17f3e5ed0f5a487bccc379aac2 Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Tue, 9 Apr 2013 19:01:01 +0100
Subject: Add lookup_kwarg
---
rest_framework/tests/filterset.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
(limited to 'rest_framework/tests')
diff --git a/rest_framework/tests/filterset.py b/rest_framework/tests/filterset.py
index 1a71558c..1e53a5cd 100644
--- a/rest_framework/tests/filterset.py
+++ b/rest_framework/tests/filterset.py
@@ -61,7 +61,7 @@ if django_filters:
class CommonFilteringTestCase(TestCase):
def _serialize_object(self, obj):
return {'id': obj.id, 'text': obj.text, 'decimal': obj.decimal, 'date': obj.date}
-
+
def setUp(self):
"""
Create 10 FilterableItem instances.
@@ -190,7 +190,7 @@ class IntegrationTestDetailFiltering(CommonFilteringTestCase):
Integration tests for filtered detail views.
"""
urls = 'rest_framework.tests.filterset'
-
+
def _get_url(self, item):
return reverse('detail-view', kwargs=dict(pk=item.pk))
@@ -221,7 +221,7 @@ class IntegrationTestDetailFiltering(CommonFilteringTestCase):
response = self.client.get('{url}?decimal={param}'.format(url=self._get_url(low_item), param=search_decimal))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, low_item_data)
-
+
# Tests that multiple filters works.
search_decimal = Decimal('5.25')
search_date = datetime.date(2012, 10, 2)
--
cgit v1.2.3
From 76e039d70e8fc7f1d5c65180cb544abab81e600e Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Wed, 10 Apr 2013 22:38:02 +0100
Subject: First pass on automatically including reverse relationship
---
rest_framework/tests/serializer.py | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
(limited to 'rest_framework/tests')
diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py
index 05217f35..3a94fad5 100644
--- a/rest_framework/tests/serializer.py
+++ b/rest_framework/tests/serializer.py
@@ -738,6 +738,43 @@ class ManyRelatedTests(TestCase):
self.assertEqual(serializer.data, expected)
+ def test_include_reverse_relations(self):
+ post = BlogPost.objects.create(title="Test blog post")
+ post.blogpostcomment_set.create(text="I hate this blog post")
+ post.blogpostcomment_set.create(text="I love this blog post")
+
+ class BlogPostSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = BlogPost
+ fields = ('id', 'title', 'blogpostcomment_set')
+
+ serializer = BlogPostSerializer(instance=post)
+ expected = {
+ 'id': 1, 'title': 'Test blog post', 'blogpostcomment_set': [1, 2]
+ }
+ self.assertEqual(serializer.data, expected)
+
+ def test_depth_include_reverse_relations(self):
+ post = BlogPost.objects.create(title="Test blog post")
+ post.blogpostcomment_set.create(text="I hate this blog post")
+ post.blogpostcomment_set.create(text="I love this blog post")
+
+ class BlogPostSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = BlogPost
+ fields = ('id', 'title', 'blogpostcomment_set')
+ depth = 1
+
+ serializer = BlogPostSerializer(instance=post)
+ expected = {
+ 'id': 1, 'title': 'Test blog post',
+ 'blogpostcomment_set': [
+ {'id': 1, 'text': 'I hate this blog post', 'blog_post': 1},
+ {'id': 2, 'text': 'I love this blog post', 'blog_post': 1}
+ ]
+ }
+ self.assertEqual(serializer.data, expected)
+
def test_callable_source(self):
post = BlogPost.objects.create(title="Test blog post")
post.blogpostcomment_set.create(text="I love this blog post")
--
cgit v1.2.3
From 750451f5b4de61684f4a4e69dd5776bd84ac054c Mon Sep 17 00:00:00 2001
From: Johannes Spielmann
Date: Sun, 14 Apr 2013 18:30:44 +0200
Subject: adding test case for generic view with overriden get_object()
---
rest_framework/tests/generics.py | 173 +++++++++++++++++++++++++++++++++++++++
1 file changed, 173 insertions(+)
(limited to 'rest_framework/tests')
diff --git a/rest_framework/tests/generics.py b/rest_framework/tests/generics.py
index f564890c..b40b0102 100644
--- a/rest_framework/tests/generics.py
+++ b/rest_framework/tests/generics.py
@@ -24,6 +24,28 @@ class InstanceView(generics.RetrieveUpdateDestroyAPIView):
model = BasicModel
+class InstanceDetailView(generics.RetrieveUpdateDestroyAPIView):
+ """
+ Example detail view for override of get_object().
+ """
+
+ # we have to implement this too, otherwise we can't be sure that get_object
+ # will be called
+ def get_serializer(self, instance=None, data=None, files=None, partial=None):
+ class InstanceDetailSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = BasicModel
+ return InstanceDetailSerializer(instance=instance, data=data, files=files, partial=partial)
+
+ def get_object(self):
+ try:
+ pk = int(self.kwargs['pk'])
+ self.object = BasicModel.objects.get(id=pk)
+ return self.object
+ except BasicModel.DoesNotExist:
+ return self.permission_denied(self.request)
+
+
class SlugSerializer(serializers.ModelSerializer):
slug = serializers.Field() # read only
@@ -301,6 +323,157 @@ class TestInstanceView(TestCase):
new_obj = SlugBasedModel.objects.get(slug='test_slug')
self.assertEqual(new_obj.text, 'foobar')
+class TestInstanceDetailView(TestCase):
+ """
+ Test cases for a RetrieveUpdateDestroyAPIView that does NOT use the
+ queryset/model mechanism but instead overrides get_object()
+ """
+ def setUp(self):
+ """
+ Create 3 BasicModel intances.
+ """
+ items = ['foo', 'bar', 'baz']
+ for item in items:
+ BasicModel(text=item).save()
+ self.objects = BasicModel.objects
+ self.data = [
+ {'id': obj.id, 'text': obj.text}
+ for obj in self.objects.all()
+ ]
+ self.view_class = InstanceDetailView
+ self.view = InstanceDetailView.as_view()
+
+ def test_get_instance_view(self):
+ """
+ GET requests to RetrieveUpdateDestroyAPIView should return a single object.
+ """
+ request = factory.get('/1')
+ with self.assertNumQueries(1):
+ response = self.view(request, pk=1).render()
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertEqual(response.data, self.data[0])
+
+ def test_post_instance_view(self):
+ """
+ POST requests to RetrieveUpdateDestroyAPIView should not be allowed
+ """
+ content = {'text': 'foobar'}
+ request = factory.post('/', json.dumps(content),
+ content_type='application/json')
+ with self.assertNumQueries(0):
+ response = self.view(request).render()
+ self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)
+ self.assertEqual(response.data, {"detail": "Method 'POST' not allowed."})
+
+ def test_put_instance_view(self):
+ """
+ PUT requests to RetrieveUpdateDestroyAPIView should update an object.
+ """
+ content = {'text': 'foobar'}
+ request = factory.put('/1', json.dumps(content),
+ content_type='application/json')
+ with self.assertNumQueries(2):
+ response = self.view(request, pk='1').render()
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertEqual(response.data, {'id': 1, 'text': 'foobar'})
+ updated = self.objects.get(id=1)
+ self.assertEqual(updated.text, 'foobar')
+
+ def test_patch_instance_view(self):
+ """
+ PATCH requests to RetrieveUpdateDestroyAPIView should update an object.
+ """
+ content = {'text': 'foobar'}
+ request = factory.patch('/1', json.dumps(content),
+ content_type='application/json')
+
+ with self.assertNumQueries(2):
+ response = self.view(request, pk=1).render()
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertEqual(response.data, {'id': 1, 'text': 'foobar'})
+ updated = self.objects.get(id=1)
+ self.assertEqual(updated.text, 'foobar')
+
+ def test_delete_instance_view(self):
+ """
+ DELETE requests to RetrieveUpdateDestroyAPIView should delete an object.
+ """
+ request = factory.delete('/1')
+ with self.assertNumQueries(2):
+ response = self.view(request, pk=1).render()
+ self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
+ self.assertEqual(response.content, six.b(''))
+ ids = [obj.id for obj in self.objects.all()]
+ self.assertEqual(ids, [2, 3])
+
+ def test_options_instance_view(self):
+ """
+ OPTIONS requests to RetrieveUpdateDestroyAPIView should return metadata
+ """
+ request = factory.options('/')
+ with self.assertNumQueries(0):
+ response = self.view(request).render()
+ expected = {
+ 'parses': [
+ 'application/json',
+ 'application/x-www-form-urlencoded',
+ 'multipart/form-data'
+ ],
+ 'renders': [
+ 'application/json',
+ 'text/html'
+ ],
+ 'name': 'Instance Detail',
+ 'description': 'Example detail view for override of get_object().'
+ }
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertEqual(response.data, expected)
+
+ def test_put_cannot_set_id(self):
+ """
+ PUT requests to create a new object should not be able to set the id.
+ """
+ content = {'id': 999, 'text': 'foobar'}
+ request = factory.put('/1', json.dumps(content),
+ content_type='application/json')
+ with self.assertNumQueries(2):
+ response = self.view(request, pk=1).render()
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertEqual(response.data, {'id': 1, 'text': 'foobar'})
+ updated = self.objects.get(id=1)
+ self.assertEqual(updated.text, 'foobar')
+
+ def test_put_to_deleted_instance(self):
+ """
+ PUT requests to RetrieveUpdateDestroyAPIView should create an object
+ if it does not currently exist. In our DetailView, however,
+ we cannot access any other id's than those that already exist.
+ See the InstanceView for the normal behaviour.
+ """
+ self.objects.get(id=1).delete()
+ content = {'text': 'foobar'}
+ request = factory.put('/1', json.dumps(content),
+ content_type='application/json')
+ with self.assertNumQueries(1):
+ response = self.view(request, pk=5).render()
+ self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
+
+ def test_put_as_create_on_id_based_url(self):
+ """
+ PUT requests to RetrieveUpdateDestroyAPIView should create an object
+ at the requested url if it doesn't exist. In our DetailView, however,
+ we cannot access any other id's than those that already exist.
+ See the InstanceView for the normal behaviour.
+ """
+ content = {'text': 'foobar'}
+ # pk fields can not be created on demand, only the database can set the pk for a new object
+ request = factory.put('/5', json.dumps(content),
+ content_type='application/json')
+ with self.assertNumQueries(1):
+ response = self.view(request, pk=5).render()
+ self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
+
+
# Regression test for #285
--
cgit v1.2.3
From ad436d966fa9ee2f5817aa5c26612c82558c4262 Mon Sep 17 00:00:00 2001
From: Stephan Groß
Date: Mon, 15 Apr 2013 12:40:18 +0200
Subject: Add DecimalField support
---
rest_framework/tests/fields.py | 165 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 165 insertions(+)
(limited to 'rest_framework/tests')
diff --git a/rest_framework/tests/fields.py b/rest_framework/tests/fields.py
index 19c663d8..f833aa32 100644
--- a/rest_framework/tests/fields.py
+++ b/rest_framework/tests/fields.py
@@ -3,12 +3,14 @@ General serializer field tests.
"""
from __future__ import unicode_literals
import datetime
+from decimal import Decimal
from django.db import models
from django.test import TestCase
from django.core import validators
from rest_framework import serializers
+from rest_framework.serializers import Serializer
class TimestampedModel(models.Model):
@@ -481,3 +483,166 @@ class TimeFieldTest(TestCase):
self.assertEqual('04 - 00 [000000]', result_1)
self.assertEqual('04 - 59 [000000]', result_2)
self.assertEqual('04 - 59 [000200]', result_3)
+
+
+class DecimalFieldTest(TestCase):
+ """
+ Tests for the DecimalField from_native() and to_native() behavior
+ """
+
+ def test_from_native_string(self):
+ """
+ Make sure from_native() accepts string values
+ """
+ f = serializers.DecimalField()
+ result_1 = f.from_native('9000')
+ result_2 = f.from_native('1.00000001')
+
+ self.assertEqual(Decimal('9000'), result_1)
+ self.assertEqual(Decimal('1.00000001'), result_2)
+
+ def test_from_native_invalid_string(self):
+ """
+ Make sure from_native() raises ValidationError on passing invalid string
+ """
+ f = serializers.DecimalField()
+
+ try:
+ f.from_native('123.45.6')
+ except validators.ValidationError as e:
+ self.assertEqual(e.messages, ["Enter a number."])
+ else:
+ self.fail("ValidationError was not properly raised")
+
+ def test_from_native_integer(self):
+ """
+ Make sure from_native() accepts integer values
+ """
+ f = serializers.DecimalField()
+ result = f.from_native(9000)
+
+ self.assertEqual(Decimal('9000'), result)
+
+ def test_from_native_float(self):
+ """
+ Make sure from_native() accepts float values
+ """
+ f = serializers.DecimalField()
+ result = f.from_native(1.00000001)
+
+ self.assertEqual(Decimal('1.00000001'), result)
+
+ def test_from_native_empty(self):
+ """
+ Make sure from_native() returns None on empty param.
+ """
+ f = serializers.DecimalField()
+ result = f.from_native('')
+
+ self.assertEqual(result, None)
+
+ def test_from_native_none(self):
+ """
+ Make sure from_native() returns None on None param.
+ """
+ f = serializers.DecimalField()
+ result = f.from_native(None)
+
+ self.assertEqual(result, None)
+
+ def test_to_native(self):
+ """
+ Make sure to_native() returns Decimal as string.
+ """
+ f = serializers.DecimalField()
+
+ result_1 = f.to_native(Decimal('9000'))
+ result_2 = f.to_native(Decimal('1.00000001'))
+
+ self.assertEqual('9000', result_1)
+ self.assertEqual('1.00000001', result_2)
+
+ def test_to_native_none(self):
+ """
+ Make sure from_native() returns None on None param.
+ """
+ f = serializers.DecimalField(required=False)
+ self.assertEqual(None, f.to_native(None))
+
+ def test_valid_serialization(self):
+ """
+ Make sure the serializer works correctly
+ """
+ class DecimalSerializer(Serializer):
+ decimal_field = serializers.DecimalField(max_value=9010,
+ min_value=9000,
+ max_digits=6,
+ decimal_places=2)
+
+ self.assertTrue(DecimalSerializer(data={'decimal_field': '9001'}).is_valid())
+ self.assertTrue(DecimalSerializer(data={'decimal_field': '9001.2'}).is_valid())
+ self.assertTrue(DecimalSerializer(data={'decimal_field': '9001.23'}).is_valid())
+
+ self.assertFalse(DecimalSerializer(data={'decimal_field': '8000'}).is_valid())
+ self.assertFalse(DecimalSerializer(data={'decimal_field': '9900'}).is_valid())
+ self.assertFalse(DecimalSerializer(data={'decimal_field': '9001.234'}).is_valid())
+
+ def test_raise_max_value(self):
+ """
+ Make sure max_value violations raises ValidationError
+ """
+ class DecimalSerializer(Serializer):
+ decimal_field = serializers.DecimalField(max_value=100)
+
+ s = DecimalSerializer(data={'decimal_field': '123'})
+
+ self.assertFalse(s.is_valid())
+ self.assertEqual(s.errors, {'decimal_field': [u'Ensure this value is less than or equal to 100.']})
+
+ def test_raise_min_value(self):
+ """
+ Make sure min_value violations raises ValidationError
+ """
+ class DecimalSerializer(Serializer):
+ decimal_field = serializers.DecimalField(min_value=100)
+
+ s = DecimalSerializer(data={'decimal_field': '99'})
+
+ self.assertFalse(s.is_valid())
+ self.assertEqual(s.errors, {'decimal_field': [u'Ensure this value is greater than or equal to 100.']})
+
+ def test_raise_max_digits(self):
+ """
+ Make sure max_digits violations raises ValidationError
+ """
+ class DecimalSerializer(Serializer):
+ decimal_field = serializers.DecimalField(max_digits=5)
+
+ s = DecimalSerializer(data={'decimal_field': '123.456'})
+
+ self.assertFalse(s.is_valid())
+ self.assertEqual(s.errors, {'decimal_field': [u'Ensure that there are no more than 5 digits in total.']})
+
+ def test_raise_max_decimal_places(self):
+ """
+ Make sure max_decimal_places violations raises ValidationError
+ """
+ class DecimalSerializer(Serializer):
+ decimal_field = serializers.DecimalField(decimal_places=3)
+
+ s = DecimalSerializer(data={'decimal_field': '123.4567'})
+
+ self.assertFalse(s.is_valid())
+ self.assertEqual(s.errors, {'decimal_field': [u'Ensure that there are no more than 3 decimal places.']})
+
+ def test_raise_max_whole_digits(self):
+ """
+ Make sure max_whole_digits violations raises ValidationError
+ """
+ class DecimalSerializer(Serializer):
+ decimal_field = serializers.DecimalField(max_digits=4, decimal_places=3)
+
+ s = DecimalSerializer(data={'decimal_field': '12345.6'})
+
+ self.assertFalse(s.is_valid())
+ self.assertEqual(s.errors, {'decimal_field': [u'Ensure that there are no more than 4 digits in total.']})
\ No newline at end of file
--
cgit v1.2.3
From 37f7d8bc0f00feb1a4d23c0e163eab8b47faaec3 Mon Sep 17 00:00:00 2001
From: Stephan Groß
Date: Mon, 15 Apr 2013 12:55:29 +0200
Subject: Fix unicodes
---
rest_framework/tests/fields.py | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
(limited to 'rest_framework/tests')
diff --git a/rest_framework/tests/fields.py b/rest_framework/tests/fields.py
index f833aa32..597180b4 100644
--- a/rest_framework/tests/fields.py
+++ b/rest_framework/tests/fields.py
@@ -597,7 +597,7 @@ class DecimalFieldTest(TestCase):
s = DecimalSerializer(data={'decimal_field': '123'})
self.assertFalse(s.is_valid())
- self.assertEqual(s.errors, {'decimal_field': [u'Ensure this value is less than or equal to 100.']})
+ self.assertEqual(s.errors, {'decimal_field': ['Ensure this value is less than or equal to 100.']})
def test_raise_min_value(self):
"""
@@ -609,7 +609,7 @@ class DecimalFieldTest(TestCase):
s = DecimalSerializer(data={'decimal_field': '99'})
self.assertFalse(s.is_valid())
- self.assertEqual(s.errors, {'decimal_field': [u'Ensure this value is greater than or equal to 100.']})
+ self.assertEqual(s.errors, {'decimal_field': ['Ensure this value is greater than or equal to 100.']})
def test_raise_max_digits(self):
"""
@@ -621,7 +621,7 @@ class DecimalFieldTest(TestCase):
s = DecimalSerializer(data={'decimal_field': '123.456'})
self.assertFalse(s.is_valid())
- self.assertEqual(s.errors, {'decimal_field': [u'Ensure that there are no more than 5 digits in total.']})
+ self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 5 digits in total.']})
def test_raise_max_decimal_places(self):
"""
@@ -633,7 +633,7 @@ class DecimalFieldTest(TestCase):
s = DecimalSerializer(data={'decimal_field': '123.4567'})
self.assertFalse(s.is_valid())
- self.assertEqual(s.errors, {'decimal_field': [u'Ensure that there are no more than 3 decimal places.']})
+ self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 3 decimal places.']})
def test_raise_max_whole_digits(self):
"""
@@ -645,4 +645,4 @@ class DecimalFieldTest(TestCase):
s = DecimalSerializer(data={'decimal_field': '12345.6'})
self.assertFalse(s.is_valid())
- self.assertEqual(s.errors, {'decimal_field': [u'Ensure that there are no more than 4 digits in total.']})
\ No newline at end of file
+ self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 4 digits in total.']})
\ No newline at end of file
--
cgit v1.2.3
From cac669702596cdf768971267e6355fb9223a69e8 Mon Sep 17 00:00:00 2001
From: Stephan Groß
Date: Mon, 15 Apr 2013 15:24:14 +0200
Subject: Return Decimal instance instead of string
---
rest_framework/tests/fields.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
(limited to 'rest_framework/tests')
diff --git a/rest_framework/tests/fields.py b/rest_framework/tests/fields.py
index 597180b4..3cdfa0f6 100644
--- a/rest_framework/tests/fields.py
+++ b/rest_framework/tests/fields.py
@@ -559,8 +559,8 @@ class DecimalFieldTest(TestCase):
result_1 = f.to_native(Decimal('9000'))
result_2 = f.to_native(Decimal('1.00000001'))
- self.assertEqual('9000', result_1)
- self.assertEqual('1.00000001', result_2)
+ self.assertEqual(Decimal('9000'), result_1)
+ self.assertEqual(Decimal('1.00000001'), result_2)
def test_to_native_none(self):
"""
--
cgit v1.2.3
From 37fe0bf0de25d28d792a291d5a84987ab71c4cb6 Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Wed, 17 Apr 2013 09:03:24 +0100
Subject: Remove unneccessary tests from #789, and bit of cleanup.
---
rest_framework/tests/generics.py | 165 ++++-----------------------------------
1 file changed, 17 insertions(+), 148 deletions(-)
(limited to 'rest_framework/tests')
diff --git a/rest_framework/tests/generics.py b/rest_framework/tests/generics.py
index b40b0102..4a13389a 100644
--- a/rest_framework/tests/generics.py
+++ b/rest_framework/tests/generics.py
@@ -1,5 +1,6 @@
from __future__ import unicode_literals
from django.db import models
+from django.shortcuts import get_object_or_404
from django.test import TestCase
from rest_framework import generics, serializers, status
from rest_framework.tests.utils import RequestFactory
@@ -24,28 +25,6 @@ class InstanceView(generics.RetrieveUpdateDestroyAPIView):
model = BasicModel
-class InstanceDetailView(generics.RetrieveUpdateDestroyAPIView):
- """
- Example detail view for override of get_object().
- """
-
- # we have to implement this too, otherwise we can't be sure that get_object
- # will be called
- def get_serializer(self, instance=None, data=None, files=None, partial=None):
- class InstanceDetailSerializer(serializers.ModelSerializer):
- class Meta:
- model = BasicModel
- return InstanceDetailSerializer(instance=instance, data=data, files=files, partial=partial)
-
- def get_object(self):
- try:
- pk = int(self.kwargs['pk'])
- self.object = BasicModel.objects.get(id=pk)
- return self.object
- except BasicModel.DoesNotExist:
- return self.permission_denied(self.request)
-
-
class SlugSerializer(serializers.ModelSerializer):
slug = serializers.Field() # read only
@@ -323,7 +302,8 @@ class TestInstanceView(TestCase):
new_obj = SlugBasedModel.objects.get(slug='test_slug')
self.assertEqual(new_obj.text, 'foobar')
-class TestInstanceDetailView(TestCase):
+
+class TestOverriddenGetObject(TestCase):
"""
Test cases for a RetrieveUpdateDestroyAPIView that does NOT use the
queryset/model mechanism but instead overrides get_object()
@@ -340,139 +320,28 @@ class TestInstanceDetailView(TestCase):
{'id': obj.id, 'text': obj.text}
for obj in self.objects.all()
]
- self.view_class = InstanceDetailView
- self.view = InstanceDetailView.as_view()
- def test_get_instance_view(self):
- """
- GET requests to RetrieveUpdateDestroyAPIView should return a single object.
- """
- request = factory.get('/1')
- with self.assertNumQueries(1):
- response = self.view(request, pk=1).render()
- self.assertEqual(response.status_code, status.HTTP_200_OK)
- self.assertEqual(response.data, self.data[0])
+ class OverriddenGetObjectView(generics.RetrieveUpdateDestroyAPIView):
+ """
+ Example detail view for override of get_object().
+ """
+ model = BasicModel
- def test_post_instance_view(self):
- """
- POST requests to RetrieveUpdateDestroyAPIView should not be allowed
- """
- content = {'text': 'foobar'}
- request = factory.post('/', json.dumps(content),
- content_type='application/json')
- with self.assertNumQueries(0):
- response = self.view(request).render()
- self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)
- self.assertEqual(response.data, {"detail": "Method 'POST' not allowed."})
-
- def test_put_instance_view(self):
- """
- PUT requests to RetrieveUpdateDestroyAPIView should update an object.
- """
- content = {'text': 'foobar'}
- request = factory.put('/1', json.dumps(content),
- content_type='application/json')
- with self.assertNumQueries(2):
- response = self.view(request, pk='1').render()
- self.assertEqual(response.status_code, status.HTTP_200_OK)
- self.assertEqual(response.data, {'id': 1, 'text': 'foobar'})
- updated = self.objects.get(id=1)
- self.assertEqual(updated.text, 'foobar')
-
- def test_patch_instance_view(self):
- """
- PATCH requests to RetrieveUpdateDestroyAPIView should update an object.
- """
- content = {'text': 'foobar'}
- request = factory.patch('/1', json.dumps(content),
- content_type='application/json')
-
- with self.assertNumQueries(2):
- response = self.view(request, pk=1).render()
- self.assertEqual(response.status_code, status.HTTP_200_OK)
- self.assertEqual(response.data, {'id': 1, 'text': 'foobar'})
- updated = self.objects.get(id=1)
- self.assertEqual(updated.text, 'foobar')
-
- def test_delete_instance_view(self):
- """
- DELETE requests to RetrieveUpdateDestroyAPIView should delete an object.
- """
- request = factory.delete('/1')
- with self.assertNumQueries(2):
- response = self.view(request, pk=1).render()
- self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
- self.assertEqual(response.content, six.b(''))
- ids = [obj.id for obj in self.objects.all()]
- self.assertEqual(ids, [2, 3])
+ def get_object(self):
+ pk = int(self.kwargs['pk'])
+ return get_object_or_404(BasicModel.objects.all(), id=pk)
- def test_options_instance_view(self):
- """
- OPTIONS requests to RetrieveUpdateDestroyAPIView should return metadata
- """
- request = factory.options('/')
- with self.assertNumQueries(0):
- response = self.view(request).render()
- expected = {
- 'parses': [
- 'application/json',
- 'application/x-www-form-urlencoded',
- 'multipart/form-data'
- ],
- 'renders': [
- 'application/json',
- 'text/html'
- ],
- 'name': 'Instance Detail',
- 'description': 'Example detail view for override of get_object().'
- }
- self.assertEqual(response.status_code, status.HTTP_200_OK)
- self.assertEqual(response.data, expected)
+ self.view = OverriddenGetObjectView.as_view()
- def test_put_cannot_set_id(self):
+ def test_overridden_get_object_view(self):
"""
- PUT requests to create a new object should not be able to set the id.
+ GET requests to RetrieveUpdateDestroyAPIView should return a single object.
"""
- content = {'id': 999, 'text': 'foobar'}
- request = factory.put('/1', json.dumps(content),
- content_type='application/json')
- with self.assertNumQueries(2):
+ request = factory.get('/1')
+ with self.assertNumQueries(1):
response = self.view(request, pk=1).render()
self.assertEqual(response.status_code, status.HTTP_200_OK)
- self.assertEqual(response.data, {'id': 1, 'text': 'foobar'})
- updated = self.objects.get(id=1)
- self.assertEqual(updated.text, 'foobar')
-
- def test_put_to_deleted_instance(self):
- """
- PUT requests to RetrieveUpdateDestroyAPIView should create an object
- if it does not currently exist. In our DetailView, however,
- we cannot access any other id's than those that already exist.
- See the InstanceView for the normal behaviour.
- """
- self.objects.get(id=1).delete()
- content = {'text': 'foobar'}
- request = factory.put('/1', json.dumps(content),
- content_type='application/json')
- with self.assertNumQueries(1):
- response = self.view(request, pk=5).render()
- self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
-
- def test_put_as_create_on_id_based_url(self):
- """
- PUT requests to RetrieveUpdateDestroyAPIView should create an object
- at the requested url if it doesn't exist. In our DetailView, however,
- we cannot access any other id's than those that already exist.
- See the InstanceView for the normal behaviour.
- """
- content = {'text': 'foobar'}
- # pk fields can not be created on demand, only the database can set the pk for a new object
- request = factory.put('/5', json.dumps(content),
- content_type='application/json')
- with self.assertNumQueries(1):
- response = self.view(request, pk=5).render()
- self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
-
+ self.assertEqual(response.data, self.data[0])
# Regression test for #285
--
cgit v1.2.3
From 4bf1a09baeb885863e6028b97c2d51b26fb18534 Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Tue, 23 Apr 2013 11:31:38 +0100
Subject: Ensure implementation of reverse relations in 'fields' is backwards
compatible
---
rest_framework/tests/relations_hyperlink.py | 16 +++++++++-------
rest_framework/tests/relations_nested.py | 24 ++++++++----------------
rest_framework/tests/relations_pk.py | 17 ++++++++++-------
3 files changed, 27 insertions(+), 30 deletions(-)
(limited to 'rest_framework/tests')
diff --git a/rest_framework/tests/relations_hyperlink.py b/rest_framework/tests/relations_hyperlink.py
index b5702a48..b1eed9a7 100644
--- a/rest_framework/tests/relations_hyperlink.py
+++ b/rest_framework/tests/relations_hyperlink.py
@@ -26,42 +26,44 @@ urlpatterns = patterns('',
)
+# ManyToMany
class ManyToManyTargetSerializer(serializers.HyperlinkedModelSerializer):
- sources = serializers.HyperlinkedRelatedField(many=True, view_name='manytomanysource-detail')
-
class Meta:
model = ManyToManyTarget
+ fields = ('url', 'name', 'sources')
class ManyToManySourceSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = ManyToManySource
+ fields = ('url', 'name', 'targets')
+# ForeignKey
class ForeignKeyTargetSerializer(serializers.HyperlinkedModelSerializer):
- sources = serializers.HyperlinkedRelatedField(many=True, view_name='foreignkeysource-detail')
-
class Meta:
model = ForeignKeyTarget
+ fields = ('url', 'name', 'sources')
class ForeignKeySourceSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = ForeignKeySource
+ fields = ('url', 'name', 'target')
# Nullable ForeignKey
class NullableForeignKeySourceSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = NullableForeignKeySource
+ fields = ('url', 'name', 'target')
-# OneToOne
+# Nullable OneToOne
class NullableOneToOneTargetSerializer(serializers.HyperlinkedModelSerializer):
- nullable_source = serializers.HyperlinkedRelatedField(view_name='nullableonetoonesource-detail')
-
class Meta:
model = OneToOneTarget
+ fields = ('url', 'name', 'nullable_source')
# TODO: Add test that .data cannot be accessed prior to .is_valid
diff --git a/rest_framework/tests/relations_nested.py b/rest_framework/tests/relations_nested.py
index a125ba65..f6d006b3 100644
--- a/rest_framework/tests/relations_nested.py
+++ b/rest_framework/tests/relations_nested.py
@@ -5,39 +5,31 @@ from rest_framework.tests.models import ForeignKeyTarget, ForeignKeySource, Null
class ForeignKeySourceSerializer(serializers.ModelSerializer):
- class Meta:
- depth = 1
- model = ForeignKeySource
-
-
-class FlatForeignKeySourceSerializer(serializers.ModelSerializer):
class Meta:
model = ForeignKeySource
+ fields = ('id', 'name', 'target')
+ depth = 1
class ForeignKeyTargetSerializer(serializers.ModelSerializer):
- sources = FlatForeignKeySourceSerializer(many=True)
-
class Meta:
model = ForeignKeyTarget
+ fields = ('id', 'name', 'sources')
+ depth = 1
class NullableForeignKeySourceSerializer(serializers.ModelSerializer):
class Meta:
- depth = 1
model = NullableForeignKeySource
-
-
-class NullableOneToOneSourceSerializer(serializers.ModelSerializer):
- class Meta:
- model = NullableOneToOneSource
+ fields = ('id', 'name', 'target')
+ depth = 1
class NullableOneToOneTargetSerializer(serializers.ModelSerializer):
- nullable_source = NullableOneToOneSourceSerializer()
-
class Meta:
model = OneToOneTarget
+ fields = ('id', 'name', 'nullable_source')
+ depth = 1
class ReverseForeignKeyTests(TestCase):
diff --git a/rest_framework/tests/relations_pk.py b/rest_framework/tests/relations_pk.py
index f08e1808..5ce8b567 100644
--- a/rest_framework/tests/relations_pk.py
+++ b/rest_framework/tests/relations_pk.py
@@ -5,41 +5,44 @@ from rest_framework.tests.models import ManyToManyTarget, ManyToManySource, Fore
from rest_framework.compat import six
+# ManyToMany
class ManyToManyTargetSerializer(serializers.ModelSerializer):
- sources = serializers.PrimaryKeyRelatedField(many=True)
-
class Meta:
model = ManyToManyTarget
+ fields = ('id', 'name', 'sources')
class ManyToManySourceSerializer(serializers.ModelSerializer):
class Meta:
model = ManyToManySource
+ fields = ('id', 'name', 'targets')
+# ForeignKey
class ForeignKeyTargetSerializer(serializers.ModelSerializer):
- sources = serializers.PrimaryKeyRelatedField(many=True)
-
class Meta:
model = ForeignKeyTarget
+ fields = ('id', 'name', 'sources')
class ForeignKeySourceSerializer(serializers.ModelSerializer):
class Meta:
model = ForeignKeySource
+ fields = ('id', 'name', 'target')
+# Nullable ForeignKey
class NullableForeignKeySourceSerializer(serializers.ModelSerializer):
class Meta:
model = NullableForeignKeySource
+ fields = ('id', 'name', 'target')
-# OneToOne
+# Nullable OneToOne
class NullableOneToOneTargetSerializer(serializers.ModelSerializer):
- nullable_source = serializers.PrimaryKeyRelatedField()
-
class Meta:
model = OneToOneTarget
+ fields = ('id', 'name', 'nullable_source')
# TODO: Add test that .data cannot be accessed prior to .is_valid
--
cgit v1.2.3
From 3b0fa3ebaa9d42723d970bb88be0dfe2586d1a5e Mon Sep 17 00:00:00 2001
From: JC
Date: Sat, 27 Apr 2013 13:10:39 -0700
Subject: Changed DepthTest to have depth=2
---
rest_framework/tests/serializer.py | 31 +++++++++++++++++++------------
1 file changed, 19 insertions(+), 12 deletions(-)
(limited to 'rest_framework/tests')
diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py
index 05217f35..bd874253 100644
--- a/rest_framework/tests/serializer.py
+++ b/rest_framework/tests/serializer.py
@@ -3,7 +3,7 @@ from django.utils.datastructures import MultiValueDict
from django.test import TestCase
from rest_framework import serializers
from rest_framework.tests.models import (HasPositiveIntegerAsChoice, Album, ActionItem, Anchor, BasicModel,
- BlankFieldModel, BlogPost, Book, CallableDefaultValueModel, DefaultValueModel,
+ BlankFieldModel, BlogPost, BlogPostComment, Book, CallableDefaultValueModel, DefaultValueModel,
ManyToManyModel, Person, ReadOnlyManyToManyModel, Photo)
import datetime
import pickle
@@ -767,8 +767,6 @@ class RelatedTraversalTest(TestCase):
post = BlogPost.objects.create(title="Test blog post", writer=user)
post.blogpostcomment_set.create(text="I love this blog post")
- from rest_framework.tests.models import BlogPostComment
-
class PersonSerializer(serializers.ModelSerializer):
class Meta:
model = Person
@@ -968,23 +966,26 @@ class SerializerPickleTests(TestCase):
class DepthTest(TestCase):
def test_implicit_nesting(self):
+
writer = Person.objects.create(name="django", age=1)
post = BlogPost.objects.create(title="Test blog post", writer=writer)
+ comment = BlogPostComment.objects.create(text="Test blog post comment", blog_post=post)
- class BlogPostSerializer(serializers.ModelSerializer):
+ class BlogPostCommentSerializer(serializers.ModelSerializer):
class Meta:
- model = BlogPost
- depth = 1
+ model = BlogPostComment
+ depth = 2
- serializer = BlogPostSerializer(instance=post)
- expected = {'id': 1, 'title': 'Test blog post',
- 'writer': {'id': 1, 'name': 'django', 'age': 1}}
+ serializer = BlogPostCommentSerializer(instance=comment)
+ expected = {'id': 1, 'text': 'Test blog post comment', 'blog_post': {'id': 1, 'title': 'Test blog post',
+ 'writer': {'id': 1, 'name': 'django', 'age': 1}}}
self.assertEqual(serializer.data, expected)
def test_explicit_nesting(self):
writer = Person.objects.create(name="django", age=1)
post = BlogPost.objects.create(title="Test blog post", writer=writer)
+ comment = BlogPostComment.objects.create(text="Test blog post comment", blog_post=post)
class PersonSerializer(serializers.ModelSerializer):
class Meta:
@@ -996,9 +997,15 @@ class DepthTest(TestCase):
class Meta:
model = BlogPost
- serializer = BlogPostSerializer(instance=post)
- expected = {'id': 1, 'title': 'Test blog post',
- 'writer': {'id': 1, 'name': 'django', 'age': 1}}
+ class BlogPostCommentSerializer(serializers.ModelSerializer):
+ blog_post = BlogPostSerializer()
+
+ class Meta:
+ model = BlogPostComment
+
+ serializer = BlogPostCommentSerializer(instance=comment)
+ expected = {'id': 1, 'text': 'Test blog post comment', 'blog_post': {'id': 1, 'title': 'Test blog post',
+ 'writer': {'id': 1, 'name': 'django', 'age': 1}}}
self.assertEqual(serializer.data, expected)
--
cgit v1.2.3
From dc7b1d643020cac5d585aac42f98962cc7aa6bf7 Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Mon, 29 Apr 2013 12:45:00 +0100
Subject: 2.2's PendingDeprecationWarnings now become DeprecationWarnings.
2.3's PendingDeprecationWarnings added.
---
rest_framework/tests/serializer.py | 5 ++---
rest_framework/tests/serializer_nested.py | 4 ++--
2 files changed, 4 insertions(+), 5 deletions(-)
(limited to 'rest_framework/tests')
diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py
index 3a94fad5..ae8d09dc 100644
--- a/rest_framework/tests/serializer.py
+++ b/rest_framework/tests/serializer.py
@@ -357,7 +357,6 @@ class CustomValidationTests(TestCase):
def validate_email(self, attrs, source):
value = attrs[source]
-
return attrs
def validate_content(self, attrs, source):
@@ -1103,7 +1102,7 @@ class DeserializeListTestCase(TestCase):
def test_no_errors(self):
data = [self.data.copy() for x in range(0, 3)]
- serializer = CommentSerializer(data=data)
+ serializer = CommentSerializer(data=data, many=True)
self.assertTrue(serializer.is_valid())
self.assertTrue(isinstance(serializer.object, list))
self.assertTrue(
@@ -1115,7 +1114,7 @@ class DeserializeListTestCase(TestCase):
invalid_item['email'] = ''
data = [self.data.copy(), invalid_item, self.data.copy()]
- serializer = CommentSerializer(data=data)
+ serializer = CommentSerializer(data=data, many=True)
self.assertFalse(serializer.is_valid())
expected = [{}, {'email': ['This field is required.']}, {}]
self.assertEqual(serializer.errors, expected)
diff --git a/rest_framework/tests/serializer_nested.py b/rest_framework/tests/serializer_nested.py
index 6a29c652..71d0e24b 100644
--- a/rest_framework/tests/serializer_nested.py
+++ b/rest_framework/tests/serializer_nested.py
@@ -109,7 +109,7 @@ class WritableNestedSerializerBasicTests(TestCase):
}
]
- serializer = self.AlbumSerializer(data=data)
+ serializer = self.AlbumSerializer(data=data, many=True)
self.assertEqual(serializer.is_valid(), False)
self.assertEqual(serializer.errors, expected_errors)
@@ -241,6 +241,6 @@ class WritableNestedSerializerObjectTests(TestCase):
)
]
- serializer = self.AlbumSerializer(data=data)
+ serializer = self.AlbumSerializer(data=data, many=True)
self.assertEqual(serializer.is_valid(), True)
self.assertEqual(serializer.object, expected_object)
--
cgit v1.2.3
From 53f9d4a380ee0066cbee8382ae265ea6005d8c88 Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Mon, 29 Apr 2013 13:20:15 +0100
Subject: fields shortcut on views
---
rest_framework/tests/generics.py | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
(limited to 'rest_framework/tests')
diff --git a/rest_framework/tests/generics.py b/rest_framework/tests/generics.py
index 4a13389a..12c9b677 100644
--- a/rest_framework/tests/generics.py
+++ b/rest_framework/tests/generics.py
@@ -344,6 +344,30 @@ class TestOverriddenGetObject(TestCase):
self.assertEqual(response.data, self.data[0])
+class TestFieldsShortcut(TestCase):
+ """
+ Test cases for setting the `fields` attribute on a view.
+ """
+ def setUp(self):
+ class OverriddenFieldsView(generics.RetrieveUpdateDestroyAPIView):
+ model = BasicModel
+ fields = ('text',)
+
+ class RegularView(generics.RetrieveUpdateDestroyAPIView):
+ model = BasicModel
+
+ self.overridden_fields_view = OverriddenFieldsView()
+ self.regular_view = RegularView()
+
+ def test_overridden_fields_view(self):
+ Serializer = self.overridden_fields_view.get_serializer_class()
+ self.assertEqual(Serializer().fields.keys(), ['text'])
+
+ def test_not_overridden_fields_view(self):
+ Serializer = self.regular_view.get_serializer_class()
+ self.assertEqual(Serializer().fields.keys(), ['id', 'text'])
+
+
# Regression test for #285
class CommentSerializer(serializers.ModelSerializer):
--
cgit v1.2.3
From 0c1ab584d3d0898d47e0bce6beb5d7c39a55dd52 Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Mon, 29 Apr 2013 14:08:38 +0100
Subject: Tweaks for preferring .queryset over .model
---
rest_framework/tests/generics.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
(limited to 'rest_framework/tests')
diff --git a/rest_framework/tests/generics.py b/rest_framework/tests/generics.py
index 12c9b677..63ff1fc3 100644
--- a/rest_framework/tests/generics.py
+++ b/rest_framework/tests/generics.py
@@ -350,11 +350,11 @@ class TestFieldsShortcut(TestCase):
"""
def setUp(self):
class OverriddenFieldsView(generics.RetrieveUpdateDestroyAPIView):
- model = BasicModel
+ queryset = BasicModel.objects.all()
fields = ('text',)
class RegularView(generics.RetrieveUpdateDestroyAPIView):
- model = BasicModel
+ queryset = BasicModel.objects.all()
self.overridden_fields_view = OverriddenFieldsView()
self.regular_view = RegularView()
@@ -362,10 +362,12 @@ class TestFieldsShortcut(TestCase):
def test_overridden_fields_view(self):
Serializer = self.overridden_fields_view.get_serializer_class()
self.assertEqual(Serializer().fields.keys(), ['text'])
+ self.assertEqual(Serializer().opts.model, BasicModel)
def test_not_overridden_fields_view(self):
Serializer = self.regular_view.get_serializer_class()
self.assertEqual(Serializer().fields.keys(), ['id', 'text'])
+ self.assertEqual(Serializer().opts.model, BasicModel)
# Regression test for #285
--
cgit v1.2.3
From 21ae3a66917acf4ea57e8f7940ce1a6823a2ce92 Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Tue, 30 Apr 2013 08:24:33 +0100
Subject: Drop out attribute
---
rest_framework/tests/generics.py | 26 --------------------------
1 file changed, 26 deletions(-)
(limited to 'rest_framework/tests')
diff --git a/rest_framework/tests/generics.py b/rest_framework/tests/generics.py
index 63ff1fc3..4a13389a 100644
--- a/rest_framework/tests/generics.py
+++ b/rest_framework/tests/generics.py
@@ -344,32 +344,6 @@ class TestOverriddenGetObject(TestCase):
self.assertEqual(response.data, self.data[0])
-class TestFieldsShortcut(TestCase):
- """
- Test cases for setting the `fields` attribute on a view.
- """
- def setUp(self):
- class OverriddenFieldsView(generics.RetrieveUpdateDestroyAPIView):
- queryset = BasicModel.objects.all()
- fields = ('text',)
-
- class RegularView(generics.RetrieveUpdateDestroyAPIView):
- queryset = BasicModel.objects.all()
-
- self.overridden_fields_view = OverriddenFieldsView()
- self.regular_view = RegularView()
-
- def test_overridden_fields_view(self):
- Serializer = self.overridden_fields_view.get_serializer_class()
- self.assertEqual(Serializer().fields.keys(), ['text'])
- self.assertEqual(Serializer().opts.model, BasicModel)
-
- def test_not_overridden_fields_view(self):
- Serializer = self.regular_view.get_serializer_class()
- self.assertEqual(Serializer().fields.keys(), ['id', 'text'])
- self.assertEqual(Serializer().opts.model, BasicModel)
-
-
# Regression test for #285
class CommentSerializer(serializers.ModelSerializer):
--
cgit v1.2.3
From 8cabae22c5330da2e0a15a6d61ef038a6447756a Mon Sep 17 00:00:00 2001
From: Victor Shih
Date: Wed, 1 May 2013 21:26:40 -0700
Subject: Example and spelling fixes. Change "browseable" to "browsable" for
consistency.
---
rest_framework/tests/generics.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
(limited to 'rest_framework/tests')
diff --git a/rest_framework/tests/generics.py b/rest_framework/tests/generics.py
index 4a13389a..eca50d82 100644
--- a/rest_framework/tests/generics.py
+++ b/rest_framework/tests/generics.py
@@ -377,7 +377,7 @@ class TestCreateModelWithAutoNowAddField(TestCase):
self.assertEqual(created.content, 'foobar')
-# Test for particularly ugly regression with m2m in browseable API
+# Test for particularly ugly regression with m2m in browsable API
class ClassB(models.Model):
name = models.CharField(max_length=255)
@@ -402,7 +402,7 @@ class ExampleView(generics.ListCreateAPIView):
class TestM2MBrowseableAPI(TestCase):
def test_m2m_in_browseable_api(self):
"""
- Test for particularly ugly regression with m2m in browseable API
+ Test for particularly ugly regression with m2m in browsable API
"""
request = factory.get('/', HTTP_ACCEPT='text/html')
view = ExampleView().as_view()
--
cgit v1.2.3
From 318fdaabe560c99de4983e0a3cdcb79756baaf01 Mon Sep 17 00:00:00 2001
From: Michael Elovskikh
Date: Fri, 3 May 2013 01:39:08 +0600
Subject: Tests for FileUploadParser
---
rest_framework/tests/parsers.py | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
(limited to 'rest_framework/tests')
diff --git a/rest_framework/tests/parsers.py b/rest_framework/tests/parsers.py
index 539c5b44..b18ecbf2 100644
--- a/rest_framework/tests/parsers.py
+++ b/rest_framework/tests/parsers.py
@@ -1,10 +1,11 @@
from __future__ import unicode_literals
from rest_framework.compat import StringIO
from django import forms
+from django.core.files.uploadhandler import MemoryFileUploadHandler
from django.test import TestCase
from django.utils import unittest
from rest_framework.compat import etree
-from rest_framework.parsers import FormParser
+from rest_framework.parsers import FormParser, FileUploadParser
from rest_framework.parsers import XMLParser
import datetime
@@ -82,3 +83,27 @@ class TestXMLParser(TestCase):
parser = XMLParser()
data = parser.parse(self._complex_data_input)
self.assertEqual(data, self._complex_data)
+
+
+class TestFileUploadParser(TestCase):
+ def setUp(self):
+ class MockRequest(object):
+ pass
+ from io import BytesIO
+ self.stream = BytesIO(
+ "Test text file".encode('utf-8')
+ )
+ request = MockRequest()
+ request.upload_handlers = (MemoryFileUploadHandler(),)
+ request.META = {
+ 'HTTP_CONTENT_DISPOSITION': 'Content-Disposition: inline; filename=file.txt'.encode('utf-8'),
+ 'HTTP_CONTENT_LENGTH': 14,
+ }
+ self.parser_context = {'request': request}
+
+ def test_parse(self):
+ """ Make sure the `QueryDict` works OK """
+ parser = FileUploadParser()
+ data_and_files = parser.parse(self.stream, parser_context=self.parser_context)
+ file_obj = data_and_files.files['file']
+ self.assertEqual(file_obj._size, 14)
--
cgit v1.2.3
From e36e4f48ad481b4303e68ed524677add07b224f7 Mon Sep 17 00:00:00 2001
From: Michael Elovskikh
Date: Sat, 4 May 2013 14:58:21 +0600
Subject: Codebase improvements on FileUploadParser
* Added docstrings.
* Added `FileUploadParser.get_filename` to make it easier to override.
* Added url kwargs filename detection step.
* Updated tests corresponding to these changes.
---
rest_framework/tests/parsers.py | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
(limited to 'rest_framework/tests')
diff --git a/rest_framework/tests/parsers.py b/rest_framework/tests/parsers.py
index b18ecbf2..7699e10c 100644
--- a/rest_framework/tests/parsers.py
+++ b/rest_framework/tests/parsers.py
@@ -99,11 +99,17 @@ class TestFileUploadParser(TestCase):
'HTTP_CONTENT_DISPOSITION': 'Content-Disposition: inline; filename=file.txt'.encode('utf-8'),
'HTTP_CONTENT_LENGTH': 14,
}
- self.parser_context = {'request': request}
+ self.parser_context = {'request': request, 'kwargs': {}}
def test_parse(self):
""" Make sure the `QueryDict` works OK """
parser = FileUploadParser()
- data_and_files = parser.parse(self.stream, parser_context=self.parser_context)
+ self.stream.seek(0)
+ data_and_files = parser.parse(self.stream, None, self.parser_context)
file_obj = data_and_files.files['file']
self.assertEqual(file_obj._size, 14)
+
+ def test_get_filename(self):
+ parser = FileUploadParser()
+ filename = parser.get_filename(self.stream, None, self.parser_context)
+ self.assertEqual(filename, 'file.txt'.encode('utf-8'))
--
cgit v1.2.3
From de69a28b9e786b8c759cda4acedb0a1b8542298b Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Wed, 8 May 2013 20:18:01 +0100
Subject: Test and fix for #814.
---
rest_framework/tests/filterset.py | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
(limited to 'rest_framework/tests')
diff --git a/rest_framework/tests/filterset.py b/rest_framework/tests/filterset.py
index 1e53a5cd..023bd016 100644
--- a/rest_framework/tests/filterset.py
+++ b/rest_framework/tests/filterset.py
@@ -5,7 +5,7 @@ from django.core.urlresolvers import reverse
from django.test import TestCase
from django.test.client import RequestFactory
from django.utils import unittest
-from rest_framework import generics, status, filters
+from rest_framework import generics, serializers, status, filters
from rest_framework.compat import django_filters, patterns, url
from rest_framework.tests.models import FilterableItem, BasicModel
@@ -52,6 +52,17 @@ if django_filters:
filter_class = SeveralFieldsFilter
filter_backend = filters.DjangoFilterBackend
+ # Regression test for #814
+ class FilterableItemSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = FilterableItem
+
+ class FilterFieldsQuerysetView(generics.ListCreateAPIView):
+ queryset = FilterableItem.objects.all()
+ serializer_class = FilterableItemSerializer
+ filter_fields = ['decimal', 'date']
+ filter_backend = filters.DjangoFilterBackend
+
urlpatterns = patterns('',
url(r'^(?P\d+)/$', FilterClassDetailView.as_view(), name='detail-view'),
url(r'^$', FilterClassRootView.as_view(), name='root-view'),
@@ -114,6 +125,21 @@ class IntegrationTestFiltering(CommonFilteringTestCase):
expected_data = [f for f in self.data if f['date'] == search_date]
self.assertEqual(response.data, expected_data)
+ @unittest.skipUnless(django_filters, 'django-filters not installed')
+ def test_filter_with_queryset(self):
+ """
+ Regression test for #814.
+ """
+ view = FilterFieldsQuerysetView.as_view()
+
+ # Tests that the decimal filter works.
+ search_decimal = Decimal('2.25')
+ request = factory.get('/?decimal=%s' % search_decimal)
+ response = view(request).render()
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ expected_data = [f for f in self.data if f['decimal'] == search_decimal]
+ self.assertEqual(response.data, expected_data)
+
@unittest.skipUnless(django_filters, 'django-filters not installed')
def test_get_filtered_class_root_view(self):
"""
--
cgit v1.2.3