Skip to content

Commit df31946

Browse files
iamogbznoahnu
andauthored
feat: provide __repr__ for SnapshotAssertion (#600)
Co-authored-by: Noah <[email protected]>
1 parent 9375da9 commit df31946

File tree

4 files changed

+63
-9
lines changed

4 files changed

+63
-9
lines changed

src/syrupy/assertion.py

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import traceback
2+
from collections import namedtuple
23
from dataclasses import (
34
dataclass,
45
field,
@@ -15,6 +16,7 @@
1516
)
1617

1718
from .exceptions import SnapshotDoesNotExist
19+
from .extensions.amber.serializer import Repr
1820

1921
if TYPE_CHECKING:
2022
from .extensions.base import AbstractSyrupyExtension
@@ -54,8 +56,6 @@ class SnapshotAssertion:
5456
test_location: "PyTestLocation"
5557
update_snapshots: bool
5658

57-
name: str = "snapshot"
58-
5959
_exclude: Optional["PropertyFilter"] = field(
6060
init=False,
6161
default=None,
@@ -76,6 +76,9 @@ class SnapshotAssertion:
7676
init=False,
7777
default_factory=dict,
7878
)
79+
_execution_name_index: Dict["SnapshotIndex", int] = field(
80+
init=False, default_factory=dict
81+
)
7982
_matcher: Optional["PropertyMatcher"] = field(
8083
init=False,
8184
default=None,
@@ -104,7 +107,7 @@ def num_executions(self) -> int:
104107
return int(self._executions)
105108

106109
@property
107-
def executions(self) -> Dict[int, AssertionResult]:
110+
def executions(self) -> Dict[int, "AssertionResult"]:
108111
return self._execution_results
109112

110113
@property
@@ -113,6 +116,44 @@ def index(self) -> "SnapshotIndex":
113116
return self._custom_index
114117
return self.num_executions
115118

119+
@property
120+
def name(self) -> str:
121+
return self._custom_index or "snapshot"
122+
123+
@property
124+
def __repr(self) -> "SerializableData":
125+
SnapshotAssertionRepr = namedtuple( # type: ignore
126+
"SnapshotAssertion", ["name", "num_executions"]
127+
)
128+
assertion_result = self.executions.get(
129+
(self._custom_index and self._execution_name_index.get(self._custom_index))
130+
or self.num_executions - 1
131+
)
132+
return (
133+
Repr(str(assertion_result.final_data))
134+
if assertion_result
135+
else SnapshotAssertionRepr(
136+
name=self.name,
137+
num_executions=self.num_executions,
138+
)
139+
)
140+
141+
@property
142+
def __matcher(self) -> "PropertyMatcher":
143+
"""
144+
Get matcher that replaces `SnapshotAssertion` with one that can be serialized
145+
"""
146+
147+
def _matcher(**kwargs: Any) -> Optional["SerializableData"]:
148+
maybe_assertion = kwargs.get("data")
149+
if isinstance(maybe_assertion, SnapshotAssertion):
150+
return maybe_assertion.__repr
151+
if self._matcher:
152+
return self._matcher(**kwargs)
153+
return maybe_assertion
154+
155+
return _matcher
156+
116157
def use_extension(
117158
self, extension_class: Optional[Type["AbstractSyrupyExtension"]] = None
118159
) -> "SnapshotAssertion":
@@ -132,7 +173,7 @@ def assert_match(self, data: "SerializableData") -> None:
132173

133174
def _serialize(self, data: "SerializableData") -> "SerializedData":
134175
return self.extension.serialize(
135-
data, exclude=self._exclude, matcher=self._matcher
176+
data, exclude=self._exclude, matcher=self.__matcher
136177
)
137178

138179
def get_assert_diff(self) -> List[str]:
@@ -190,8 +231,8 @@ def __call__(
190231
self.__with_prop("_snapshot_diff", diff)
191232
return self
192233

193-
def __dir__(self) -> List[str]:
194-
return ["name", "num_executions"]
234+
def __repr__(self) -> str:
235+
return str(self._serialize(self.__repr))
195236

196237
def __eq__(self, other: "SerializableData") -> bool:
197238
return self._assert(other)
@@ -233,6 +274,7 @@ def _assert(self, data: "SerializableData") -> bool:
233274
finally:
234275
snapshot_created = snapshot_data is None and assertion_success
235276
snapshot_updated = matches is False and assertion_success
277+
self._execution_name_index[self.index] = self._executions
236278
self._execution_results[self._executions] = AssertionResult(
237279
snapshot_location=snapshot_location,
238280
snapshot_name=snapshot_name,

tests/syrupy/extensions/amber/__snapshots__/test_amber_serializer.ambr

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,9 +313,15 @@
313313
# name: test_parameter_with_dot[value.with.dot]
314314
'value.with.dot'
315315
# ---
316-
# name: test_reflection
316+
# name: test_reflection.1
317317
SnapshotAssertion(
318-
name='snapshot',
318+
name='reflectionA',
319+
num_executions=0,
320+
)
321+
# ---
322+
# name: test_reflection[reflectionA]
323+
SnapshotAssertion(
324+
name='reflectionA',
319325
num_executions=0,
320326
)
321327
# ---

tests/syrupy/extensions/amber/test_amber_serializer.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ def test_non_snapshots(snapshot):
1111

1212

1313
def test_reflection(snapshot):
14+
"""assert [expected|snapshot] == [actual|received]"""
15+
assert snapshot(name="reflectionA") == snapshot
1416
assert snapshot == snapshot
17+
assert snapshot == snapshot(name="reflectionA")
1518

1619

1720
def test_empty_snapshot(snapshot):
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
"<class 'SnapshotAssertion'>"
1+
{
2+
"name": "snapshot",
3+
"num_executions": 0
4+
}

0 commit comments

Comments
 (0)