diff --git a/pytest_textual_snapshot.py b/pytest_textual_snapshot.py index f973ae1..90884e0 100644 --- a/pytest_textual_snapshot.py +++ b/pytest_textual_snapshot.py @@ -10,6 +10,7 @@ from operator import attrgetter from os import PathLike from pathlib import Path, PurePath +from random import random from tempfile import mkdtemp from typing import Any, Awaitable, Union, Optional, Callable, Iterable, TYPE_CHECKING @@ -33,6 +34,18 @@ class SVGImageExtension(SingleFileSnapshotExtension): _file_extension = "svg" _write_mode = WriteMode.TEXT + def _read_snapshot_data_from_location(self, *args, **kwargs) -> Optional["SerializableData"]: + """Normalize SVG data right after they are loaded from persistent storage.""" + data = super()._read_snapshot_data_from_location(*args, **kwargs) + if data is not None: + data = normalize_svg(data) + return data + + def serialize(self, *args, **kwargs) -> "SerializedData": + """Normalize SVG data before they get compared against a snapshot and + before they get persisted to storage.""" + return normalize_svg(super().serialize(*args, **kwargs)) + class TemporaryDirectory: """A temporary that survives forking. @@ -71,10 +84,14 @@ class PseudoApp: console: PseudoConsole -def rename_styles(svg: str, suffix: str) -> str: - """Rename style names to prevent clashes when combined in HTML report.""" - return re.sub(r"terminal-(\d+)-r(\d+)", rf"terminal-\1-r\2-{suffix}", svg) +def individualize_svg(svg: str, unique_id: Optional[str] = None) -> str: + """Inject a random id, à la rich.Console.export_svg().""" + unique_id = str(int(random() * 1e10)) if unique_id is None else unique_id + return re.sub(r"\bterminal(?:-\d+)?-([\w-]+)", rf"terminal-{unique_id}-\1", svg) +def normalize_svg(svg: str) -> str: + """Strip the unique id generated by rich.Console.export_svg().""" + return re.sub(r"\bterminal-\d+-([\w-]+)", r"terminal-\1", svg) def pytest_addoption(parser): parser.addoption( @@ -301,8 +318,8 @@ def retrieve_svg_diffs( n += 1 diffs.append( SvgSnapshotDiff( - snapshot=rename_styles(str(expect_svg_text), f"exp{n}"), - actual=rename_styles(svg_text, f"act{n}"), + snapshot=individualize_svg(str(expect_svg_text)), + actual=individualize_svg(svg_text), test_name=name, path=full_path, line_number=line_index + 1,