From 0081d744b9f530b2418d1e82d7ad94a2ebc31c9c Mon Sep 17 00:00:00 2001 From: Matteo Suppo Date: Sat, 23 Mar 2013 14:18:11 +0100 Subject: Added tests for issue 747 in serializer.py --- rest_framework/tests/serializer.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'rest_framework/tests') diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py index 05217f35..0386ca76 100644 --- a/rest_framework/tests/serializer.py +++ b/rest_framework/tests/serializer.py @@ -1082,3 +1082,32 @@ class DeserializeListTestCase(TestCase): self.assertFalse(serializer.is_valid()) expected = [{}, {'email': ['This field is required.']}, {}] self.assertEqual(serializer.errors, expected) + + +# test for issue 747 + +class LazyStringModel(object): + def __init__(self, lazystring): + self.lazystring = lazystring + + +class LazyStringSerializer(serializers.Serializer): + lazystring = serializers.Field() + + def restore_object(self, attrs, instance=None): + if instance is not None: + instance.lazystring = attrs.get('lazystring', instance.lazystring) + return instance + return Comment(**attrs) + + +class LazyStringsTestCase(TestCase): + + def setUp(self): + from django.utils.translation import ugettext_lazy as _ + + self.model = LazyStringModel(lazystring=_("lazystring")) + + def test_lazy_strings_are_translated(self): + serializer = LazyStringSerializer(self.model) + self.assertEqual(type(serializer.data['lazystring']), type("lazystring")) -- cgit v1.2.3 From ef383d969c440a20fdf25748de590e07cb1abfda Mon Sep 17 00:00:00 2001 From: Ryan Kaskel Date: Sat, 18 May 2013 14:31:29 +0100 Subject: Clean up test case. --- rest_framework/tests/serializer.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'rest_framework/tests') diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py index d978dc87..e999b624 100644 --- a/rest_framework/tests/serializer.py +++ b/rest_framework/tests/serializer.py @@ -1,8 +1,9 @@ from __future__ import unicode_literals from django.db import models from django.db.models.fields import BLANK_CHOICE_DASH -from django.utils.datastructures import MultiValueDict from django.test import TestCase +from django.utils.datastructures import MultiValueDict +from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers from rest_framework.tests.models import (HasPositiveIntegerAsChoice, Album, ActionItem, Anchor, BasicModel, BlankFieldModel, BlogPost, BlogPostComment, Book, CallableDefaultValueModel, DefaultValueModel, @@ -1246,6 +1247,7 @@ class DeserializeListTestCase(TestCase): # test for issue 747 + class LazyStringModel(object): def __init__(self, lazystring): self.lazystring = lazystring @@ -1258,16 +1260,14 @@ class LazyStringSerializer(serializers.Serializer): if instance is not None: instance.lazystring = attrs.get('lazystring', instance.lazystring) return instance - return Comment(**attrs) + return LazyStringModel(**attrs) class LazyStringsTestCase(TestCase): - def setUp(self): - from django.utils.translation import ugettext_lazy as _ - - self.model = LazyStringModel(lazystring=_("lazystring")) + self.model = LazyStringModel(lazystring=_('lazystring')) def test_lazy_strings_are_translated(self): serializer = LazyStringSerializer(self.model) - self.assertEqual(type(serializer.data['lazystring']), type("lazystring")) + self.assertEqual(type(serializer.data['lazystring']), + type('lazystring')) -- cgit v1.2.3 From ebe959b52a10a88975b15c69275b0ef5c50cb9fa Mon Sep 17 00:00:00 2001 From: Karol Majta Date: Sat, 18 May 2013 16:45:05 +0200 Subject: charset param gets now appended to response's Content-Type. Closes #807 --- rest_framework/tests/negotiation.py | 35 +++++++++++++++++++---- rest_framework/tests/response.py | 57 +++++++++++++++++++++++++++++++++---- 2 files changed, 80 insertions(+), 12 deletions(-) (limited to 'rest_framework/tests') diff --git a/rest_framework/tests/negotiation.py b/rest_framework/tests/negotiation.py index 43721b84..d7ef6470 100644 --- a/rest_framework/tests/negotiation.py +++ b/rest_framework/tests/negotiation.py @@ -3,18 +3,24 @@ from django.test import TestCase from django.test.client import RequestFactory from rest_framework.negotiation import DefaultContentNegotiation from rest_framework.request import Request +from rest_framework.renderers import BaseRenderer factory = RequestFactory() -class MockJSONRenderer(object): +class MockJSONRenderer(BaseRenderer): media_type = 'application/json' - -class MockHTMLRenderer(object): +class MockHTMLRenderer(BaseRenderer): media_type = 'text/html' +class NoCharsetSpecifiedRenderer(BaseRenderer): + media_type = 'my/media' + +class CharsetSpecifiedRenderer(BaseRenderer): + media_type = 'my/media' + charset = 'mycharset' class TestAcceptedMediaType(TestCase): def setUp(self): @@ -26,15 +32,32 @@ class TestAcceptedMediaType(TestCase): def test_client_without_accept_use_renderer(self): request = Request(factory.get('/')) - accepted_renderer, accepted_media_type = self.select_renderer(request) + accepted_renderer, accepted_media_type, charset = self.select_renderer(request) self.assertEqual(accepted_media_type, 'application/json') def test_client_underspecifies_accept_use_renderer(self): request = Request(factory.get('/', HTTP_ACCEPT='*/*')) - accepted_renderer, accepted_media_type = self.select_renderer(request) + accepted_renderer, accepted_media_type, charset = self.select_renderer(request) self.assertEqual(accepted_media_type, 'application/json') def test_client_overspecifies_accept_use_client(self): request = Request(factory.get('/', HTTP_ACCEPT='application/json; indent=8')) - accepted_renderer, accepted_media_type = self.select_renderer(request) + accepted_renderer, accepted_media_type, charset = self.select_renderer(request) self.assertEqual(accepted_media_type, 'application/json; indent=8') + +class TestCharset(TestCase): + def setUp(self): + self.renderers = [NoCharsetSpecifiedRenderer()] + self.negotiator = DefaultContentNegotiation() + + def test_returns_none_if_no_charset_set(self): + request = Request(factory.get('/')) + renderers = [NoCharsetSpecifiedRenderer()] + _, _, charset = self.negotiator.select_renderer(request, renderers) + self.assertIsNone(charset) + + def test_returns_attribute_from_renderer_if_charset_is_set(self): + request = Request(factory.get('/')) + renderers = [CharsetSpecifiedRenderer()] + _, _, charset = self.negotiator.select_renderer(request, renderers) + self.assertEquals(CharsetSpecifiedRenderer.charset, charset) \ No newline at end of file diff --git a/rest_framework/tests/response.py b/rest_framework/tests/response.py index aecf83f4..f2a1c635 100644 --- a/rest_framework/tests/response.py +++ b/rest_framework/tests/response.py @@ -12,7 +12,6 @@ from rest_framework.renderers import ( from rest_framework.settings import api_settings from rest_framework.compat import six - class MockPickleRenderer(BaseRenderer): media_type = 'application/pickle' @@ -20,6 +19,8 @@ class MockPickleRenderer(BaseRenderer): class MockJsonRenderer(BaseRenderer): media_type = 'application/json' +class MockTextMediaRenderer(BaseRenderer): + media_type = 'text/html' DUMMYSTATUS = status.HTTP_200_OK DUMMYCONTENT = 'dummycontent' @@ -43,14 +44,18 @@ class RendererB(BaseRenderer): def render(self, data, media_type=None, renderer_context=None): return RENDERER_B_SERIALIZER(data) +class RendererC(RendererB): + media_type = 'mock/rendererc' + format = 'formatc' + charset = "rendererc" + class MockView(APIView): - renderer_classes = (RendererA, RendererB) + renderer_classes = (RendererA, RendererB, RendererC) def get(self, request, **kwargs): return Response(DUMMYCONTENT, status=DUMMYSTATUS) - class HTMLView(APIView): renderer_classes = (BrowsableAPIRenderer, ) @@ -64,10 +69,9 @@ class HTMLView1(APIView): def get(self, request, **kwargs): return Response('text') - urlpatterns = patterns('', - url(r'^.*\.(?P.+)$', MockView.as_view(renderer_classes=[RendererA, RendererB])), - url(r'^$', MockView.as_view(renderer_classes=[RendererA, RendererB])), + url(r'^.*\.(?P.+)$', MockView.as_view(renderer_classes=[RendererA, RendererB, RendererC])), + url(r'^$', MockView.as_view(renderer_classes=[RendererA, RendererB, RendererC])), url(r'^html$', HTMLView.as_view()), url(r'^html1$', HTMLView1.as_view()), url(r'^restframework', include('rest_framework.urls', namespace='rest_framework')) @@ -173,3 +177,44 @@ class Issue122Tests(TestCase): Test if no infinite recursion occurs. """ self.client.get('/html1') + +class Issue807Testts(TestCase): + """ + Covers #807 + """ + + urls = 'rest_framework.tests.response' + + def test_does_not_append_charset_by_default(self): + """ + For backwards compatibility `REST_FRAMEWORK['DEFAULT_CHARSET']` defaults + to None, so that all legacy code works as expected. + """ + headers = {"HTTP_ACCEPT": RendererA.media_type} + resp = self.client.get('/', **headers) + self.assertEquals(RendererA.media_type, resp['Content-Type']) + + def test_if_there_is_charset_specified_on_renderer_it_gets_appended(self): + """ + If renderer class has charset attribute declared, it gets appended + to Response's Content-Type + """ + resp = self.client.get('/?format=%s' % RendererC.format) + expected = "{0}; charset={1}".format(RendererC.media_type, RendererC.charset) + self.assertEquals(expected, resp['Content-Type']) + + def test_if_there_is_default_charset_specified_it_gets_appended(self): + """ + If user defines `REST_FRAMEWORK['DEFAULT_CHARSET']` it will get appended + to Content-Type of all responses. + """ + original_default_charset = api_settings.DEFAULT_CHARSET + api_settings.DEFAULT_CHARSET = "utf-8" + headers = {'HTTP_ACCEPT': RendererA.media_type} + resp = self.client.get('/', **headers) + expected = "{0}; charset={1}".format( + RendererA.media_type, + api_settings.DEFAULT_CHARSET + ) + self.assertEquals(expected, resp['Content-Type']) + api_settings.DEFAULT_CHARSET = original_default_charset \ No newline at end of file -- cgit v1.2.3 From 0c81d04170da19e5bfb332641d92d9c3346598f8 Mon Sep 17 00:00:00 2001 From: Stephan Groß Date: Sat, 18 May 2013 17:04:20 +0200 Subject: Add min_value=0 to autogenerated Pos..IntFields --- rest_framework/tests/serializer.py | 73 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) (limited to 'rest_framework/tests') diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py index 4f188c3e..220a581a 100644 --- a/rest_framework/tests/serializer.py +++ b/rest_framework/tests/serializer.py @@ -1402,3 +1402,76 @@ class AttributeMappingOnAutogeneratedFieldsTests(TestCase): def test_url_field(self): self.field_test('url_field') + + +class DefaultValuesOnAutogeneratedFieldsTests(TestCase): + + def setUp(self): + class DVOAFModel(RESTFrameworkModel): + positive_integer_field = models.PositiveIntegerField(blank=True) + positive_small_integer_field = models.PositiveSmallIntegerField(blank=True) + email_field = models.EmailField(blank=True) + file_field = models.FileField(blank=True) + image_field = models.ImageField(blank=True) + slug_field = models.SlugField(blank=True) + url_field = models.URLField(blank=True) + + class DVOAFSerializer(serializers.ModelSerializer): + class Meta: + model = DVOAFModel + + self.serializer_class = DVOAFSerializer + self.fields_attributes = { + 'positive_integer_field': [ + ('min_value', 0), + ], + 'positive_small_integer_field': [ + ('min_value', 0), + ], + 'email_field': [ + ('max_length', 75), + ], + 'file_field': [ + ('max_length', 100), + ], + 'image_field': [ + ('max_length', 100), + ], + 'slug_field': [ + ('max_length', 50), + ], + 'url_field': [ + ('max_length', 200), + ], + } + + def field_test(self, field): + serializer = self.serializer_class(data={}) + self.assertEqual(serializer.is_valid(), True) + + for attribute in self.fields_attributes[field]: + self.assertEqual( + getattr(serializer.fields[field], attribute[0]), + attribute[1] + ) + + def test_positive_integer_field(self): + self.field_test('positive_integer_field') + + def test_positive_small_integer_field(self): + self.field_test('positive_small_integer_field') + + def test_email_field(self): + self.field_test('email_field') + + def test_file_field(self): + self.field_test('file_field') + + def test_image_field(self): + self.field_test('image_field') + + def test_slug_field(self): + self.field_test('slug_field') + + def test_url_field(self): + self.field_test('url_field') -- cgit v1.2.3 From b9b22976125fffa4552da695183bf75fbaf0b927 Mon Sep 17 00:00:00 2001 From: Pablo Recio Date: Sat, 18 May 2013 17:06:25 +0200 Subject: Tests proper encoding in JSONRenderer and UnicodeJSONRenderer --- rest_framework/tests/renderers.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'rest_framework/tests') diff --git a/rest_framework/tests/renderers.py b/rest_framework/tests/renderers.py index 40bac9cb..739f9184 100644 --- a/rest_framework/tests/renderers.py +++ b/rest_framework/tests/renderers.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- from decimal import Decimal from django.core.cache import cache from django.test import TestCase @@ -8,7 +9,7 @@ from rest_framework.compat import yaml, etree, patterns, url, include from rest_framework.response import Response from rest_framework.views import APIView from rest_framework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer, \ - XMLRenderer, JSONPRenderer, BrowsableAPIRenderer + XMLRenderer, JSONPRenderer, BrowsableAPIRenderer, UnicodeJSONRenderer from rest_framework.parsers import YAMLParser, XMLParser from rest_framework.settings import api_settings from rest_framework.compat import StringIO @@ -254,6 +255,23 @@ class JSONRendererTests(TestCase): content = renderer.render(obj, 'application/json; indent=2') self.assertEqual(strip_trailing_whitespace(content), _indented_repr) + def test_check_ascii(self): + obj = {'countries': ['United Kingdom', 'France', 'España']} + renderer = JSONRenderer() + content = renderer.render(obj, 'application/json') + self.assertEqual(content, '{"countries": ["United Kingdom", "France", "Espa\\u00f1a"]}') + + +class UnicodeJSONRendererTests(TestCase): + """ + Tests specific for the Unicode JSON Renderer + """ + def test_proper_encoding(self): + obj = {'countries': ['United Kingdom', 'France', 'España']} + renderer = UnicodeJSONRenderer() + content = renderer.render(obj, 'application/json') + self.assertEqual(content, '{"countries": ["United Kingdom", "France", "España"]}') + class JSONPRendererTests(TestCase): """ -- cgit v1.2.3 From 0d3d66cb0232e1067600ef22fcf88937ac6bee9d Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sat, 18 May 2013 17:21:43 +0100 Subject: Added proper charset support --- rest_framework/tests/htmlrenderer.py | 10 ++++---- rest_framework/tests/negotiation.py | 28 ++++---------------- rest_framework/tests/response.py | 50 ++++++++++++++++++++---------------- 3 files changed, 38 insertions(+), 50 deletions(-) (limited to 'rest_framework/tests') diff --git a/rest_framework/tests/htmlrenderer.py b/rest_framework/tests/htmlrenderer.py index 8f2e2b5a..5d18a6e8 100644 --- a/rest_framework/tests/htmlrenderer.py +++ b/rest_framework/tests/htmlrenderer.py @@ -66,19 +66,19 @@ class TemplateHTMLRendererTests(TestCase): def test_simple_html_view(self): response = self.client.get('/') self.assertContains(response, "example: foobar") - self.assertEqual(response['Content-Type'], 'text/html') + self.assertEqual(response['Content-Type'], 'text/html; charset=utf-8') def test_not_found_html_view(self): response = self.client.get('/not_found') self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) self.assertEqual(response.content, six.b("404 Not Found")) - self.assertEqual(response['Content-Type'], 'text/html') + self.assertEqual(response['Content-Type'], 'text/html; charset=utf-8') def test_permission_denied_html_view(self): response = self.client.get('/permission_denied') self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) self.assertEqual(response.content, six.b("403 Forbidden")) - self.assertEqual(response['Content-Type'], 'text/html') + self.assertEqual(response['Content-Type'], 'text/html; charset=utf-8') class TemplateHTMLRendererExceptionTests(TestCase): @@ -109,10 +109,10 @@ class TemplateHTMLRendererExceptionTests(TestCase): response = self.client.get('/not_found') self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) self.assertEqual(response.content, six.b("404: Not found")) - self.assertEqual(response['Content-Type'], 'text/html') + self.assertEqual(response['Content-Type'], 'text/html; charset=utf-8') def test_permission_denied_html_view_with_template(self): response = self.client.get('/permission_denied') self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) self.assertEqual(response.content, six.b("403: Permission denied")) - self.assertEqual(response['Content-Type'], 'text/html') + self.assertEqual(response['Content-Type'], 'text/html; charset=utf-8') diff --git a/rest_framework/tests/negotiation.py b/rest_framework/tests/negotiation.py index d7ef6470..7f84827f 100644 --- a/rest_framework/tests/negotiation.py +++ b/rest_framework/tests/negotiation.py @@ -12,15 +12,14 @@ factory = RequestFactory() class MockJSONRenderer(BaseRenderer): media_type = 'application/json' + class MockHTMLRenderer(BaseRenderer): media_type = 'text/html' + class NoCharsetSpecifiedRenderer(BaseRenderer): media_type = 'my/media' -class CharsetSpecifiedRenderer(BaseRenderer): - media_type = 'my/media' - charset = 'mycharset' class TestAcceptedMediaType(TestCase): def setUp(self): @@ -32,32 +31,15 @@ class TestAcceptedMediaType(TestCase): def test_client_without_accept_use_renderer(self): request = Request(factory.get('/')) - accepted_renderer, accepted_media_type, charset = self.select_renderer(request) + accepted_renderer, accepted_media_type = self.select_renderer(request) self.assertEqual(accepted_media_type, 'application/json') def test_client_underspecifies_accept_use_renderer(self): request = Request(factory.get('/', HTTP_ACCEPT='*/*')) - accepted_renderer, accepted_media_type, charset = self.select_renderer(request) + accepted_renderer, accepted_media_type = self.select_renderer(request) self.assertEqual(accepted_media_type, 'application/json') def test_client_overspecifies_accept_use_client(self): request = Request(factory.get('/', HTTP_ACCEPT='application/json; indent=8')) - accepted_renderer, accepted_media_type, charset = self.select_renderer(request) + accepted_renderer, accepted_media_type = self.select_renderer(request) self.assertEqual(accepted_media_type, 'application/json; indent=8') - -class TestCharset(TestCase): - def setUp(self): - self.renderers = [NoCharsetSpecifiedRenderer()] - self.negotiator = DefaultContentNegotiation() - - def test_returns_none_if_no_charset_set(self): - request = Request(factory.get('/')) - renderers = [NoCharsetSpecifiedRenderer()] - _, _, charset = self.negotiator.select_renderer(request, renderers) - self.assertIsNone(charset) - - def test_returns_attribute_from_renderer_if_charset_is_set(self): - request = Request(factory.get('/')) - renderers = [CharsetSpecifiedRenderer()] - _, _, charset = self.negotiator.select_renderer(request, renderers) - self.assertEquals(CharsetSpecifiedRenderer.charset, charset) \ No newline at end of file diff --git a/rest_framework/tests/response.py b/rest_framework/tests/response.py index f2a1c635..8f1163e8 100644 --- a/rest_framework/tests/response.py +++ b/rest_framework/tests/response.py @@ -12,6 +12,7 @@ from rest_framework.renderers import ( from rest_framework.settings import api_settings from rest_framework.compat import six + class MockPickleRenderer(BaseRenderer): media_type = 'application/pickle' @@ -19,6 +20,7 @@ class MockPickleRenderer(BaseRenderer): class MockJsonRenderer(BaseRenderer): media_type = 'application/json' + class MockTextMediaRenderer(BaseRenderer): media_type = 'text/html' @@ -44,6 +46,7 @@ class RendererB(BaseRenderer): def render(self, data, media_type=None, renderer_context=None): return RENDERER_B_SERIALIZER(data) + class RendererC(RendererB): media_type = 'mock/rendererc' format = 'formatc' @@ -56,6 +59,14 @@ class MockView(APIView): def get(self, request, **kwargs): return Response(DUMMYCONTENT, status=DUMMYSTATUS) + +class MockViewSettingCharset(APIView): + renderer_classes = (RendererA, RendererB, RendererC) + + def get(self, request, **kwargs): + return Response(DUMMYCONTENT, status=DUMMYSTATUS, charset='setbyview') + + class HTMLView(APIView): renderer_classes = (BrowsableAPIRenderer, ) @@ -70,6 +81,7 @@ class HTMLView1(APIView): return Response('text') urlpatterns = patterns('', + url(r'^setbyview$', MockViewSettingCharset.as_view(renderer_classes=[RendererA, RendererB, RendererC])), url(r'^.*\.(?P.+)$', MockView.as_view(renderer_classes=[RendererA, RendererB, RendererC])), url(r'^$', MockView.as_view(renderer_classes=[RendererA, RendererB, RendererC])), url(r'^html$', HTMLView.as_view()), @@ -178,43 +190,37 @@ class Issue122Tests(TestCase): """ self.client.get('/html1') + class Issue807Testts(TestCase): """ Covers #807 """ - + urls = 'rest_framework.tests.response' - + def test_does_not_append_charset_by_default(self): """ - For backwards compatibility `REST_FRAMEWORK['DEFAULT_CHARSET']` defaults - to None, so that all legacy code works as expected. + Renderers don't include a charset unless set explicitly. """ headers = {"HTTP_ACCEPT": RendererA.media_type} resp = self.client.get('/', **headers) - self.assertEquals(RendererA.media_type, resp['Content-Type']) - + self.assertEqual(RendererA.media_type, resp['Content-Type']) + def test_if_there_is_charset_specified_on_renderer_it_gets_appended(self): """ If renderer class has charset attribute declared, it gets appended to Response's Content-Type """ - resp = self.client.get('/?format=%s' % RendererC.format) + headers = {"HTTP_ACCEPT": RendererC.media_type} + resp = self.client.get('/', **headers) expected = "{0}; charset={1}".format(RendererC.media_type, RendererC.charset) - self.assertEquals(expected, resp['Content-Type']) - - def test_if_there_is_default_charset_specified_it_gets_appended(self): + self.assertEqual(expected, resp['Content-Type']) + + def test_charset_set_explictly_on_response(self): """ - If user defines `REST_FRAMEWORK['DEFAULT_CHARSET']` it will get appended - to Content-Type of all responses. + The charset may be set explictly on the response. """ - original_default_charset = api_settings.DEFAULT_CHARSET - api_settings.DEFAULT_CHARSET = "utf-8" - headers = {'HTTP_ACCEPT': RendererA.media_type} - resp = self.client.get('/', **headers) - expected = "{0}; charset={1}".format( - RendererA.media_type, - api_settings.DEFAULT_CHARSET - ) - self.assertEquals(expected, resp['Content-Type']) - api_settings.DEFAULT_CHARSET = original_default_charset \ No newline at end of file + headers = {"HTTP_ACCEPT": RendererC.media_type} + resp = self.client.get('/setbyview', **headers) + expected = "{0}; charset={1}".format(RendererC.media_type, 'setbyview') + self.assertEqual(expected, resp['Content-Type']) -- cgit v1.2.3