1import copy
2
3import graphene
4from django.db import models
5from graphene import InputObjectType
6from py.test import raises
7from rest_framework import serializers
8
9from ..serializer_converter import convert_serializer_field
10from ..types import DictType
11
12
13def _get_type(
14    rest_framework_field, is_input=True, convert_choices_to_enum=True, **kwargs
15):
16    # prevents the following error:
17    # AssertionError: The `source` argument is not meaningful when applied to a `child=` field.
18    # Remove `source=` from the field declaration.
19    # since we are reusing the same child in when testing the required attribute
20
21    if "child" in kwargs:
22        kwargs["child"] = copy.deepcopy(kwargs["child"])
23
24    field = rest_framework_field(**kwargs)
25
26    return convert_serializer_field(
27        field, is_input=is_input, convert_choices_to_enum=convert_choices_to_enum
28    )
29
30
31def assert_conversion(rest_framework_field, graphene_field, **kwargs):
32    graphene_type = _get_type(
33        rest_framework_field, help_text="Custom Help Text", **kwargs
34    )
35    assert isinstance(graphene_type, graphene_field)
36
37    graphene_type_required = _get_type(
38        rest_framework_field, help_text="Custom Help Text", required=True, **kwargs
39    )
40    assert isinstance(graphene_type_required, graphene_field)
41
42    return graphene_type
43
44
45def test_should_unknown_rest_framework_field_raise_exception():
46    with raises(Exception) as excinfo:
47        convert_serializer_field(None)
48    assert "Don't know how to convert the serializer field" in str(excinfo.value)
49
50
51def test_should_char_convert_string():
52    assert_conversion(serializers.CharField, graphene.String)
53
54
55def test_should_email_convert_string():
56    assert_conversion(serializers.EmailField, graphene.String)
57
58
59def test_should_slug_convert_string():
60    assert_conversion(serializers.SlugField, graphene.String)
61
62
63def test_should_url_convert_string():
64    assert_conversion(serializers.URLField, graphene.String)
65
66
67def test_should_choice_convert_enum():
68    field = assert_conversion(
69        serializers.ChoiceField,
70        graphene.Enum,
71        choices=[("h", "Hello"), ("w", "World")],
72        source="word",
73    )
74    assert field._meta.enum.__members__["H"].value == "h"
75    assert field._meta.enum.__members__["H"].description == "Hello"
76    assert field._meta.enum.__members__["W"].value == "w"
77    assert field._meta.enum.__members__["W"].description == "World"
78
79
80def test_should_choice_convert_string_if_enum_disabled():
81    assert_conversion(
82        serializers.ChoiceField,
83        graphene.String,
84        choices=[("h", "Hello"), ("w", "World")],
85        source="word",
86        convert_choices_to_enum=False,
87    )
88
89
90def test_should_base_field_convert_string():
91    assert_conversion(serializers.Field, graphene.String)
92
93
94def test_should_regex_convert_string():
95    assert_conversion(serializers.RegexField, graphene.String, regex="[0-9]+")
96
97
98def test_should_uuid_convert_string():
99    if hasattr(serializers, "UUIDField"):
100        assert_conversion(serializers.UUIDField, graphene.String)
101
102
103def test_should_model_convert_field():
104    class MyModelSerializer(serializers.ModelSerializer):
105        class Meta:
106            model = None
107            fields = "__all__"
108
109    assert_conversion(MyModelSerializer, graphene.Field, is_input=False)
110
111
112def test_should_date_time_convert_datetime():
113    assert_conversion(serializers.DateTimeField, graphene.types.datetime.DateTime)
114
115
116def test_should_date_convert_date():
117    assert_conversion(serializers.DateField, graphene.types.datetime.Date)
118
119
120def test_should_time_convert_time():
121    assert_conversion(serializers.TimeField, graphene.types.datetime.Time)
122
123
124def test_should_integer_convert_int():
125    assert_conversion(serializers.IntegerField, graphene.Int)
126
127
128def test_should_boolean_convert_boolean():
129    assert_conversion(serializers.BooleanField, graphene.Boolean)
130
131
132def test_should_float_convert_float():
133    assert_conversion(serializers.FloatField, graphene.Float)
134
135
136def test_should_decimal_convert_float():
137    assert_conversion(
138        serializers.DecimalField, graphene.Float, max_digits=4, decimal_places=2
139    )
140
141
142def test_should_list_convert_to_list():
143    class StringListField(serializers.ListField):
144        child = serializers.CharField()
145
146    field_a = assert_conversion(
147        serializers.ListField,
148        graphene.List,
149        child=serializers.IntegerField(min_value=0, max_value=100),
150    )
151
152    assert field_a.of_type == graphene.Int
153
154    field_b = assert_conversion(StringListField, graphene.List)
155
156    assert field_b.of_type == graphene.String
157
158
159def test_should_list_serializer_convert_to_list():
160    class FooModel(models.Model):
161        pass
162
163    class ChildSerializer(serializers.ModelSerializer):
164        class Meta:
165            model = FooModel
166            fields = "__all__"
167
168    class ParentSerializer(serializers.ModelSerializer):
169        child = ChildSerializer(many=True)
170
171        class Meta:
172            model = FooModel
173            fields = "__all__"
174
175    converted_type = convert_serializer_field(
176        ParentSerializer().get_fields()["child"], is_input=True
177    )
178    assert isinstance(converted_type, graphene.List)
179
180    converted_type = convert_serializer_field(
181        ParentSerializer().get_fields()["child"], is_input=False
182    )
183    assert isinstance(converted_type, graphene.List)
184    assert converted_type.of_type is None
185
186
187def test_should_dict_convert_dict():
188    assert_conversion(serializers.DictField, DictType)
189
190
191def test_should_duration_convert_string():
192    assert_conversion(serializers.DurationField, graphene.String)
193
194
195def test_should_file_convert_string():
196    assert_conversion(serializers.FileField, graphene.String)
197
198
199def test_should_filepath_convert_string():
200    assert_conversion(serializers.FilePathField, graphene.Enum, path="/")
201
202
203def test_should_ip_convert_string():
204    assert_conversion(serializers.IPAddressField, graphene.String)
205
206
207def test_should_image_convert_string():
208    assert_conversion(serializers.ImageField, graphene.String)
209
210
211def test_should_json_convert_jsonstring():
212    assert_conversion(serializers.JSONField, graphene.types.json.JSONString)
213
214
215def test_should_multiplechoicefield_convert_to_list_of_enum():
216    field = assert_conversion(
217        serializers.MultipleChoiceField, graphene.List, choices=[1, 2, 3]
218    )
219
220    assert issubclass(field.of_type, graphene.Enum)
221