"""Minimale Tests für die Kernlogik: Token-Suche, Geometrie, Fehlerfälle."""
import re
import fitz
import pytest
from core import (
PT_TO_MM,
PlacementError,
build_a4_svg,
find_token_occurrences,
parse_svg,
place_all,
signatur_geometrie,
)
from models import SignatureJob
# ── Test-Hilfen ─────────────────────────────────────────────────────────
SVG_OK = (
b''
)
SVG_NO_VIEWBOX = (
b''
)
def make_pdf(tokens_at):
"""Erzeugt ein A4-PDF (1 Seite) mit den Token an gegebenen Punkt-Positionen."""
doc = fitz.open()
page = doc.new_page(width=595.0, height=842.0) # A4 in pt
for token, (x, y) in tokens_at:
page.insert_text((x, y), token, fontsize=11)
pdf_bytes = doc.tobytes()
doc.close()
return pdf_bytes
def _translate_from_svg(a4_svg):
"""Liest tx, ty aus dem ersten translate(...) des A4-SVG."""
m = re.search(r"translate\(([-\d.]+),([-\d.]+)\)", a4_svg)
assert m, "kein translate gefunden"
return float(m.group(1)), float(m.group(2))
def _scale_from_svg(a4_svg):
m = re.search(r"scale\(([-\d.]+)\)", a4_svg)
assert m, "kein scale gefunden"
return float(m.group(1))
# ── viewBox / SVG ───────────────────────────────────────────────────────
def test_parse_svg_liest_viewbox():
vb = parse_svg(SVG_OK)
assert (vb.minx, vb.miny, vb.vw, vb.vh) == (0.0, 0.0, 100.0, 40.0)
assert "'
b''
)
vb = parse_svg(svg)
rect = fitz.Rect(72.0, 72.0, 120.0, 84.0)
job = SignatureJob(token="§§SIG1§§", svg_id="s.svg", position="unter")
a4 = build_a4_svg(vb, rect, job)
tx, ty = _translate_from_svg(a4)
skala = _scale_from_svg(a4)
# tx = x_sig - minx*skala
assert tx == pytest.approx(72.0 * PT_TO_MM - 10.0 * skala, abs=1e-3)
def test_versatz_verschiebt_links_rechts_oben_unten():
vb = parse_svg(SVG_OK)
rect = fitz.Rect(72.0, 72.0, 120.0, 84.0)
base = SignatureJob(token="§§S§§", svg_id="s.svg", position="genau")
moved = SignatureJob(token="§§S§§", svg_id="s.svg", position="genau",
versatz_x_mm=5.0, versatz_y_mm=-3.0)
a4_base = build_a4_svg(vb, rect, base)
a4_moved = build_a4_svg(vb, rect, moved)
bx, by = _translate_from_svg(a4_base)
mx, my = _translate_from_svg(a4_moved)
assert mx == pytest.approx(bx + 5.0, abs=1e-3) # +x → nach rechts
assert my == pytest.approx(by - 3.0, abs=1e-3) # −y → nach oben
def test_immer_single_stroke_fill_none_und_stroke():
"""Signaturen werden immer als Single-Stroke gezeichnet (fill:none + stroke)."""
vb = parse_svg(SVG_OK)
rect = fitz.Rect(72.0, 72.0, 120.0, 84.0)
job = SignatureJob(token="§§S§§", svg_id="s.svg", position="genau",
breite_mm=50.0, linienstaerke_mm=0.5)
a4 = build_a4_svg(vb, rect, job)
assert 'fill="none"' in a4
assert "stroke=" in a4 and "stroke-width=" in a4
# stroke-width in viewBox-Einheiten: 0.5mm / skala (skala = 50/100 = 0.5) = 1.0
import re
sw = float(re.search(r'stroke-width="([\d.]+)"', a4).group(1))
assert sw == pytest.approx(1.0, abs=1e-3)
def test_root_transform_wird_nicht_uebernommen():
"""Ein transform auf der äußersten