Skip to content

Commit 7d6abc2

Browse files
committed
Test it hard!
1 parent 0086ca3 commit 7d6abc2

File tree

2 files changed

+197
-1
lines changed

2 files changed

+197
-1
lines changed

flask_mongoengine/db_fields.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ def __init__(
137137
)
138138
self.wtf_options = wtf_options
139139
self.wtf_choices_coerce = wtf_choices_coerce or self.DEFAULT_WTF_CHOICES_COERCE
140-
# Some attributes that will be updated by parent methods
140+
# Some attributes that will be updated by super()
141141
self.required = False
142142
self.default = None
143143
self.name = ""

tests/test_db_fields.py

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import pytest
55
from mongoengine import fields as base_fields
66
from pytest_mock import MockerFixture
7+
from wtforms import validators as wtf_validators_
78

89
from flask_mongoengine import db_fields, documents
910

@@ -88,6 +89,12 @@ def test__to_wtf_form__logs_error(self, caplog, TempDocument):
8889

8990

9091
class TestWtfFieldMixin:
92+
# noinspection PyAbstractClass
93+
class WTFieldBaseMRO(db_fields.WtfFieldMixin, base_fields.BaseField):
94+
"""Just an MRO setter for testing any BaseField child."""
95+
96+
pass
97+
9198
def test__init__set_additional_instance_arguments(self, db, mocker: MockerFixture):
9299
checker_spy = mocker.spy(db_fields.WtfFieldMixin, "_ensure_callable_or_list")
93100

@@ -122,6 +129,195 @@ def test__ensure_callable_or_list__raise_error_if_argument_not_callable_and_not_
122129
)
123130
assert str(error.value) == "Argument 'field' must be a list value"
124131

