22from httpx import Response
33
44from mpt_api_client .models import Meta , Model
5+ from mpt_api_client .models .model import BaseModel , ModelList , to_snake_case # noqa: WPS347
56
67
78class AgreementDummy (Model ): # noqa: WPS431
@@ -20,6 +21,30 @@ class AgreementWithContactDummy(Model):
2021 contact : ContactDummy
2122
2223
24+ class TypedListItemDummy (BaseModel ):
25+ """Dummy item for typed list tests."""
26+
27+ name : str
28+
29+
30+ class TypedListContainerDummy (BaseModel ):
31+ """Dummy container with a typed list field."""
32+
33+ entries : list [TypedListItemDummy ]
34+
35+
36+ class DictTypedContainerDummy (BaseModel ):
37+ """Dummy container with a dict-typed field."""
38+
39+ metadata : dict [str , str ]
40+
41+
42+ class ScalarListContainerDummy (BaseModel ):
43+ """Dummy container with a list[str] field."""
44+
45+ tags : list [str ]
46+
47+
2348@pytest .fixture
2449def meta_data ():
2550 return {"pagination" : {"limit" : 10 , "offset" : 20 , "total" : 100 }, "ignored" : ["one" ]} # noqa: WPS226
@@ -156,9 +181,11 @@ def test_append():
156181 agreement .parameters .ordering .append (new_param ) # act
157182
158183 assert agreement .id == "AGR-123"
159- assert agreement .parameters .ordering [0 ].external_id == "contact"
160- assert agreement .parameters .ordering [1 ].external_id == "address"
161- assert agreement .parameters .ordering [2 ].external_id == "email"
184+ assert [agr_param .external_id for agr_param in agreement .parameters .ordering ] == [
185+ "contact" ,
186+ "address" ,
187+ "email" ,
188+ ]
162189 agreement_data ["parameters" ]["ordering" ].append (new_param )
163190 assert agreement .to_dict () == agreement_data
164191
@@ -177,8 +204,10 @@ def test_overwrite_list():
177204 agreement .parameters .ordering = ordering_parameters # act
178205
179206 assert agreement .id == "AGR-123"
180- assert agreement .parameters .ordering [0 ].external_id == "contact"
181- assert agreement .parameters .ordering [1 ].external_id == "address"
207+ assert [agr_param .external_id for agr_param in agreement .parameters .ordering ] == [
208+ "contact" ,
209+ "address" ,
210+ ]
182211 assert agreement .to_dict () == agreement_data
183212
184213
@@ -197,6 +226,103 @@ def test_advanced_mapping():
197226 agreement .parameters .ordering = ordering_parameters # act
198227
199228 assert isinstance (agreement .contact , ContactDummy )
200- assert agreement .parameters .ordering [0 ].external_id == "contact"
201- assert agreement .parameters .ordering [1 ].external_id == "address"
229+ assert [agr_param .external_id for agr_param in agreement .parameters .ordering ] == [
230+ "contact" ,
231+ "address" ,
232+ ]
202233 assert agreement .to_dict () == agreement_data
234+
235+
236+ def test_to_snake_case_already_snake ():
237+ result = to_snake_case ("already_snake" ) # act
238+
239+ assert result == "already_snake"
240+
241+
242+ def test_model_list_extend ():
243+ ml = ModelList ([{"id" : "1" }])
244+
245+ ml .extend ([{"id" : "2" }, {"id" : "3" }]) # act
246+
247+ assert [ml_item .id for ml_item in ml ] == ["1" , "2" , "3" ]
248+
249+
250+ def test_model_list_insert ():
251+ ml = ModelList ([{"id" : "1" }, {"id" : "3" }])
252+
253+ ml .insert (1 , {"id" : "2" }) # act
254+
255+ assert [ml_item .id for ml_item in ml ] == ["1" , "2" , "3" ]
256+
257+
258+ def test_model_list_process_item_nested_list ():
259+ nested = [{"id" : "a" }, {"id" : "b" }]
260+
261+ ml = ModelList ([nested ]) # act
262+
263+ assert isinstance (ml [0 ], ModelList )
264+ assert ml [0 ][0 ].id == "a"
265+
266+
267+ def test_model_list_process_item_scalar ():
268+ ml = ModelList (["a" , "b" , "c" ]) # act
269+
270+ assert ml == ["a" , "b" , "c" ]
271+
272+
273+ def test_base_model_getattr_from_dict ():
274+ model = BaseModel (foo = "bar" )
275+
276+ result = model .__getattr__ ("foo" ) # noqa: PLC2801
277+
278+ assert result == "bar"
279+
280+
281+ def test_base_model_setattr_private ():
282+ model = BaseModel (foo = "bar" )
283+
284+ model ._private = "secret" # noqa: SLF001 # act
285+
286+ assert model ._private == "secret" # noqa: SLF001
287+
288+
289+ def test_to_dict_excludes_private_attrs ():
290+ model = BaseModel (foo = "bar" )
291+ model ._private = "secret" # noqa: SLF001
292+
293+ result = model .to_dict ()
294+
295+ assert result == {"foo" : "bar" }
296+ assert "_private" not in result
297+
298+
299+ def test_process_value_typed_list ():
300+ container = TypedListContainerDummy (entries = [{"name" : "one" }, {"name" : "two" }]) # act
301+
302+ assert all (isinstance (entry , TypedListItemDummy ) for entry in container .entries )
303+ assert [entry .name for entry in container .entries ] == ["one" , "two" ]
304+
305+
306+ def test_process_value_existing_base_model ():
307+ nested = BaseModel (value = "test" )
308+ model = BaseModel ()
309+
310+ model .nested = nested # act
311+
312+ assert model .nested is nested
313+
314+
315+ def test_process_value_non_list_target ():
316+ container = DictTypedContainerDummy ()
317+
318+ container .metadata = [{"id" : "1" }] # act
319+
320+ assert isinstance (container .metadata , ModelList )
321+ assert container .metadata [0 ].id == "1"
322+
323+
324+ def test_process_value_scalar_list_elements ():
325+ container = ScalarListContainerDummy (tags = ["a" , "b" , "c" ]) # act
326+
327+ assert isinstance (container .tags , ModelList )
328+ assert list (container .tags ) == ["a" , "b" , "c" ]
0 commit comments