Skip to content

Commit e0c4df9

Browse files
committed
Finish property tests
#3
1 parent 1c84332 commit e0c4df9

File tree

2 files changed

+293
-6
lines changed

2 files changed

+293
-6
lines changed

openapi_python_client/openapi_parser/properties.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,14 +119,13 @@ class EnumProperty(Property):
119119
""" A property that should use an enum """
120120

121121
values: Dict[str, str]
122-
inverse_values: Dict[str, str] = field(init=False)
123122
reference: Reference = field(init=False)
124123

125124
def __post_init__(self) -> None:
126125
self.reference = Reference(self.name)
127-
self.inverse_values = {v: k for k, v in self.values.items()}
126+
inverse_values = {v: k for k, v in self.values.items()}
128127
if self.default is not None:
129-
self.default = f"{self.reference.class_name}.{self.inverse_values[self.default]}"
128+
self.default = f"{self.reference.class_name}.{inverse_values[self.default]}"
130129

131130
def get_type_string(self) -> str:
132131
""" Get a string representation of type that should be used when declaring this property """
@@ -149,7 +148,7 @@ def values_from_list(l: List[str], /) -> Dict[str, str]:
149148
output: Dict[str, str] = {}
150149

151150
for i, value in enumerate(l):
152-
if value.isalpha():
151+
if value[0].isalpha():
153152
key = value.upper()
154153
else:
155154
key = f"VALUE_{i}"
@@ -227,5 +226,5 @@ def property_from_dict(name: str, required: bool, data: Dict[str, Any]) -> Prope
227226
_type = _openapi_types_to_python_type_strings[data["items"]["type"]]
228227
return ListProperty(name=name, required=required, type=_type, reference=reference, default=None)
229228
elif data["type"] == "object":
230-
return DictProperty(name=name, required=required, default=None)
229+
return DictProperty(name=name, required=required, default=data.get("default"))
231230
raise ValueError(f"Did not recognize type of {data}")

tests/test_openapi_parser/test_properties.py

Lines changed: 289 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import pytest
22

3+
MODULE_NAME = "openapi_python_client.openapi_parser.properties"
4+
35

46
class TestProperty:
57
def test_get_type_string(self):
@@ -85,10 +87,296 @@ def test_get_type_string_when_reference(self, mocker):
8587
p.required = False
8688
assert p.get_type_string() == "Optional[List[MyTestClassName]]"
8789

88-
def test_get_type_string_fails_when_no_type_nor_reference(self, mocker):
90+
def test_get_type_string_fails_when_no_type_nor_reference(self):
8991
from openapi_python_client.openapi_parser.properties import ListProperty
9092

9193
p = ListProperty(name="test", required=True, default=None, type=None, reference=None)
9294