132+
@pytest.mark.parametrize(
133+
"FieldClass",
134+
[
135+
db_fields.WtfFieldMixin,
136+
db_fields.BinaryField,
137+
db_fields.BooleanField,
138+
db_fields.CachedReferenceField,
139+
db_fields.ComplexDateTimeField,
140+
db_fields.DateField,
141+
db_fields.DateTimeField,
142+
db_fields.DecimalField,
143+
db_fields.DictField,
144+
db_fields.DynamicField,
145+
db_fields.EmailField,
146+
db_fields.EmbeddedDocumentField,
147+
db_fields.EmbeddedDocumentListField,
148+
db_fields.EnumField,
149+
db_fields.FileField,
150+
db_fields.FloatField,
151+
db_fields.GenericEmbeddedDocumentField,
152+
db_fields.GenericLazyReferenceField,
153+
db_fields.GenericReferenceField,
154+
db_fields.GeoJsonBaseField,
155+
db_fields.GeoPointField,
156+
db_fields.ImageField,
157+
db_fields.IntField,
158+
db_fields.LazyReferenceField,
159+
db_fields.LineStringField,
160+
db_fields.ListField,
161+
db_fields.LongField,
162+
db_fields.MapField,
163+
db_fields.MultiLineStringField,
164+
db_fields.MultiPointField,
165+
db_fields.MultiPolygonField,
166+
db_fields.ObjectIdField,
167+
db_fields.PointField,
168+
db_fields.PolygonField,
169+
db_fields.ReferenceField,
170+
db_fields.SequenceField,
171+
db_fields.SortedListField,
172+
db_fields.StringField,
173+
db_fields.URLField,
174+
db_fields.UUIDField,
175+
],
176+
)
177+
def test__ensure_nested_field_class__to_wtf_field__method_disabled(
178+
self, FieldClass, mocker: MockerFixture
179+
):
180+
"""
181+
It is expected, that amount of such classes will be decreased in the future.
182+
183+
__init__ method mocked to limit test scope.
184+
"""
185+
mocker.patch.object(db_fields.WtfFieldMixin, "__init__", return_value=None)
186+
field = FieldClass()
187+
with pytest.raises(NotImplementedError):
188+
field.to_wtf_field(model=None, field_kwargs=None)
189+
190+
def test__init__method__warning__if_deprecated__validators__set(self, recwarn):
191+
db_fields.WtfFieldMixin(validators=[])
192+
assert str(recwarn.list[0].message) == (
193+
"Passing 'validators' keyword argument to field definition is "
194+
"deprecated and will be removed in version 3.0.0. "
195+
"Please rename 'validators' to 'wtf_validators'. "
196+
"If both values set, 'wtf_validators' is used."
197+
)
198+
199+
def test__init__method__warning__if_deprecated__filters__set(self, recwarn):
200+
db_fields.WtfFieldMixin(filters=[])
201+
assert str(recwarn.list[0].message) == (
202+
"Passing 'filters' keyword argument to field definition is "
203+
"deprecated and will be removed in version 3.0.0. "
204+
"Please rename 'filters' to 'wtf_filters'. "
205+
"If both values set, 'wtf_filters' is used."
206+
)
207+
208+
def test__wtf_field_class__return__DEFAULT_WTF_FIELD__value_if_no_init_options_set(
209+
self,
210+
):
211+
field = db_fields.WtfFieldMixin()
212+
field.DEFAULT_WTF_FIELD = "fake"
213+
assert field.wtf_field_class == "fake"
214+
215+
def test__wtf_field_class__return__DEFAULT_WTF_CHOICES_FIELD_value_if_choices_options_set(
216+
self,
217+
):
218+
field = db_fields.StringField(choices=(1, 2, 3))
219+
field.DEFAULT_WTF_CHOICES_FIELD = "fake"
220+
assert issubclass(field.__class__, db_fields.WtfFieldMixin)
221+
assert field.wtf_field_class == "fake"
222+
223+
def test__wtf_field_class__return__user_provided_value__if_set(self):
224+
field = db_fields.WtfFieldMixin(wtf_field_class=str)
225+
226+
assert issubclass(field.wtf_field_class, str)
227+
228+
@pytest.mark.parametrize(
229+
["user_dict", "expected_result"],
230+
[
231+
({"fake": "replaced"}, {"fake": "replaced"}),
232+
({"added_arg": "added"}, {"fake": "dict", "added_arg": "added"}),
233+
(None, {"fake": "dict"}),
234+
],
235+
)
236+
def test__wtf_field_options__overwrite_generated_options_with_user_provided(
237+
self, mocker: MockerFixture, user_dict, expected_result
238+
):
239+
mocker.patch.object(
240+
db_fields.WtfFieldMixin,
241+
"wtf_generated_options",
242+
new_callable=lambda: {"fake": "dict"},
243+
)
244+
245+
field = db_fields.WtfFieldMixin(wtf_options=user_dict)
246+
assert field.wtf_field_options == expected_result
247+
248+
def test__wtf_generated_options__correctly_retrieve_label_from_parent_class(self):
249+
"""Test based on base class for all fields."""
250+
default_call = self.WTFieldBaseMRO()
251+
default_call.name = "set not by init" # set by metaclass for documents
252+
with_option_call = self.WTFieldBaseMRO(verbose_name="fake")
253+
254+
assert default_call.wtf_generated_options["label"] == "set not by init"
255+
assert with_option_call.wtf_generated_options["label"] == "fake"
256+
257+
def test__wtf_generated_options__correctly_retrieve_description_from_parent_class(
258+
self,
259+
):
260+
default_call = self.WTFieldBaseMRO()
261+
with_option_call = self.WTFieldBaseMRO(help_text="fake")
262+
263+
assert default_call.wtf_generated_options["description"] == ""
264+
assert with_option_call.wtf_generated_options["description"] == "fake"
265+
266+
def test__wtf_generated_options__correctly_retrieve_default_from_parent_class(self):
267+
default_call = self.WTFieldBaseMRO()
268+
with_option_call = self.WTFieldBaseMRO(default="fake")
269+
270+
assert default_call.wtf_generated_options["default"] is None
271+
assert with_option_call.wtf_generated_options["default"] == "fake"
272+
273+
def test__wtf_generated_options__correctly_retrieve_validators_from_parent_class__and__add_optional_validator__if_field_not_required(
274+
self,
275+
):
276+
default_call = self.WTFieldBaseMRO()
277+
with_option_call = self.WTFieldBaseMRO(wtf_validators=[str, int])
278+
279+
assert isinstance(
280+
default_call.wtf_generated_options["validators"][0],
281+
wtf_validators_.Optional,
282+
)
283+
assert len(with_option_call.wtf_generated_options["validators"]) == 3
284+
assert isinstance(
285+
with_option_call.wtf_generated_options["validators"][-1],
286+
wtf_validators_.Optional,
287+
)
288+
289+
def test__wtf_generated_options__correctly_retrieve_validators_from_parent_class__and__add_required__if_field_required(
290+
self,
291+
):
292+
default_call = self.WTFieldBaseMRO(required=True)
293+
with_option_call = self.WTFieldBaseMRO(required=True, wtf_validators=[str, int])
294+
295+
assert isinstance(
296+
default_call.wtf_generated_options["validators"][0],
297+
wtf_validators_.InputRequired,
298+
)
299+
assert len(with_option_call.wtf_generated_options["validators"]) == 3
300+
assert isinstance(
301+
with_option_call.wtf_generated_options["validators"][-1],
302+
wtf_validators_.InputRequired,
303+
)
304+
305+
def test__wtf_generated_options__correctly_retrieve_filters_from_parent_class(self):
306+
default_call = self.WTFieldBaseMRO()
307+
with_option_call = self.WTFieldBaseMRO(wtf_filters=[str, list])
308+
309+
assert default_call.wtf_generated_options["filters"] == []
310+
assert with_option_call.wtf_generated_options["filters"] == [str, list]
311+
312+
def test__wtf_generated_options__correctly_handle_choices_settings(self):
313+
default_call = self.WTFieldBaseMRO(choices=[1, 2])
314+
with_option_call = self.WTFieldBaseMRO(choices=[1, 2], wtf_choices_coerce=list)
315+
316+
assert default_call.wtf_generated_options["choices"] == [1, 2]
317+
assert default_call.wtf_generated_options["coerce"] is str
318+
assert with_option_call.wtf_generated_options["choices"] == [1, 2]
319+
assert with_option_call.wtf_generated_options["coerce"] is list
320+
125321

126322
class TestBinaryField:
127323
"""Custom test set for :class:`~flask_mongoengine.wtf.db_fields.`"""

0 commit comments

Comments
 (0)