diff --git a/tests/test_bound_fields.py b/tests/test_bound_fields.py index e1f6cd88b..f2fac8f0d 100644 --- a/tests/test_bound_fields.py +++ b/tests/test_bound_fields.py @@ -38,10 +38,6 @@ class TestSimpleBoundField: serializer = ExampleSerializer(data={'text': 'x' * 1000, 'amount': 123}) serializer.is_valid() - # TODO Should we add the _errors with ValidationError to the bound_field.errors to get acces to the error code? - assert serializer._errors['text'].detail[0].detail == ['Ensure this field has no more than 100 characters.'] - assert serializer._errors['text'].detail[0].code == 'max_length' - assert serializer['text'].value == 'x' * 1000 assert serializer['text'].errors == ['Ensure this field has no more than 100 characters.'] assert serializer['text'].name == 'text' diff --git a/tests/test_fields.py b/tests/test_fields.py index 0c1bbfc85..9cb59f7da 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -10,7 +10,6 @@ from django.utils import timezone import rest_framework from rest_framework import serializers -from rest_framework.exceptions import ValidationError # Tests for field keyword arguments and core functionality. @@ -427,13 +426,7 @@ class FieldValues: for input_value, expected_failure in get_items(self.invalid_inputs): with pytest.raises(serializers.ValidationError) as exc_info: self.field.run_validation(input_value) - - if isinstance(exc_info.value.detail[0], ValidationError): - failure = exc_info.value.detail[0].detail - else: - failure = exc_info.value.detail - - assert failure == expected_failure + assert exc_info.value.detail == expected_failure def test_outputs(self): for output_value, expected_output in get_items(self.outputs): @@ -1400,10 +1393,7 @@ class TestFieldFieldWithName(FieldValues): # call into it's regular validation, or require PIL for testing. class FailImageValidation(object): def to_python(self, value): - raise serializers.ValidationError( - self.error_messages['invalid_image'], - code='invalid_image' - ) + raise serializers.ValidationError(self.error_messages['invalid_image']) class PassImageValidation(object): diff --git a/tests/test_relations_hyperlink.py b/tests/test_relations_hyperlink.py index 2bf311d8e..c0642eda2 100644 --- a/tests/test_relations_hyperlink.py +++ b/tests/test_relations_hyperlink.py @@ -245,8 +245,6 @@ class HyperlinkedForeignKeyTests(TestCase): serializer = ForeignKeySourceSerializer(instance, data=data, context={'request': request}) self.assertFalse(serializer.is_valid()) self.assertEqual(serializer.errors, {'target': ['Incorrect type. Expected URL string, received int.']}) - self.assertEqual(serializer._errors['target'].detail, ['Incorrect type. Expected URL string, received int.']) - self.assertEqual(serializer._errors['target'].code, 'incorrect_type') def test_reverse_foreign_key_update(self): data = {'url': 'http://testserver/foreignkeytarget/2/', 'name': 'target-2', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/3/']} @@ -318,8 +316,6 @@ class HyperlinkedForeignKeyTests(TestCase): serializer = ForeignKeySourceSerializer(instance, data=data, context={'request': request}) self.assertFalse(serializer.is_valid()) self.assertEqual(serializer.errors, {'target': ['This field may not be null.']}) - self.assertEqual(serializer._errors['target'].detail, ['This field may not be null.']) - self.assertEqual(serializer._errors['target'].code, 'null') class HyperlinkedNullableForeignKeyTests(TestCase): diff --git a/tests/test_relations_pk.py b/tests/test_relations_pk.py index 49110d2de..169f7d9c5 100644 --- a/tests/test_relations_pk.py +++ b/tests/test_relations_pk.py @@ -235,11 +235,7 @@ class PKForeignKeyTests(TestCase): instance = ForeignKeySource.objects.get(pk=1) serializer = ForeignKeySourceSerializer(instance, data=data) self.assertFalse(serializer.is_valid()) - self.assertEqual(serializer.errors, - {'target': ['Incorrect type. Expected pk value, received %s.' % six.text_type.__name__]}) - self.assertEqual(serializer._errors['target'].detail, - ['Incorrect type. Expected pk value, received %s.' % six.text_type.__name__]) - self.assertEqual(serializer._errors['target'].code, 'incorrect_type') + self.assertEqual(serializer.errors, {'target': ['Incorrect type. Expected pk value, received %s.' % six.text_type.__name__]}) def test_reverse_foreign_key_update(self): data = {'id': 2, 'name': 'target-2', 'sources': [1, 3]} @@ -311,8 +307,6 @@ class PKForeignKeyTests(TestCase): serializer = ForeignKeySourceSerializer(instance, data=data) self.assertFalse(serializer.is_valid()) self.assertEqual(serializer.errors, {'target': ['This field may not be null.']}) - self.assertEqual(serializer._errors['target'].detail, ['This field may not be null.']) - self.assertEqual(serializer._errors['target'].code, 'null') def test_foreign_key_with_unsaved(self): source = ForeignKeySource(name='source-unsaved') diff --git a/tests/test_relations_slug.py b/tests/test_relations_slug.py index 936546b8d..680aee417 100644 --- a/tests/test_relations_slug.py +++ b/tests/test_relations_slug.py @@ -105,8 +105,6 @@ class SlugForeignKeyTests(TestCase): serializer = ForeignKeySourceSerializer(instance, data=data) self.assertFalse(serializer.is_valid()) self.assertEqual(serializer.errors, {'target': ['Object with name=123 does not exist.']}) - self.assertEqual(serializer._errors['target'].detail, ['Object with name=123 does not exist.']) - self.assertEqual(serializer._errors['target'].code, 'does_not_exist') def test_reverse_foreign_key_update(self): data = {'id': 2, 'name': 'target-2', 'sources': ['source-1', 'source-3']} @@ -179,8 +177,6 @@ class SlugForeignKeyTests(TestCase): serializer = ForeignKeySourceSerializer(instance, data=data) self.assertFalse(serializer.is_valid()) self.assertEqual(serializer.errors, {'target': ['This field may not be null.']}) - self.assertEqual(serializer._errors['target'].detail, ['This field may not be null.']) - self.assertEqual(serializer._errors['target'].code, 'null') class SlugNullableForeignKeyTests(TestCase): diff --git a/tests/test_serializer.py b/tests/test_serializer.py index 97a2c642e..741c6ab17 100644 --- a/tests/test_serializer.py +++ b/tests/test_serializer.py @@ -7,7 +7,6 @@ import pytest from rest_framework import serializers from rest_framework.compat import unicode_repr -from rest_framework.fields import DjangoValidationError from .utils import MockObject @@ -33,8 +32,6 @@ class TestSerializer: assert not serializer.is_valid() assert serializer.validated_data == {} assert serializer.errors == {'integer': ['This field is required.']} - assert serializer._errors['integer'].detail == ['This field is required.'] - assert serializer._errors['integer'].code == 'required' def test_partial_validation(self): serializer = self.Serializer(data={'char': 'abc'}, partial=True) @@ -72,10 +69,7 @@ class TestValidateMethod: integer = serializers.IntegerField() def validate(self, attrs): - raise serializers.ValidationError( - 'Non field error', - code='test' - ) + raise serializers.ValidationError('Non field error') serializer = ExampleSerializer(data={'char': 'abc', 'integer': 123}) assert not serializer.is_valid() @@ -315,27 +309,3 @@ class TestCacheSerializerData: pickled = pickle.dumps(serializer.data) data = pickle.loads(pickled) assert data == {'field1': 'a', 'field2': 'b'} - - -class TestGetValidationErrorDetail: - def test_get_validation_error_detail_converts_django_errors(self): - exc = DjangoValidationError("Missing field.", code='required') - detail = serializers.get_validation_error_detail(exc) - assert detail['non_field_errors'][0].detail == ['Missing field.'] - assert detail['non_field_errors'][0].code == 'required' - - -class TestCapturingDjangoValidationError: - def test_django_validation_error_on_a_field_is_converted(self): - class ExampleSerializer(serializers.Serializer): - field = serializers.CharField() - - def validate_field(self, value): - raise DjangoValidationError( - 'validation failed' - ) - - serializer = ExampleSerializer(data={'field': 'a'}) - assert not serializer.is_valid() - assert serializer.errors['field'][0].detail == ['validation failed'] - assert serializer.errors['field'][0].code == 'invalid' diff --git a/tests/test_serializer_bulk_update.py b/tests/test_serializer_bulk_update.py index 2b67ff5c7..8d7240a7b 100644 --- a/tests/test_serializer_bulk_update.py +++ b/tests/test_serializer_bulk_update.py @@ -67,25 +67,16 @@ class BulkCreateSerializerTests(TestCase): 'author': 'Haruki Murakami' } ] - - serializer = self.BookSerializer(data=data, many=True) - self.assertEqual(serializer.is_valid(), False) - expected_errors = [ {}, {}, {'id': ['A valid integer is required.']} ] + serializer = self.BookSerializer(data=data, many=True) + self.assertEqual(serializer.is_valid(), False) self.assertEqual(serializer.errors, expected_errors) - for idx, error in enumerate(serializer._errors): - if idx < 2: - self.assertEqual(error, {}) - else: - self.assertEqual(error['id'].detail, ['A valid integer is required.']) - self.assertEqual(error['id'].code, 'invalid') - def test_invalid_list_datatype(self): """ Data containing list of incorrect data type should return errors. @@ -96,10 +87,13 @@ class BulkCreateSerializerTests(TestCase): text_type_string = six.text_type.__name__ message = 'Invalid data. Expected a dictionary, but got %s.' % text_type_string + expected_errors = [ + {'non_field_errors': [message]}, + {'non_field_errors': [message]}, + {'non_field_errors': [message]} + ] - for error in serializer.errors: - self.assertEqual(error['non_field_errors'][0].detail, [message]) - self.assertEqual(error['non_field_errors'][0].code, 'invalid') + self.assertEqual(serializer.errors, expected_errors) def test_invalid_single_datatype(self): """ @@ -109,9 +103,9 @@ class BulkCreateSerializerTests(TestCase): serializer = self.BookSerializer(data=data, many=True) self.assertEqual(serializer.is_valid(), False) - self.assertEqual(serializer.errors['non_field_errors'][0].detail, - ['Expected a list of items but got type "int".']) - self.assertEqual(serializer.errors['non_field_errors'][0].code, 'not_a_list') + expected_errors = {'non_field_errors': ['Expected a list of items but got type "int".']} + + self.assertEqual(serializer.errors, expected_errors) def test_invalid_single_object(self): """ @@ -126,7 +120,6 @@ class BulkCreateSerializerTests(TestCase): serializer = self.BookSerializer(data=data, many=True) self.assertEqual(serializer.is_valid(), False) - self.assertEqual(serializer.errors['non_field_errors'][0].detail, - ['Expected a list of items but got type "dict".']) + expected_errors = {'non_field_errors': ['Expected a list of items but got type "dict".']} - self.assertEqual(serializer.errors['non_field_errors'][0].code, 'not_a_list') + self.assertEqual(serializer.errors, expected_errors) diff --git a/tests/test_serializer_lists.py b/tests/test_serializer_lists.py index 81aed3574..607ddba04 100644 --- a/tests/test_serializer_lists.py +++ b/tests/test_serializer_lists.py @@ -280,10 +280,7 @@ class TestListSerializerClass: def test_list_serializer_class_validate(self): class CustomListSerializer(serializers.ListSerializer): def validate(self, attrs): - raise serializers.ValidationError( - 'Non field error', - code='test' - ) + raise serializers.ValidationError('Non field error') class TestSerializer(serializers.Serializer): class Meta: diff --git a/tests/test_serializer_nested.py b/tests/test_serializer_nested.py index 870d66c54..aeb092ee0 100644 --- a/tests/test_serializer_nested.py +++ b/tests/test_serializer_nested.py @@ -116,9 +116,6 @@ class TestNestedSerializerWithMany: expected_errors = {'not_allow_null': [serializer.error_messages['null']]} assert serializer.errors == expected_errors - assert serializer._errors['not_allow_null'].detail == [serializer.error_messages['null']] - assert serializer._errors['not_allow_null'].code == 'null' - def test_run_the_field_validation_even_if_the_field_is_null(self): class TestSerializer(self.Serializer): validation_was_run = False @@ -168,11 +165,5 @@ class TestNestedSerializerWithMany: assert not serializer.is_valid() - expected_errors = { - 'not_allow_empty': {'non_field_errors': [serializers.ListSerializer.default_error_messages['empty']]}} + expected_errors = {'not_allow_empty': {'non_field_errors': [serializers.ListSerializer.default_error_messages['empty']]}} assert serializer.errors == expected_errors - - assert serializer._errors['not_allow_empty'].detail['non_field_errors'][0].detail == \ - [serializers.ListSerializer.default_error_messages['empty']] - - assert serializer._errors['not_allow_empty'].detail['non_field_errors'][0].code == 'empty_not_allowed' diff --git a/tests/test_validation.py b/tests/test_validation.py index eb4b6be64..855ff20e0 100644 --- a/tests/test_validation.py +++ b/tests/test_validation.py @@ -41,8 +41,7 @@ class ShouldValidateModelSerializer(serializers.ModelSerializer): def validate_renamed(self, value): if len(value) < 3: - raise serializers.ValidationError('Minimum 3 characters.', - code='min_length') + raise serializers.ValidationError('Minimum 3 characters.') return value class Meta: @@ -92,9 +91,11 @@ class TestAvoidValidation(TestCase): def test_serializer_errors_has_only_invalid_data_error(self): serializer = ValidationSerializer(data='invalid data') self.assertFalse(serializer.is_valid()) - self.assertEqual(serializer.errors['non_field_errors'][0].detail, - ['Invalid data. Expected a dictionary, but got %s.' % type('').__name__]) - self.assertEqual(serializer.errors['non_field_errors'][0].code, 'invalid') + self.assertDictEqual(serializer.errors, { + 'non_field_errors': [ + 'Invalid data. Expected a dictionary, but got %s.' % type('').__name__ + ] + }) # regression tests for issue: 1493 @@ -122,14 +123,8 @@ class TestMaxValueValidatorValidation(TestCase): def test_max_value_validation_serializer_fails(self): serializer = ValidationMaxValueValidatorModelSerializer(data={'number_value': 101}) self.assertFalse(serializer.is_valid()) - self.assertDictEqual({'number_value': ['Ensure this value is less than or equal to 100.']}, serializer.errors) - self.assertEqual(['Ensure this value is less than or equal to 100.'], - serializer._errors['number_value'].detail[0].detail) - self.assertEqual(None, serializer._errors['number_value'].code) - self.assertEqual('max_value', serializer._errors['number_value'].detail[0].code) - def test_max_value_validation_success(self): obj = ValidationMaxValueValidatorModel.objects.create(number_value=100) request = factory.patch('/{0}'.format(obj.pk), {'number_value': 98}, format='json') diff --git a/tests/test_validation_error.py b/tests/test_validation_error.py deleted file mode 100644 index 7e6513127..000000000 --- a/tests/test_validation_error.py +++ /dev/null @@ -1,95 +0,0 @@ -import pytest -from django.test import TestCase - -from rest_framework import serializers, status -from rest_framework.decorators import api_view -from rest_framework.exceptions import ValidationError -from rest_framework.response import Response -from rest_framework.settings import api_settings -from rest_framework.test import APIRequestFactory -from rest_framework.views import APIView - -factory = APIRequestFactory() - - -class ExampleSerializer(serializers.Serializer): - char = serializers.CharField() - integer = serializers.IntegerField() - - -class ErrorView(APIView): - def get(self, request, *args, **kwargs): - ExampleSerializer(data={}).is_valid(raise_exception=True) - - -@api_view(['GET']) -def error_view(request): - ExampleSerializer(data={}).is_valid(raise_exception=True) - - -class TestValidationErrorWithCode(TestCase): - def setUp(self): - self.DEFAULT_HANDLER = api_settings.EXCEPTION_HANDLER - - def exception_handler(exc, request): - if not exc.code: - errors = { - field_name: { - 'code': e.code, - 'message': e.detail - } for field_name, e in exc.detail.items() - } - else: - errors = { - 'code': exc.code, - 'detail': exc.detail - } - return Response(errors, status=status.HTTP_400_BAD_REQUEST) - - api_settings.EXCEPTION_HANDLER = exception_handler - - self.expected_response_data = { - 'char': { - 'message': ['This field is required.'], - 'code': 'required', - }, - 'integer': { - 'message': ['This field is required.'], - 'code': 'required' - }, - } - - def tearDown(self): - api_settings.EXCEPTION_HANDLER = self.DEFAULT_HANDLER - - def test_validation_error_requires_no_code_for_structured_errors(self): - """ - ValidationError can hold a list or dictionary of simple errors, in - which case the code is no longer meaningful and should not be - specified. - """ - with pytest.raises(AssertionError): - serializers.ValidationError([ValidationError("test-detail", "test-code")], code='min_value') - - with pytest.raises(AssertionError): - serializers.ValidationError({}, code='min_value') - - def test_validation_error_stores_error_code(self): - exception = serializers.ValidationError("", code='min_value') - assert exception.code == 'min_value' - - def test_class_based_view_exception_handler(self): - view = ErrorView.as_view() - - request = factory.get('/', content_type='application/json') - response = view(request) - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - self.assertEqual(response.data, self.expected_response_data) - - def test_function_based_view_exception_handler(self): - view = error_view - - request = factory.get('/', content_type='application/json') - response = view(request) - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - self.assertEqual(response.data, self.expected_response_data) diff --git a/tests/test_validators.py b/tests/test_validators.py index ff28908c3..acaaf5743 100644 --- a/tests/test_validators.py +++ b/tests/test_validators.py @@ -47,15 +47,9 @@ class TestUniquenessValidation(TestCase): def test_is_not_unique(self): data = {'username': 'existing'} serializer = UniquenessSerializer(data=data) - assert not serializer.is_valid() - assert serializer.errors == {'username': ['UniquenessModel with this username already exists.']} - assert serializer._errors['username'].code is None - assert serializer._errors['username'].detail[0].code == 'unique' - assert serializer._errors['username'].detail[0].detail == ['UniquenessModel with this username already exists.'] - def test_is_unique(self): data = {'username': 'other'} serializer = UniquenessSerializer(data=data) @@ -156,9 +150,11 @@ class TestUniquenessTogetherValidation(TestCase): data = {'race_name': 'example', 'position': 2} serializer = UniquenessTogetherSerializer(data=data) assert not serializer.is_valid() - assert serializer.errors['non_field_errors'][0].code == 'unique' - assert serializer.errors['non_field_errors'][0].detail == [ - 'The fields race_name, position must make a unique set.'] + assert serializer.errors == { + 'non_field_errors': [ + 'The fields race_name, position must make a unique set.' + ] + } def test_is_unique_together(self): """ @@ -193,8 +189,9 @@ class TestUniquenessTogetherValidation(TestCase): data = {'position': 2} serializer = UniquenessTogetherSerializer(data=data, partial=True) assert not serializer.is_valid() - assert serializer.errors['race_name'][0].code == 'required' - assert serializer.errors['race_name'][0].detail == ['This field is required.'] + assert serializer.errors == { + 'race_name': ['This field is required.'] + } def test_ignore_excluded_fields(self): """ @@ -281,8 +278,9 @@ class TestUniquenessForDateValidation(TestCase): data = {'slug': 'existing', 'published': '2000-01-01'} serializer = UniqueForDateSerializer(data=data) assert not serializer.is_valid() - assert serializer.errors['slug'][0].code == 'unique' - assert serializer.errors['slug'][0].detail == ['This field must be unique for the "published" date.'] + assert serializer.errors == { + 'slug': ['This field must be unique for the "published" date.'] + } def test_is_unique_for_date(self): """