Skip to content

Commit b0cd665

Browse files
authored
API: add snapshot.match_object() (#4)
2 parents 1a22848 + 059a981 commit b0cd665

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

localstack_snapshot/snapshots/prototype.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,23 @@ def _load_state(self) -> dict:
164164
def _update(self, key: str, obj_state: dict) -> None:
165165
self.observed_state[key] = obj_state
166166

167+
def match_object(self, key: str, obj: object) -> None:
168+
def _convert_object_to_dict(obj_):
169+
if isinstance(obj_, dict):
170+
for key in list(obj_.keys()):
171+
if key.startswith("_"):
172+
del obj_[key]
173+
else:
174+
obj_[key] = _convert_object_to_dict(obj_[key])
175+
elif isinstance(obj_, list):
176+
for idx, val in enumerate(obj_):
177+
obj_[idx] = _convert_object_to_dict(val)
178+
elif hasattr(obj_, "__dict__"):
179+
return _convert_object_to_dict(obj_.__dict__)
180+
return obj_
181+
182+
return self.match(key, _convert_object_to_dict(obj))
183+
167184
def match(self, key: str, obj: dict) -> None:
168185
if key in self.called_keys:
169186
raise Exception(

tests/test_snapshots.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,48 @@ def test_context_replacement(self):
3737
sm.match("key_a", {"aaa": "something", "bbb": "something hello"})
3838
sm._assert_all()
3939

40+
def test_match_object_nochange(self):
41+
class CustomObject:
42+
def __init__(self, name, nested=False):
43+
self.name = name
44+
if nested:
45+
self.nested = CustomObject(f"nested{name}")
46+
self.listed = [CustomObject(f"listed{name}"), "otherobj"]
47+
48+
sm = SnapshotSession(scope_key="A", verify=True, base_file_path="", update=False)
49+
sm.recorded_state = {
50+
"key_a": {
51+
"name": "myname",
52+
"nested": {"name": "nestedmyname"},
53+
"listed": [{"name": "listedmyname"}, "otherobj"],
54+
}
55+
}
56+
sm.match_object("key_a", CustomObject(name="myname", nested=True))
57+
sm._assert_all()
58+
59+
def test_match_object_ignore_private_values(self):
60+
class CustomObject:
61+
def __init__(self, name):
62+
self.name = name
63+
self._internal = "n/a"
64+
65+
sm = SnapshotSession(scope_key="A", verify=True, base_file_path="", update=False)
66+
sm.recorded_state = {"key_a": {"name": "myname"}}
67+
sm.match_object("key_a", CustomObject(name="myname"))
68+
sm._assert_all()
69+
70+
def test_match_object_change(self):
71+
class CustomObject:
72+
def __init__(self, name):
73+
self.name = name
74+
75+
sm = SnapshotSession(scope_key="A", verify=True, base_file_path="", update=False)
76+
sm.recorded_state = {"key_a": {"name": "myname"}}
77+
sm.match_object("key_a", CustomObject(name="diffname"))
78+
with pytest.raises(Exception) as ctx:
79+
sm._assert_all()
80+
ctx.match("Parity snapshot failed")
81+
4082
# def test_context_replacement_no_change(self):
4183
# sm = SnapshotSession(scope_key="A", verify=True, base_file_path="", update=False)
4284
# sm.add_transformer(TransformerUtility.key_value("name"))

0 commit comments

Comments
 (0)