|
2 | 2 |
|
3 | 3 | from __future__ import annotations |
4 | 4 |
|
5 | | -from dataclasses import dataclass |
| 5 | +from dataclasses import dataclass, field |
6 | 6 | from unittest.mock import MagicMock |
7 | 7 |
|
8 | 8 | import pytest |
@@ -57,6 +57,24 @@ class DummyResult: |
57 | 57 | other: str | None = None |
58 | 58 |
|
59 | 59 |
|
| 60 | +@dataclass |
| 61 | +class NestedChild: |
| 62 | + """Nested dataclass for testing recursive None stripping.""" |
| 63 | + |
| 64 | + amount: str | None = None |
| 65 | + label: str | None = None |
| 66 | + |
| 67 | + |
| 68 | +@dataclass |
| 69 | +class DummyResultWithNested: |
| 70 | + """Dataclass with nested fields for testing recursive parse_result.""" |
| 71 | + |
| 72 | + name: str | None = None |
| 73 | + child: NestedChild | None = None |
| 74 | + children: list[NestedChild] | None = None |
| 75 | + nullable_field: str | None = field(metadata={"nullable": True}, default=None) |
| 76 | + |
| 77 | + |
60 | 78 | class TestHandlerRegistration: |
61 | 79 | def test_handler_registration_via_decorator(self): |
62 | 80 | """Test that @rpc_method decorator registers handler.""" |
@@ -265,3 +283,46 @@ def test_parse_result_dataclass_ignore_none(self): |
265 | 283 | parsed = parse_result(result) |
266 | 284 |
|
267 | 285 | assert parsed == {"value": 10}, "Expected filtered dataclass result" |
| 286 | + |
| 287 | + def test_parse_result_strips_none_in_nested_dicts(self): |
| 288 | + """None values in nested dataclass dicts should be stripped.""" |
| 289 | + result = DummyResultWithNested( |
| 290 | + name="test", |
| 291 | + child=NestedChild(amount="5", label=None), |
| 292 | + ) |
| 293 | + |
| 294 | + parsed = parse_result(result) |
| 295 | + |
| 296 | + assert parsed == {"name": "test", "child": {"amount": "5"}, "nullable_field": None} |
| 297 | + |
| 298 | + def test_parse_result_strips_none_in_nested_lists(self): |
| 299 | + """None values inside list items should be stripped.""" |
| 300 | + result = DummyResultWithNested( |
| 301 | + name="test", |
| 302 | + children=[ |
| 303 | + NestedChild(amount="1", label=None), |
| 304 | + NestedChild(amount="2", label="ok"), |
| 305 | + ], |
| 306 | + ) |
| 307 | + |
| 308 | + parsed = parse_result(result) |
| 309 | + |
| 310 | + assert parsed == { |
| 311 | + "name": "test", |
| 312 | + "children": [ |
| 313 | + {"amount": "1"}, |
| 314 | + {"amount": "2", "label": "ok"}, |
| 315 | + ], |
| 316 | + "nullable_field": None, |
| 317 | + } |
| 318 | + |
| 319 | + def test_parse_result_preserves_nullable_field_when_none(self): |
| 320 | + """Fields marked nullable should be preserved even when None.""" |
| 321 | + result = DummyResultWithNested( |
| 322 | + name="test", |
| 323 | + nullable_field=None, |
| 324 | + ) |
| 325 | + |
| 326 | + parsed = parse_result(result) |
| 327 | + |
| 328 | + assert parsed == {"name": "test", "nullable_field": None} |
0 commit comments