aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test_metadata.py17
-rw-r--r--tests/test_parsers.py6
-rw-r--r--tests/test_renderers.py18
-rw-r--r--tests/test_routers.py14
-rw-r--r--tests/test_validators.py54
5 files changed, 96 insertions, 13 deletions
diff --git a/tests/test_metadata.py b/tests/test_metadata.py
index 5031c0f3..3a435f02 100644
--- a/tests/test_metadata.py
+++ b/tests/test_metadata.py
@@ -54,8 +54,12 @@ class TestMetadata:
"""
class ExampleSerializer(serializers.Serializer):
choice_field = serializers.ChoiceField(['red', 'green', 'blue'])
- integer_field = serializers.IntegerField(max_value=10)
- char_field = serializers.CharField(required=False)
+ integer_field = serializers.IntegerField(
+ min_value=1, max_value=1000
+ )
+ char_field = serializers.CharField(
+ required=False, min_length=3, max_length=40
+ )
class ExampleView(views.APIView):
"""Example view."""
@@ -96,13 +100,18 @@ class TestMetadata:
'type': 'integer',
'required': True,
'read_only': False,
- 'label': 'Integer field'
+ 'label': 'Integer field',
+ 'min_value': 1,
+ 'max_value': 1000,
+
},
'char_field': {
'type': 'string',
'required': False,
'read_only': False,
- 'label': 'Char field'
+ 'label': 'Char field',
+ 'min_length': 3,
+ 'max_length': 40
}
}
}
diff --git a/tests/test_parsers.py b/tests/test_parsers.py
index 8816065a..fe6aec19 100644
--- a/tests/test_parsers.py
+++ b/tests/test_parsers.py
@@ -99,11 +99,5 @@ class TestFileUploadParser(TestCase):
filename = parser.get_filename(self.stream, None, self.parser_context)
self.assertEqual(filename, 'ÀĥƦ.txt')
- self.__replace_content_disposition('inline; filename=fallback.txt; filename*=utf-8--ÀĥƦ.txt')
- filename = parser.get_filename(self.stream, None, self.parser_context)
- # Malformed. Either None or 'fallback.txt' will be acceptable.
- # See also https://code.djangoproject.com/ticket/24209
- self.assertIn(filename, ('fallback.txt', None))
-
def __replace_content_disposition(self, disposition):
self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = disposition
diff --git a/tests/test_renderers.py b/tests/test_renderers.py
index 60a08225..cb76f683 100644
--- a/tests/test_renderers.py
+++ b/tests/test_renderers.py
@@ -10,7 +10,10 @@ from rest_framework import status, permissions
from rest_framework.compat import OrderedDict
from rest_framework.response import Response
from rest_framework.views import APIView
-from rest_framework.renderers import BaseRenderer, JSONRenderer, BrowsableAPIRenderer
+from rest_framework import serializers
+from rest_framework.renderers import (
+ BaseRenderer, JSONRenderer, BrowsableAPIRenderer, HTMLFormRenderer
+)
from rest_framework.settings import api_settings
from rest_framework.test import APIRequestFactory
from collections import MutableMapping
@@ -455,3 +458,16 @@ class TestJSONIndentationStyles:
renderer.compact = False
data = OrderedDict([('a', 1), ('b', 2)])
assert renderer.render(data) == b'{"a": 1, "b": 2}'
+
+
+class TestHiddenFieldHTMLFormRenderer(TestCase):
+ def test_hidden_field_rendering(self):
+ class TestSerializer(serializers.Serializer):
+ published = serializers.HiddenField(default=True)
+
+ serializer = TestSerializer(data={})
+ serializer.is_valid()
+ renderer = HTMLFormRenderer()
+ field = serializer['published']
+ rendered = renderer.render_field(field, {})
+ assert rendered == ''
diff --git a/tests/test_routers.py b/tests/test_routers.py
index 948c69bb..08c58ec7 100644
--- a/tests/test_routers.py
+++ b/tests/test_routers.py
@@ -302,12 +302,16 @@ class DynamicListAndDetailViewSet(viewsets.ViewSet):
return Response({'method': 'link2'})
+class SubDynamicListAndDetailViewSet(DynamicListAndDetailViewSet):
+ pass
+
+
class TestDynamicListAndDetailRouter(TestCase):
def setUp(self):
self.router = SimpleRouter()
- def test_list_and_detail_route_decorators(self):
- routes = self.router.get_routes(DynamicListAndDetailViewSet)
+ def _test_list_and_detail_route_decorators(self, viewset):
+ routes = self.router.get_routes(viewset)
decorator_routes = [r for r in routes if not (r.name.endswith('-list') or r.name.endswith('-detail'))]
MethodNamesMap = namedtuple('MethodNamesMap', 'method_name url_path')
@@ -336,3 +340,9 @@ class TestDynamicListAndDetailRouter(TestCase):
else:
method_map = 'get'
self.assertEqual(route.mapping[method_map], method_name)
+
+ def test_list_and_detail_route_decorators(self):
+ self._test_list_and_detail_route_decorators(DynamicListAndDetailViewSet)
+
+ def test_inherited_list_and_detail_route_decorators(self):
+ self._test_list_and_detail_route_decorators(SubDynamicListAndDetailViewSet)
diff --git a/tests/test_validators.py b/tests/test_validators.py
index 072cec36..127ec6f8 100644
--- a/tests/test_validators.py
+++ b/tests/test_validators.py
@@ -83,11 +83,37 @@ class UniquenessTogetherModel(models.Model):
unique_together = ('race_name', 'position')
+class NullUniquenessTogetherModel(models.Model):
+ """
+ Used to ensure that null values are not included when checking
+ unique_together constraints.
+
+ Ignoring items which have a null in any of the validated fields is the same
+ behavior that database backends will use when they have the
+ unique_together constraint added.
+
+ Example case: a null position could indicate a non-finisher in the race,
+ there could be many non-finishers in a race, but all non-NULL
+ values *should* be unique against the given `race_name`.
+ """
+ date_of_birth = models.DateField(null=True) # Not part of the uniqueness constraint
+ race_name = models.CharField(max_length=100)
+ position = models.IntegerField(null=True)
+
+ class Meta:
+ unique_together = ('race_name', 'position')
+
+
class UniquenessTogetherSerializer(serializers.ModelSerializer):
class Meta:
model = UniquenessTogetherModel
+class NullUniquenessTogetherSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = NullUniquenessTogetherModel
+
+
class TestUniquenessTogetherValidation(TestCase):
def setUp(self):
self.instance = UniquenessTogetherModel.objects.create(
@@ -182,6 +208,34 @@ class TestUniquenessTogetherValidation(TestCase):
""")
assert repr(serializer) == expected
+ def test_ignore_validation_for_null_fields(self):
+ # None values that are on fields which are part of the uniqueness
+ # constraint cause the instance to ignore uniqueness validation.
+ NullUniquenessTogetherModel.objects.create(
+ date_of_birth=datetime.date(2000, 1, 1),
+ race_name='Paris Marathon',
+ position=None
+ )
+ data = {
+ 'date': datetime.date(2000, 1, 1),
+ 'race_name': 'Paris Marathon',
+ 'position': None
+ }
+ serializer = NullUniquenessTogetherSerializer(data=data)
+ assert serializer.is_valid()
+
+ def test_do_not_ignore_validation_for_null_fields(self):
+ # None values that are not on fields part of the uniqueness constraint
+ # do not cause the instance to skip validation.
+ NullUniquenessTogetherModel.objects.create(
+ date_of_birth=datetime.date(2000, 1, 1),
+ race_name='Paris Marathon',
+ position=1
+ )
+ data = {'date': None, 'race_name': 'Paris Marathon', 'position': 1}
+ serializer = NullUniquenessTogetherSerializer(data=data)
+ assert not serializer.is_valid()
+
# Tests for `UniqueForDateValidator`
# ----------------------------------