regression test: Javascript buttons maskieren beim visuellen vergleich

Neue konstante Maskenrechtecke in PDF-Punktkoordinaten für die beiden Buttons unten rechts.
Neue Hilfsfunktion _mask_ignored_regions(...), die diese Bereiche auf Schwarz setzt.
Anwendung der Maske auf Seite 1 vor der Similarity-Berechnung.
Anwendung derselben maskierten Bilder auch für gespeicherte Diff-Bilder.
This commit is contained in:
Rob committed 2026-04-17 08:14:12 +02:00
1 parent bf89d116f2
commit 34fe877bb2
1 file changed
+35 -2
+35 -2
View File
@@ -50,6 +50,13 @@ FIXTURES_DIR = Path(__file__).parent / "fixtures"
SIMILARITY_THRESHOLD = 1.00 # minimum fraction of matching pixels per page SIMILARITY_THRESHOLD = 1.00 # minimum fraction of matching pixels per page
PIXEL_TOLERANCE = 5 # max per-channel delta still counted as "same" PIXEL_TOLERANCE = 5 # max per-channel delta still counted as "same"
RENDER_DPI = 150 # rendering resolution for PDF → image RENDER_DPI = 150 # rendering resolution for PDF → image
PAGE_WIDTH_PTS = 595.2760009765625
PAGE_HEIGHT_PTS = 841.8900146484375
# Ignore rendering differences for two JS-driven button widgets (bottom-right).
IGNORE_RECTS_PTS = [
(457.8450012207031, 745.5402221679688, 563.4010009765625, 765.5402221679688),
(457.8450012207031, 767.4678955078125, 563.4010009765625, 786.35693359375),
]
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@@ -136,6 +143,24 @@ def _resize_to_match(img: np.ndarray, target_shape: tuple) -> np.ndarray:
return np.array(pil) return np.array(pil)
def _mask_ignored_regions(img: np.ndarray) -> np.ndarray:
"""Return a copy of *img* where ignored regions are blacked out."""
masked = img.copy()
h, w = masked.shape[:2]
scale_x = w / PAGE_WIDTH_PTS
scale_y = h / PAGE_HEIGHT_PTS
for x0_pt, y0_pt, x1_pt, y1_pt in IGNORE_RECTS_PTS:
x0 = max(0, min(w, int(round(x0_pt * scale_x))))
y0 = max(0, min(h, int(round(y0_pt * scale_y))))
x1 = max(0, min(w, int(round(x1_pt * scale_x))))
y1 = max(0, min(h, int(round(y1_pt * scale_y))))
if x1 > x0 and y1 > y0:
masked[y0:y1, x0:x1] = 0
return masked
def _compute_similarity(ref: np.ndarray, gen: np.ndarray) -> float: def _compute_similarity(ref: np.ndarray, gen: np.ndarray) -> float:
"""Return the fraction of pixels where all RGB channels differ by at most PIXEL_TOLERANCE.""" """Return the fraction of pixels where all RGB channels differ by at most PIXEL_TOLERANCE."""
if ref.shape != gen.shape: if ref.shape != gen.shape:
@@ -249,13 +274,21 @@ def test_pdf_matches_reference(
failures.append(f" {page_label}: Seite fehlt in generierter PDF.") failures.append(f" {page_label}: Seite fehlt in generierter PDF.")
continue continue
similarity = _compute_similarity(ref_images[page_idx], gen_images[page_idx]) ref_img = ref_images[page_idx]
gen_img = gen_images[page_idx]
# Ignore the two bottom-right JavaScript button regions on page 1.
if page_idx == 0:
ref_img = _mask_ignored_regions(ref_img)
gen_img = _mask_ignored_regions(gen_img)
similarity = _compute_similarity(ref_img, gen_img)
if similarity < SIMILARITY_THRESHOLD: if similarity < SIMILARITY_THRESHOLD:
page_tag = f"seite_{page_idx + 1:02d}" page_tag = f"seite_{page_idx + 1:02d}"
img_dir = diff_dir / clean_stem / page_tag img_dir = diff_dir / clean_stem / page_tag
_save_diff_images( _save_diff_images(
ref_images[page_idx], gen_images[page_idx], img_dir, page_tag ref_img, gen_img, img_dir, page_tag
) )
rel = img_dir.relative_to(project_root) rel = img_dir.relative_to(project_root)
failures.append( failures.append(