aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/models.py111
-rw-r--r--tests/test_generics.py56
-rw-r--r--tests/test_model_serializer.py24
-rw-r--r--tests/test_parsers.py32
4 files changed, 91 insertions, 132 deletions
diff --git a/tests/models.py b/tests/models.py
index 06ec5a22..456b0a0b 100644
--- a/tests/models.py
+++ b/tests/models.py
@@ -3,62 +3,20 @@ from django.db import models
from django.utils.translation import ugettext_lazy as _
-def foobar():
- return 'foobar'
-
-
-class CustomField(models.CharField):
-
- def __init__(self, *args, **kwargs):
- kwargs['max_length'] = 12
- super(CustomField, self).__init__(*args, **kwargs)
-
-
class RESTFrameworkModel(models.Model):
"""
Base for test models that sets app_label, so they play nicely.
"""
+
class Meta:
app_label = 'tests'
abstract = True
-class HasPositiveIntegerAsChoice(RESTFrameworkModel):
- some_choices = ((1, 'A'), (2, 'B'), (3, 'C'))
- some_integer = models.PositiveIntegerField(choices=some_choices)
-
-
-class Anchor(RESTFrameworkModel):
- text = models.CharField(max_length=100, default='anchor')
-
-
class BasicModel(RESTFrameworkModel):
text = models.CharField(max_length=100, verbose_name=_("Text comes here"), help_text=_("Text description."))
-class SlugBasedModel(RESTFrameworkModel):
- text = models.CharField(max_length=100)
- slug = models.SlugField(max_length=32)
-
-
-class DefaultValueModel(RESTFrameworkModel):
- text = models.CharField(default='foobar', max_length=100)
- extra = models.CharField(blank=True, null=True, max_length=100)
-
-
-class CallableDefaultValueModel(RESTFrameworkModel):
- text = models.CharField(default=foobar, max_length=100)
-
-
-class ManyToManyModel(RESTFrameworkModel):
- rel = models.ManyToManyField(Anchor, help_text='Some help text.')
-
-
-class ReadOnlyManyToManyModel(RESTFrameworkModel):
- text = models.CharField(max_length=100, default='anchor')
- rel = models.ManyToManyField(Anchor)
-
-
class BaseFilterableItem(RESTFrameworkModel):
text = models.CharField(max_length=100)
@@ -71,73 +29,6 @@ class FilterableItem(BaseFilterableItem):
date = models.DateField()
-# Model for regression test for #285
-
-class Comment(RESTFrameworkModel):
- email = models.EmailField()
- content = models.CharField(max_length=200)
- created = models.DateTimeField(auto_now_add=True)
-
-
-class ActionItem(RESTFrameworkModel):
- title = models.CharField(max_length=200)
- started = models.NullBooleanField(default=False)
- done = models.BooleanField(default=False)
- info = CustomField(default='---', max_length=12)
-
-
-# Models for reverse relations
-class Person(RESTFrameworkModel):
- name = models.CharField(max_length=10)
- age = models.IntegerField(null=True, blank=True)
-
- @property
- def info(self):
- return {
- 'name': self.name,
- 'age': self.age,
- }
-
-
-class BlogPost(RESTFrameworkModel):
- title = models.CharField(max_length=100)
- writer = models.ForeignKey(Person, null=True, blank=True)
-
- def get_first_comment(self):
- return self.blogpostcomment_set.all()[0]
-
-
-class BlogPostComment(RESTFrameworkModel):
- text = models.TextField()
- blog_post = models.ForeignKey(BlogPost)
-
-
-class Album(RESTFrameworkModel):
- title = models.CharField(max_length=100, unique=True)
- ref = models.CharField(max_length=10, unique=True, null=True, blank=True)
-
-
-class Photo(RESTFrameworkModel):
- description = models.TextField()
- album = models.ForeignKey(Album)
-
-
-# Model for issue #324
-class BlankFieldModel(RESTFrameworkModel):
- title = models.CharField(max_length=100, blank=True, null=False,
- default="title")
-
-
-# Model for issue #380
-class OptionalRelationModel(RESTFrameworkModel):
- other = models.ForeignKey('OptionalRelationModel', blank=True, null=True)
-
-
-# Model for RegexField
-class Book(RESTFrameworkModel):
- isbn = models.CharField(max_length=13)
-
-
# Models for relations tests
# ManyToMany
class ManyToManyTarget(RESTFrameworkModel):
diff --git a/tests/test_generics.py b/tests/test_generics.py
index 2690fb47..94023c30 100644
--- a/tests/test_generics.py
+++ b/tests/test_generics.py
@@ -6,12 +6,26 @@ from django.test import TestCase
from django.utils import six
from rest_framework import generics, renderers, serializers, status
from rest_framework.test import APIRequestFactory
-from tests.models import BasicModel, Comment, SlugBasedModel
+from tests.models import BasicModel, RESTFrameworkModel
from tests.models import ForeignKeySource, ForeignKeyTarget
factory = APIRequestFactory()
+# Models
+class SlugBasedModel(RESTFrameworkModel):
+ text = models.CharField(max_length=100)
+ slug = models.SlugField(max_length=32)
+
+
+# Model for regression test for #285
+class Comment(RESTFrameworkModel):
+ email = models.EmailField()
+ content = models.CharField(max_length=200)
+ created = models.DateTimeField(auto_now_add=True)
+
+
+# Serializers
class BasicSerializer(serializers.ModelSerializer):
class Meta:
model = BasicModel
@@ -22,6 +36,15 @@ class ForeignKeySerializer(serializers.ModelSerializer):
model = ForeignKeySource
+class SlugSerializer(serializers.ModelSerializer):
+ slug = serializers.ReadOnlyField()
+
+ class Meta:
+ model = SlugBasedModel
+ fields = ('text', 'slug')
+
+
+# Views
class RootView(generics.ListCreateAPIView):
queryset = BasicModel.objects.all()
serializer_class = BasicSerializer
@@ -37,14 +60,6 @@ class FKInstanceView(generics.RetrieveUpdateDestroyAPIView):
serializer_class = ForeignKeySerializer
-class SlugSerializer(serializers.ModelSerializer):
- slug = serializers.ReadOnlyField()
-
- class Meta:
- model = SlugBasedModel
- fields = ('text', 'slug')
-
-
class SlugBasedInstanceView(InstanceView):
"""
A model with a slug-field.
@@ -54,6 +69,7 @@ class SlugBasedInstanceView(InstanceView):
lookup_field = 'slug'
+# Tests
class TestRootView(TestCase):
def setUp(self):
"""
@@ -127,13 +143,13 @@ class TestRootView(TestCase):
self.assertEqual(created.text, 'foobar')
-EXPECTED_QUERYS_FOR_PUT = 3 if django.VERSION < (1, 6) else 2
+EXPECTED_QUERIES_FOR_PUT = 3 if django.VERSION < (1, 6) else 2
class TestInstanceView(TestCase):
def setUp(self):
"""
- Create 3 BasicModel intances.
+ Create 3 BasicModel instances.
"""
items = ['foo', 'bar', 'baz', 'filtered out']
for item in items:
@@ -173,7 +189,7 @@ class TestInstanceView(TestCase):
"""
data = {'text': 'foobar'}
request = factory.put('/1', data, format='json')
- with self.assertNumQueries(EXPECTED_QUERYS_FOR_PUT):
+ with self.assertNumQueries(EXPECTED_QUERIES_FOR_PUT):
response = self.view(request, pk='1').render()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(dict(response.data), {'id': 1, 'text': 'foobar'})
@@ -187,7 +203,7 @@ class TestInstanceView(TestCase):
data = {'text': 'foobar'}
request = factory.patch('/1', data, format='json')
- with self.assertNumQueries(EXPECTED_QUERYS_FOR_PUT):
+ with self.assertNumQueries(EXPECTED_QUERIES_FOR_PUT):
response = self.view(request, pk=1).render()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, {'id': 1, 'text': 'foobar'})
@@ -222,7 +238,7 @@ class TestInstanceView(TestCase):
"""
data = {'id': 999, 'text': 'foobar'}
request = factory.put('/1', data, format='json')
- with self.assertNumQueries(EXPECTED_QUERYS_FOR_PUT):
+ with self.assertNumQueries(EXPECTED_QUERIES_FOR_PUT):
response = self.view(request, pk=1).render()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, {'id': 1, 'text': 'foobar'})
@@ -288,9 +304,10 @@ class TestOverriddenGetObject(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.
+ Create 3 BasicModel instances.
"""
items = ['foo', 'bar', 'baz']
for item in items:
@@ -363,11 +380,11 @@ class ClassB(models.Model):
class ClassA(models.Model):
name = models.CharField(max_length=255)
- childs = models.ManyToManyField(ClassB, blank=True, null=True)
+ children = models.ManyToManyField(ClassB, blank=True, null=True)
class ClassASerializer(serializers.ModelSerializer):
- childs = serializers.PrimaryKeyRelatedField(
+ children = serializers.PrimaryKeyRelatedField(
many=True, queryset=ClassB.objects.all()
)
@@ -380,8 +397,8 @@ class ExampleView(generics.ListCreateAPIView):
queryset = ClassA.objects.all()
-class TestM2MBrowseableAPI(TestCase):
- def test_m2m_in_browseable_api(self):
+class TestM2MBrowsableAPI(TestCase):
+ def test_m2m_in_browsable_api(self):
"""
Test for particularly ugly regression with m2m in browsable API
"""
@@ -424,7 +441,6 @@ class DynamicSerializerView(generics.ListCreateAPIView):
class TestFilterBackendAppliedToViews(TestCase):
-
def setUp(self):
"""
Create 3 BasicModel instances to filter on.
diff --git a/tests/test_model_serializer.py b/tests/test_model_serializer.py
index 3aec0da0..1bcd58e0 100644
--- a/tests/test_model_serializer.py
+++ b/tests/test_model_serializer.py
@@ -26,6 +26,10 @@ class CustomField(models.Field):
pass
+class OneFieldModel(models.Model):
+ char_field = models.CharField(max_length=100)
+
+
class RegularFieldsModel(models.Model):
"""
A model class for testing regular flat fields.
@@ -68,6 +72,26 @@ class FieldOptionsModel(models.Model):
choices_field = models.CharField(max_length=100, choices=COLOR_CHOICES)
+class TestModelSerializer(TestCase):
+ def test_create_method(self):
+ class TestSerializer(serializers.ModelSerializer):
+ non_model_field = serializers.CharField()
+
+ class Meta:
+ model = OneFieldModel
+ fields = ('char_field', 'non_model_field')
+
+ serializer = TestSerializer(data={
+ 'char_field': 'foo',
+ 'non_model_field': 'bar',
+ })
+ serializer.is_valid()
+ with self.assertRaises(TypeError) as excinfo:
+ serializer.save()
+ msginitial = 'Got a `TypeError` when calling `OneFieldModel.objects.create()`.'
+ assert str(excinfo.exception).startswith(msginitial)
+
+
class TestRegularFieldMappings(TestCase):
def test_regular_fields(self):
"""
diff --git a/tests/test_parsers.py b/tests/test_parsers.py
index 3f2672df..88eccef3 100644
--- a/tests/test_parsers.py
+++ b/tests/test_parsers.py
@@ -1,12 +1,13 @@
# -*- coding: utf-8 -*-
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.compat import StringIO
+from rest_framework.exceptions import ParseError
from rest_framework.parsers import FormParser, FileUploadParser
from rest_framework.parsers import XMLParser
import datetime
@@ -104,13 +105,40 @@ class TestFileUploadParser(TestCase):
self.parser_context = {'request': request, 'kwargs': {}}
def test_parse(self):
- """ Make sure the `QueryDict` works OK """
+ """
+ Parse raw file upload.
+ """
parser = FileUploadParser()
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_parse_missing_filename(self):
+ """
+ Parse raw file upload when filename is missing.
+ """
+ parser = FileUploadParser()
+ self.stream.seek(0)
+ self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = ''
+ with self.assertRaises(ParseError):
+ parser.parse(self.stream, None, self.parser_context)
+
+ def test_parse_missing_filename_multiple_upload_handlers(self):
+ """
+ Parse raw file upload with multiple handlers when filename is missing.
+ Regression test for #2109.
+ """
+ parser = FileUploadParser()
+ self.stream.seek(0)
+ self.parser_context['request'].upload_handlers = (
+ MemoryFileUploadHandler(),
+ MemoryFileUploadHandler()
+ )
+ self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = ''
+ with self.assertRaises(ParseError):
+ parser.parse(self.stream, None, self.parser_context)
+
def test_get_filename(self):
parser = FileUploadParser()
filename = parser.get_filename(self.stream, None, self.parser_context)