9395
with pytest.raises(ValueError):
9496
p.get_type_string()
97+
98+
99+
class TestEnumProperty:
100+
def test___post_init__(self, mocker):
101+
name = mocker.MagicMock()
102+
fake_reference = mocker.MagicMock(class_name="MyTestEnum")
103+
Reference = mocker.patch(f"{MODULE_NAME}.Reference", return_value=fake_reference)
104+
105+
from openapi_python_client.openapi_parser.properties import EnumProperty
106+
107+
enum_property = EnumProperty(
108+
name=name, required=True, default="second", values={"FIRST": "first", "SECOND": "second"}
109+
)
110+
111+
Reference.assert_called_once_with(name)
112+
assert enum_property.default == "MyTestEnum.SECOND"
113+
114+
def test_get_type_string(self, mocker):
115+
fake_reference = mocker.MagicMock(class_name="MyTestEnum")
116+
mocker.patch(f"{MODULE_NAME}.Reference", return_value=fake_reference)
117+
118+
from openapi_python_client.openapi_parser.properties import EnumProperty
119+
120+
enum_property = EnumProperty(name="test", required=True, default=None, values={})
121+
122+
assert enum_property.get_type_string() == "MyTestEnum"
123+
enum_property.required = False
124+
assert enum_property.get_type_string() == "Optional[MyTestEnum]"
125+
126+
def test_transform(self, mocker):
127+
name = mocker.MagicMock()
128+
mocker.patch(f"{MODULE_NAME}.Reference")
129+
130+
from openapi_python_client.openapi_parser.properties import EnumProperty
131+
132+
enum_property = EnumProperty(name=name, required=True, default=None, values={})
133+
134+
assert enum_property.transform() == f"{name}.value"
135+
136+
def test_constructor_from_dict(self, mocker):
137+
fake_reference = mocker.MagicMock(class_name="MyTestEnum")
138+
mocker.patch(f"{MODULE_NAME}.Reference", return_value=fake_reference)
139+
140+
from openapi_python_client.openapi_parser.properties import EnumProperty
141+
142+
enum_property = EnumProperty(name="test_enum", required=True, default=None, values={})
143+
144+
assert (
145+
enum_property.constructor_from_dict("my_dict")
146+
== 'MyTestEnum(my_dict["test_enum"]) if "test_enum" in my_dict else None'
147+
)
148+
149+
def test_values_from_list(self):
150+
from openapi_python_client.openapi_parser.properties import EnumProperty
151+
152+
data = ["abc", "123", "a23", "1bc"]
153+
154+
result = EnumProperty.values_from_list(data)
155+
156+
assert result == {
157+
"ABC": "abc",
158+
"VALUE_1": "123",
159+
"A23": "a23",
160+
"VALUE_3": "1bc",
161+
}
162+
163+
164+
class TestRefProperty:
165+
def test_get_type_string(self, mocker):
166+
from openapi_python_client.openapi_parser.properties import RefProperty
167+
168+
ref_property = RefProperty(
169+
name="test", required=True, default=None, reference=mocker.MagicMock(class_name="MyRefClass")
170+
)
171+
172+
assert ref_property.get_type_string() == "MyRefClass"
173+
174+
ref_property.required = False
175+
assert ref_property.get_type_string() == "Optional[MyRefClass]"
176+
177+
def test_transform(self, mocker):
178+
from openapi_python_client.openapi_parser.properties import RefProperty
179+
180+
ref_property = RefProperty(name="super_unique_name", required=True, default=None, reference=mocker.MagicMock())
181+
182+
assert ref_property.transform() == "super_unique_name.to_dict()"
183+
184+
185+
class TestPropertyFromDict:
186+
def test_property_from_dict_enum(self, mocker):
187+
name = mocker.MagicMock()
188+
required = mocker.MagicMock()
189+
data = {
190+
"enum": mocker.MagicMock(),
191+
}
192+
EnumProperty = mocker.patch(f"{MODULE_NAME}.EnumProperty")
193+
194+
from openapi_python_client.openapi_parser.properties import property_from_dict
195+
196+
p = property_from_dict(name=name, required=required, data=data)
197+
198+
EnumProperty.values_from_list.assert_called_once_with(data["enum"])
199+
EnumProperty.assert_called_once_with(
200+
name=name, required=required, values=EnumProperty.values_from_list(), default=None
201+
)
202+
assert p == EnumProperty()
203+
204+
EnumProperty.reset_mock()
205+
data["default"] = mocker.MagicMock()
206+
207+
property_from_dict(
208+
name=name, required=required, data=data,
209+
)
210+
EnumProperty.assert_called_once_with(
211+
name=name, required=required, values=EnumProperty.values_from_list(), default=data["default"]
212+
)
213+
214+
def test_property_from_dict_ref(self, mocker):
215+
name = mocker.MagicMock()
216+
required = mocker.MagicMock()
217+
data = {
218+
"$ref": mocker.MagicMock(),
219+
}
220+
Reference = mocker.patch(f"{MODULE_NAME}.Reference")
221+
RefProperty = mocker.patch(f"{MODULE_NAME}.RefProperty")
222+
223+
from openapi_python_client.openapi_parser.properties import property_from_dict
224+
225+
p = property_from_dict(name=name, required=required, data=data)
226+
227+
Reference.assert_called_once_with(data["$ref"])
228+
RefProperty.assert_called_once_with(name=name, required=required, reference=Reference(), default=None)
229+
assert p == RefProperty()
230+
231+
def test_property_from_dict_string_no_format(self, mocker):
232+
name = mocker.MagicMock()
233+
required = mocker.MagicMock()
234+
data = {
235+
"type": "string",
236+
}
237+
StringProperty = mocker.patch(f"{MODULE_NAME}.StringProperty")
238+
239+
from openapi_python_client.openapi_parser.properties import property_from_dict
240+
241+
p = property_from_dict(name=name, required=required, data=data)
242+
243+
StringProperty.assert_called_once_with(name=name, required=required, pattern=None, default=None)
244+
assert p == StringProperty()
245+
246+
# Test optional values
247+
StringProperty.reset_mock()
248+
data["default"] = mocker.MagicMock()
249+
data["pattern"] = mocker.MagicMock()
250+
251+
property_from_dict(
252+
name=name, required=required, data=data,
253+
)
254+
StringProperty.assert_called_once_with(
255+
name=name, required=required, pattern=data["pattern"], default=data["default"]
256+
)
257+
258+
def test_property_from_dict_string_datetime_format(self, mocker):
259+
name = mocker.MagicMock()
260+
required = mocker.MagicMock()
261+
data = {
262+
"type": "string",
263+
"format": "date-time",
264+
}
265+
DateTimeProperty = mocker.patch(f"{MODULE_NAME}.DateTimeProperty")
266+
267+
from openapi_python_client.openapi_parser.properties import property_from_dict
268+
269+
p = property_from_dict(name=name, required=required, data=data)
270+
271+
DateTimeProperty.assert_called_once_with(name=name, required=required, default=None)
272+
assert p == DateTimeProperty()
273+
274+
# Test optional values
275+
DateTimeProperty.reset_mock()
276+
data["default"] = mocker.MagicMock()
277+
278+
property_from_dict(
279+
name=name, required=required, data=data,
280+
)
281+
DateTimeProperty.assert_called_once_with(name=name, required=required, default=data["default"])
282+
283+
def test_property_from_dict_string_unsupported_format(self, mocker):
284+
name = mocker.MagicMock()
285+
required = mocker.MagicMock()
286+
data = {
287+
"type": "string",
288+
"format": mocker.MagicMock(),
289+
}
290+
291+
from openapi_python_client.openapi_parser.properties import property_from_dict
292+
293+
with pytest.raises(ValueError):
294+
property_from_dict(name=name, required=required, data=data)
295+
296+
@pytest.mark.parametrize(
297+
"openapi_type,python_type",
298+
[
299+
("number", "FloatProperty"),
300+
("integer", "IntProperty"),
301+
("boolean", "BooleanProperty"),
302+
("object", "DictProperty"),
303+
],
304+
)
305+
def test_property_from_dict_simple_types(self, mocker, openapi_type, python_type):
306+
name = mocker.MagicMock()
307+
required = mocker.MagicMock()
308+
data = {
309+
"type": openapi_type,
310+
}
311+
clazz = mocker.patch(f"{MODULE_NAME}.{python_type}")
312+
313+
from openapi_python_client.openapi_parser.properties import property_from_dict
314+
315+
p = property_from_dict(name=name, required=required, data=data)
316+
317+
clazz.assert_called_once_with(name=name, required=required, default=None)
318+
assert p == clazz()
319+
320+
# Test optional values
321+
clazz.reset_mock()
322+
data["default"] = mocker.MagicMock()
323+
324+
property_from_dict(
325+
name=name, required=required, data=data,
326+
)
327+
clazz.assert_called_once_with(name=name, required=required, default=data["default"])
328+
329+
def test_property_from_dict_ref_array(self, mocker):
330+
name = mocker.MagicMock()
331+
required = mocker.MagicMock()
332+
ref = mocker.MagicMock()
333+
data = {
334+
"type": "array",
335+
"items": {"$ref": ref},
336+
}
337+
ListProperty = mocker.patch(f"{MODULE_NAME}.ListProperty")
338+
Reference = mocker.patch(f"{MODULE_NAME}.Reference")
339+
340+
from openapi_python_client.openapi_parser.properties import property_from_dict
341+
342+
p = property_from_dict(name=name, required=required, data=data)
343+
344+
Reference.assert_called_once_with(ref)
345+
ListProperty.assert_called_once_with(
346+
name=name, required=required, default=None, type=None, reference=Reference()
347+
)
348+
assert p == ListProperty()
349+
350+
@pytest.mark.parametrize(
351+
"openapi_type,python_type",
352+
[("string", "str"), ("number", "float"), ("integer", "int"), ("boolean", "bool"), ("object", "Dict"),],
353+
)
354+
def test_property_from_dict_simple_array(self, mocker, openapi_type, python_type):
355+
name = mocker.MagicMock()
356+
required = mocker.MagicMock()
357+
data = {
358+
"type": "array",
359+
"items": {"type": openapi_type},
360+
}
361+
ListProperty = mocker.patch(f"{MODULE_NAME}.ListProperty")
362+
363+
from openapi_python_client.openapi_parser.properties import property_from_dict
364+
365+
p = property_from_dict(name=name, required=required, data=data)
366+
367+
ListProperty.assert_called_once_with(
368+
name=name, required=required, default=None, type=python_type, reference=None
369+
)
370+
assert p == ListProperty()
371+
372+
def test_property_from_dict_unsupported_type(self, mocker):
373+
name = mocker.MagicMock()
374+
required = mocker.MagicMock()
375+
data = {
376+
"type": mocker.MagicMock(),
377+
}
378+
379+
from openapi_python_client.openapi_parser.properties import property_from_dict
380+
381+
with pytest.raises(ValueError):
382+
property_from_dict(name=name, required=required, data=data)

0 commit comments

Comments
 (0)