Source code for dsw_document_template_tool._regression.artifacts

"""Write and compare deterministic regression artifacts."""

from __future__ import annotations

from pathlib import Path
from typing import Any

from ..html_diff import build_unified_diff, normalize_html
from ..models import RegressionReport, RenderArtifact, ResolvedSubject


[docs] def write_render_artifact( *, fixture_output_dir: Path, subject: ResolvedSubject, raw_html: str, ignore_patterns: list[str], ) -> RenderArtifact: """Persist raw and normalized HTML for one regression subject.""" raw_path = fixture_output_dir / f"{subject.label}.raw.html" normalized_path = fixture_output_dir / f"{subject.label}.normalized.html" raw_path.write_text(raw_html, encoding="utf-8") normalized_path.write_text( normalize_html(raw_html, ignore_patterns=ignore_patterns) + "\n", encoding="utf-8", ) return RenderArtifact( raw_path=raw_path, normalized_path=normalized_path, subject_label=subject.label, template_reference=subject.display_id, )
[docs] def compare_render_artifacts( *, fixture_output_dir: Path, baseline: RenderArtifact, candidate: RenderArtifact, ) -> tuple[bool, Path | None]: """Compare normalized artifacts and write a unified diff on mismatch.""" baseline_html = baseline.normalized_path.read_text(encoding="utf-8") candidate_html = candidate.normalized_path.read_text(encoding="utf-8") if baseline_html == candidate_html: return True, None diff_path = fixture_output_dir / "diff.diff" diff_path.write_text( build_unified_diff( baseline_html, candidate_html, baseline_label=baseline.template_reference, candidate_label=candidate.template_reference, ) + "\n", encoding="utf-8", ) return False, diff_path
[docs] def serialize_regression_report(report: RegressionReport) -> dict[str, Any]: """Convert a regression report into its stable JSON representation.""" return { "assertion": report.assertion, "mode": report.mode, "output_dir": str(report.output_dir), "passed": report.passed, "fixtures": [ { "fixture_name": result.fixture_name, "project_uuid": result.project_uuid, "passed": result.passed, "baseline": ( None if result.baseline is None else _serialize_render_artifact(result.baseline) ), "candidate": _serialize_render_artifact(result.candidate), "diff_path": None if result.diff_path is None else str(result.diff_path), } for result in report.fixture_results ], }
def _serialize_render_artifact(artifact: RenderArtifact) -> dict[str, str]: return { "subject_label": artifact.subject_label, "template_reference": artifact.template_reference, "raw_path": str(artifact.raw_path), "normalized_path": str(artifact.normalized_path), }