handbook_engine / tests /test_renderers.py
internationalscholarsprogram's picture
fix: ISP handbook styling overhaul - margins, typography, emphasis, benefits, CSS cascade
ec94fc1
"""Tests for utility functions & renderers."""
from __future__ import annotations
import pytest
from app.services.utils import (
format_money_figures,
h,
handbook_anchor,
hb_slug,
is_truthy,
sort_sections_stable,
)
from app.services.renderers import (
render_global_blocks,
render_toc,
sort_toc,
)
# ── h() ──
def test_h_escapes_html():
assert h('<script>alert("xss")</script>') == '&lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;'
def test_h_preserves_normal_text():
assert h("Hello World") == "Hello World"
# ── hb_slug() ──
def test_hb_slug_basic():
assert hb_slug("Hello World") == "hello_world"
def test_hb_slug_special_chars():
assert hb_slug("Montana State University!") == "montana_state_university"
# ── handbook_anchor() ──
def test_handbook_anchor():
result = handbook_anchor("uni", "Drew University", 5)
assert result == "uni-drew-university-5"
def test_handbook_anchor_empty_text():
result = handbook_anchor("g", "", 3)
assert result == "g-g-3-3"
# ── is_truthy() ──
def test_is_truthy_true_values():
assert is_truthy(True) is True
assert is_truthy(1) is True
assert is_truthy("yes") is True
assert is_truthy("1") is True
def test_is_truthy_false_values():
assert is_truthy(False) is False
assert is_truthy(0) is False
assert is_truthy("0") is False
assert is_truthy("false") is False
assert is_truthy("") is False
# ── format_money_figures() ──
def test_format_money_removes_usd_prefix():
result = format_money_figures("USD 5000")
assert "USD" not in result
assert "$" in result
def test_format_money_adds_dollar_sign():
result = format_money_figures("The cost is 15000 per year")
assert "$15,000" in result
def test_format_money_preserves_percentages():
result = format_money_figures("50% discount on 15000")
assert "50%" in result
# ── sort_sections_stable() ──
def test_sort_sections_by_sort_order():
sections = [
{"section_key": "b", "sort_order": 2, "id": 2},
{"section_key": "a", "sort_order": 1, "id": 1},
{"section_key": "c", "sort_order": 3, "id": 3},
]
result = sort_sections_stable(sections)
assert [s["section_key"] for s in result] == ["a", "b", "c"]
def test_sort_sections_null_sort_order_last():
sections = [
{"section_key": "a", "sort_order": None, "id": 1},
{"section_key": "b", "sort_order": 1, "id": 2},
]
result = sort_sections_stable(sections)
assert result[0]["section_key"] == "b"
assert result[1]["section_key"] == "a"
# ── sort_toc() ──
def test_sort_toc_stable():
items = [
{"title": "B", "sort": 2},
{"title": "A", "sort": 1},
{"title": "C"},
]
result = sort_toc(items)
assert result[0]["title"] == "A"
assert result[1]["title"] == "B"
assert result[2]["title"] == "C"
# ── render_toc() ──
def test_render_toc_produces_html():
items = [
{"title": "Overview", "target": "#overview", "level": 0, "bold": True},
{"title": "Drew University", "target": "#uni-drew", "level": 1, "bold": False},
]
html = render_toc(items)
assert "HANDBOOK_TOC_V2" in html
assert "OVERVIEW" in html # level 0 is uppercased
assert "Drew University" in html
assert '<table class="toc-table"' in html
# ── render_global_blocks() ──
def test_render_global_blocks_paragraph():
json_data = {"text": "This is a paragraph."}
html = render_global_blocks("test", "Test Section", json_data)
assert "Test Section" in html
assert "This is a paragraph." in html
def test_render_global_blocks_steps():
json_data = {
"steps": [
{"title": "Apply", "body": "Submit your application."},
{"title": "Enrol", "body": "Complete enrolment."},
]
}
html = render_global_blocks("enrolment_steps", "Steps", json_data)
assert "Step 1: Apply" in html
assert "Step 2: Enrol" in html
def test_render_global_blocks_bullets():
json_data = {"bullets": ["Item A", "Item B", "Item C"]}
html = render_global_blocks("test", "Test", json_data)
assert "<li>" in html
assert "Item A" in html
assert "Item C" in html
def test_render_global_blocks_table():
json_data = {
"columns": ["Name", "Value"],
"rows": [["Alpha", "100"], ["Beta", "200"]],
}
html = render_global_blocks("test", "Test", json_data)
assert '<table class="tbl">' in html
assert "Alpha" in html
assert "200" in html
def test_render_global_blocks_doc_v1():
json_data = {
"layout": "doc_v1",
"blocks": [
{"type": "paragraph", "text": "Hello paragraph."},
{"type": "subheading", "text": "A Subheading"},
{"type": "bullets", "items": ["Bullet 1", "Bullet 2"]},
{"type": "note", "text": "Important note."},
],
}
html = render_global_blocks("overview", "Overview", json_data)
assert "Hello paragraph." in html
assert "A Subheading" in html
assert "Bullet 1" in html
assert "Important note." in html
def test_render_global_blocks_summary_of_universities():
universities = [
{"university_name": "Drew University"},
{"university_name": "Montana State University"},
]
json_data = {"intro": "We partner with great universities."}
html = render_global_blocks(
"summary_of_universities",
"Summary of Universities",
json_data,
universities=universities,
)
assert "Summary of Universities" in html
assert "Drew University" in html
assert "Montana State University" in html
assert "<ol" in html
def test_render_global_blocks_empty_returns_warning(caplog):
with caplog.at_level("WARNING"):
html = render_global_blocks("empty_key", "Empty", {})
assert html.strip() != "" or "Empty section render" in caplog.text