from __future__ import unicode_literals import json from django.test import TestCase from rest_framework import fields as drf_fields from rest_framework_mongoengine.serializers import ( DocumentSerializer, DynamicDocumentSerializer, EmbeddedDocumentSerializer ) from .models import ( DocumentEmbeddingDynamic, DumbDocument, DumbDynamic, DumbDynamicEmbedded, DumbEmbedded, EmbeddingDynamic ) from .utils import dedent class DumbDocumentSerializer(DocumentSerializer): class Meta: model = DumbDocument fields = '__all__' class TestDynamicDataIntegration(TestCase): """ Tests that if we pass dynamic data to a DocumentSerializer, they won't make it into corresponding Document. """ def doCleanups(self): DumbDocument.drop_collection() def test_create(self): data = {'name': r'Joe', 'foo': 1, 'unexpected': r'data'} serializer = DumbDocumentSerializer(data=data) assert serializer.is_valid(raise_exception=True) instance = serializer.save() assert instance.name == r'Joe' assert instance.foo == 1 assert not hasattr(instance, 'unexpected') expected = { 'id': str(instance.id), 'name': r'Joe', 'foo': 1 } assert serializer.data == expected def test_update(self): instance = DumbDocument.objects.create(name=u'Joe', foo=1) data = {'name': r'Jack', 'foo': 2, 'unexpected': r'data'} serializer = DumbDocumentSerializer(instance, data=data) assert serializer.is_valid(), serializer.errors instance = serializer.save() assert instance.name == r'Jack' assert instance.foo == 2 assert not hasattr(instance, 'unexpected') expected = { 'id': str(instance.id), 'name': r'Jack', 'foo': 2 } assert serializer.data == expected class TestDynamicMapping(TestCase): def test_declared(self): class TestSerializer(DynamicDocumentSerializer): class Meta: model = DumbDynamic fields = '__all__' expected = dedent(""" TestSerializer(): id = ObjectIdField(read_only=True) name = CharField(required=False) foo = IntegerField(required=False) """) assert repr(TestSerializer()) == expected def test_extended(self): class TestSerializer(DynamicDocumentSerializer): bar = drf_fields.CharField(required=False) class Meta: model = DumbDynamic fields = '__all__' expected = dedent(""" TestSerializer(): id = ObjectIdField(read_only=True) bar = CharField(required=False) name = CharField(required=False) foo = IntegerField(required=False) """) assert repr(TestSerializer()) == expected class TestSerializer(DynamicDocumentSerializer): class Meta: model = DumbDynamic fields = '__all__' class TestDynamicIntegration(TestCase): def doCleanups(self): DumbDynamic.drop_collection() def test_parsing(self): input_data = { 'foo': 42, 'bar': 43, 'baz': "Baz" } serializer = TestSerializer(data=input_data) assert serializer.is_valid(), serializer.errors expected = { 'foo': 42, 'bar': 43, 'baz': "Baz" } assert serializer.validated_data == expected def test_retrieval(self): instance = DumbDynamic.objects.create(foo=42, bar=43, baz="Baz") serializer = TestSerializer(instance) expected = { 'id': str(instance.id), 'name': None, 'foo': 42, 'bar': 43, 'baz': "Baz" } assert serializer.data == expected def test_create(self): data = { 'foo': 42, 'bar': 43, 'baz': "Baz" } serializer = TestSerializer(data=data) assert serializer.is_valid(), serializer.errors instance = serializer.save() assert instance.foo == 42 assert instance.bar == 43 assert instance.baz == "Baz" expected = { 'id': str(instance.id), 'name': None, 'foo': 42, 'bar': 43, 'baz': "Baz" } assert serializer.data == expected def test_update(self): instance = DumbDynamic.objects.create(foo=42, bar=43, baz="z") data = {'foo': 142, 'bar': 143, 'baz': "Baz"} serializer = TestSerializer(instance, data=data) assert serializer.is_valid(), serializer.errors instance = serializer.save() assert instance.foo == 142 assert instance.bar == 143 assert instance.baz == "Baz" expected = { 'id': str(instance.id), 'name': None, 'foo': 142, 'bar': 143, 'baz': "Baz" } assert serializer.data == expected # Test that DynamicDocumentSerializer interprets EmbeddedDocumentSerializer # right. class DumbEmbeddedSerializer(EmbeddedDocumentSerializer): class Meta: model = DumbEmbedded fields = '__all__' class EmbeddingDynamicSerializer(DynamicDocumentSerializer): embedded = DumbEmbeddedSerializer() class Meta: model = EmbeddingDynamic fields = ('name', 'foo', 'embedded') class TestEmbeddingDynamicMapping(TestCase): def test_repr(self): expected = dedent(""" EmbeddingDynamicSerializer(): name = CharField(required=False) foo = IntegerField(required=False) embedded = DumbEmbeddedSerializer(): name = CharField(required=False) foo = IntegerField(required=False) """) assert repr(EmbeddingDynamicSerializer()) == expected class TestEmbeddingDynamicIntegration(TestCase): data = { 'name': "Ivan", 'foo': 42, 'bar': 43, 'baz': "Baz", 'embedded': { 'name': 'Dumb', 'foo': 2 } } def create_instance(self): return EmbeddingDynamic.objects.create( name="Ivan", foo=42, bar=43, baz="Baz", embedded=DumbEmbedded(name='Dumb', foo=2) ) def test_parsing(self): serializer = EmbeddingDynamicSerializer(data=self.data) assert serializer.is_valid(), serializer.errors assert serializer.validated_data == self.data def test_retrieval(self): instance = self.create_instance() serializer = EmbeddingDynamicSerializer(instance) assert serializer.data == self.data def test_create(self): serializer = EmbeddingDynamicSerializer(data=self.data) assert serializer.is_valid(), serializer.errors instance = serializer.save() assert instance.name == "Ivan" assert instance.foo == 42 assert instance.bar == 43 assert instance.baz == "Baz" assert instance.embedded.name == "Dumb" assert instance.embedded.foo == 2 assert serializer.data == self.data def test_update(self): instance = self.create_instance() new_data = { 'name': "Ivan", 'foo': 142, 'bar': 143, 'baz': u"Baz", 'embedded': { 'name': 'Bright', 'foo': 3 } } serializer = EmbeddingDynamicSerializer(instance, data=new_data) assert serializer.is_valid(), serializer.errors instance = serializer.save() assert instance.foo == 142 assert instance.bar == 143 assert instance.baz == "Baz" assert instance.embedded.name == 'Bright' assert instance.embedded.foo == 3 # Same JSON data may be represented in different ways in python # (dicts/OrderedDicts, unicode/string, different order) # so let's just compare JSONs: serializer_data_json = json.loads(json.dumps(sorted(serializer.data))) new_data_json = json.loads(json.dumps(sorted(new_data))) assert serializer_data_json == new_data_json def doCleanups(self): EmbeddingDynamic.drop_collection() class DumbDynamicEmbeddedSerializer(EmbeddedDocumentSerializer, DynamicDocumentSerializer): class Meta: model = DumbDynamicEmbedded fields = '__all__' class DocumentEmbeddingDynamicSerializer(DocumentSerializer): embedded = DumbDynamicEmbeddedSerializer() class Meta: model = DocumentEmbeddingDynamic fields = ('name', 'foo', 'embedded') class TestDocumentEmbeddingDynamicMapping(TestCase): def test_repr(self): expected = dedent(""" DocumentEmbeddingDynamicSerializer(): name = CharField(required=False) foo = IntegerField(required=False) embedded = DumbDynamicEmbeddedSerializer(): name = CharField(required=False) foo = IntegerField(required=False) """) assert repr(DocumentEmbeddingDynamicSerializer()) == expected class TestDocumentEmbeddingDynamicIntegration(TestCase): data = { 'name': 'Ivan', 'foo': 42, 'embedded': { 'name': 'Dumb', 'foo': 2, 'bar': 43, 'baz': 'Baz', }, } def create_instance(self): return DocumentEmbeddingDynamic.objects.create( name='Ivan', foo=42, embedded=DumbDynamicEmbedded(name='Dumb', foo=2, bar=43, baz='Baz') ) def test_parsing(self): serializer = DocumentEmbeddingDynamicSerializer(data=self.data) assert serializer.is_valid(), serializer.errors assert serializer.validated_data == self.data def test_retrieval(self): instance = self.create_instance() serializer = DocumentEmbeddingDynamicSerializer(instance) assert serializer.data == self.data def test_create(self): serializer = DocumentEmbeddingDynamicSerializer(data=self.data) assert serializer.is_valid(), serializer.errors instance = serializer.save() assert instance.name == 'Ivan' assert instance.foo == 42 assert instance.embedded.name == 'Dumb' assert instance.embedded.foo == 2 assert instance.embedded.bar == 43 assert instance.embedded.baz == 'Baz' def test_update(self): instance = self.create_instance() new_data = { 'name': 'Ivan', 'foo': 142, 'embedded': { 'name': 'Bright', 'foo': 3, 'bar': 143, }, } serializer = DocumentEmbeddingDynamicSerializer(instance, data=new_data) assert serializer.is_valid(), serializer.errors instance = serializer.save() assert instance.name == 'Ivan' assert instance.foo == 142 assert instance.embedded.name == 'Bright' assert instance.embedded.foo == 3 assert instance.embedded.bar == 143 assert not hasattr(instance.embedded, 'baz') serializer_data_json = json.loads(json.dumps(sorted(serializer.data))) new_data_json = json.loads(json.dumps(sorted(new_data))) assert serializer_data_json == new_data_json def doCleanups(self): DocumentEmbeddingDynamic.drop_collection()