gwoe-antragspruefer/tests/test_pm_render.py

138 lines
4.3 KiB
Python
Raw Normal View History

"""Tests für app.pm_render — Python-Spiegelbild des JS-Mini-Markdown-Renderers."""
import pytest
try:
from app.pm_render import render_pm_body
_HAS_RENDER = True
except ImportError:
_HAS_RENDER = False
pytestmark = pytest.mark.skipif(not _HAS_RENDER, reason="app.pm_render nicht importierbar")
class TestEmptyAndNone:
def test_empty_returns_empty(self):
assert render_pm_body("") == ""
def test_none_returns_empty(self):
assert render_pm_body(None) == ""
class TestPlainParagraph:
def test_single_paragraph(self):
out = render_pm_body("Ein einzelner Satz.")
assert out == '<p style="margin:0 0 0.9em;">Ein einzelner Satz.</p>'
def test_two_paragraphs(self):
out = render_pm_body("Erster Satz.\n\nZweiter Satz.")
assert "Erster Satz" in out
assert "Zweiter Satz" in out
assert out.count("<p ") == 2
def test_single_newline_becomes_br(self):
out = render_pm_body("Zeile A\nZeile B")
assert "Zeile A<br>Zeile B" in out
class TestHtmlEscape:
def test_lt_gt_escaped(self):
out = render_pm_body("Vergleich a < b > c.")
assert "&lt;" in out and "&gt;" in out
assert "<b>" not in out # nichts wird zu echten Tags
def test_amp_escaped(self):
out = render_pm_body("Tom & Jerry")
assert "&amp;" in out
class TestBold:
def test_double_star_to_strong(self):
out = render_pm_body("Wert: **30 %**")
assert "<strong>30 %</strong>" in out
def test_double_underscore_to_strong(self):
out = render_pm_body("Wert: __wichtig__")
assert "<strong>wichtig</strong>" in out
def test_no_bold_across_newline(self):
"""**...** mit Newline dazwischen wird nicht gemarkt."""
out = render_pm_body("**erste\nZeile**")
assert "<strong>" not in out
class TestItalic:
def test_single_star_to_em(self):
out = render_pm_body("Das ist *betont*.")
assert "<em>betont</em>" in out
def test_single_underscore_to_em(self):
out = render_pm_body("Das ist _wichtig_.")
assert "<em>wichtig</em>" in out
def test_underscore_in_word_not_em(self):
"""snake_case darf nicht als em gerendert werden."""
out = render_pm_body("Variable my_var hier.")
assert "<em>" not in out
def test_star_between_words_not_em(self):
"""Ein * zwischen Wort-Charaktern ist kein em-Marker."""
out = render_pm_body("Datei: foo*bar.txt")
assert "<em>" not in out
class TestBoldAndItalicCombined:
def test_bold_first_then_italic(self):
out = render_pm_body("**fett** und *kursiv*.")
assert "<strong>fett</strong>" in out
assert "<em>kursiv</em>" in out
class TestLists:
def test_simple_dash_list(self):
out = render_pm_body("- Item 1\n- Item 2")
assert "<ul" in out
assert "<li>Item 1</li>" in out
assert "<li>Item 2</li>" in out
def test_simple_star_list(self):
out = render_pm_body("* A\n* B")
assert "<ul" in out
assert "<li>A</li>" in out
assert "<li>B</li>" in out
def test_list_with_paragraph_around(self):
body = "Vor der Liste.\n\n- Item 1\n- Item 2\n\nNach der Liste."
out = render_pm_body(body)
assert "<p" in out
assert "<ul" in out
assert "<li>Item 1</li>" in out
def test_dash_in_word_not_list(self):
"""Ein Bindestrich mitten im Wort ist kein Bullet."""
out = render_pm_body("Halb-leer ist halb-voll.")
assert "<ul" not in out
class TestRealisticPmBody:
"""End-to-End-Sample wie qwen-max es typischerweise produziert."""
def test_sample_with_bold_and_paragraphs(self):
body = (
"Mehr junge Menschen entscheiden sich für die Pflege.\n\n"
"Auszubildende brechen heute zu rund **30 %** ab.\n\n"
"Wir fordern eine Mindest-Vergütung."
)
out = render_pm_body(body)
# Drei Paragraphen
assert out.count("<p ") == 3
# Bold-Markierung gerendert
assert "<strong>30 %</strong>" in out
# Keine rohen ** mehr
assert "**" not in out
def test_no_bold_when_unmatched(self):
body = "Ein *einfacher Stern."
out = render_pm_body(body)
# Unmatched * darf nicht als em gerendert werden
assert "<em>" not in out