Merge pull request 'fix(export): תיקוני-תבנית DOCX — חתימות לסוף, א–ד ללא נתונים, "החלטה"=כותרת (#205)' (#355) from worktree-agent-a4e6a6d273c4c3379 into main
This commit was merged in pull request #355.
This commit is contained in:
@@ -14,7 +14,9 @@ from lxml import etree
|
||||
from legal_mcp.services.docx_exporter import (
|
||||
_BOOKMARK_ID_START,
|
||||
HEBREW_FONT,
|
||||
TEMPLATE_PATH,
|
||||
_add_styled_paragraph,
|
||||
_clear_body,
|
||||
_insert_bookmark_end,
|
||||
_insert_bookmark_start,
|
||||
_mark_paragraph_rtl,
|
||||
@@ -168,6 +170,83 @@ def test_block_dalet_does_not_use_title_style() -> None:
|
||||
assert any("החלטה" in t for t in texts)
|
||||
|
||||
|
||||
def test_block_dalet_is_heading_only_ignores_db_content() -> None:
|
||||
"""ת2 — block-ד is the 'החלטה' heading marker, NOT a data block.
|
||||
|
||||
Whatever content sits in decision_blocks for block-dalet must be ignored;
|
||||
the only non-empty text line produced is the literal heading 'החלטה'.
|
||||
"""
|
||||
doc = Document()
|
||||
_write_block_to_docx(
|
||||
doc, "block-dalet", title="כותרת",
|
||||
content="נתון ישן שצריך להיות מתועלם\nשורה שנייה",
|
||||
)
|
||||
text_lines = [p.text for p in doc.paragraphs if p.text.strip()]
|
||||
assert text_lines == ["החלטה"], (
|
||||
f"block-dalet must render ONLY the heading 'החלטה', got {text_lines}"
|
||||
)
|
||||
|
||||
|
||||
# ── _clear_body strips ALL scaffolding (ת1 + ת3 root cause) ────────
|
||||
# The template ships 3 sample tables (header / panel / signatures). Removing
|
||||
# only <w:p> left them behind: header/panel tables injected block-א–ד data
|
||||
# never extracted from the protocol (ת1), and the signatures table floated to
|
||||
# the top against the header (ת3 — חתימות צמודות לבלוק-ד במקום בסוף). The
|
||||
# decision is rebuilt purely from decision_blocks (INV-EX1), so the template's
|
||||
# sample tables are stale scaffolding and must be cleared.
|
||||
|
||||
|
||||
def test_clear_body_removes_tables_and_leaves_only_sectpr() -> None:
|
||||
doc = Document(str(TEMPLATE_PATH))
|
||||
body = doc.element.body
|
||||
# Sanity: the template really ships sample tables (else this test is moot).
|
||||
assert len(body.findall(qn("w:tbl"))) > 0, "template expected to ship sample tables"
|
||||
|
||||
_clear_body(doc)
|
||||
|
||||
remaining = [c.tag.split("}")[-1] for c in list(body)]
|
||||
assert remaining == ["sectPr"], (
|
||||
f"_clear_body must leave only sectPr, got {remaining}"
|
||||
)
|
||||
assert len(body.findall(qn("w:tbl"))) == 0, "no template tables may survive"
|
||||
assert len(body.findall(qn("w:p"))) == 0, "no template paragraphs may survive"
|
||||
|
||||
|
||||
def test_signatures_block_renders_after_body_not_at_top() -> None:
|
||||
"""ת3 — block-yod-bet (חתימות) renders LAST, after a cleared body.
|
||||
|
||||
Regression for the bug where the leftover template signatures table sat at
|
||||
the top against the header table. After the _clear_body fix, signatures
|
||||
come only from block-yod-bet, which the export loop emits last in block
|
||||
order.
|
||||
"""
|
||||
doc = Document(str(TEMPLATE_PATH))
|
||||
_clear_body(doc)
|
||||
|
||||
# Emit a header block, a body block, then signatures last (canonical order).
|
||||
_write_block_to_docx(doc, "block-alef", title="", content="מדינת ישראל")
|
||||
_write_block_to_docx(doc, "block-vav", title="", content="רקע עובדתי\n1. המקרקעין.")
|
||||
_write_block_to_docx(
|
||||
doc, "block-yod-bet", title="",
|
||||
content='ניתנה פה אחד היום.\nדפנה תמיר, עו"ד',
|
||||
)
|
||||
|
||||
text_lines = [p.text for p in doc.paragraphs if p.text.strip()]
|
||||
assert text_lines[0] == "מדינת ישראל", text_lines
|
||||
# The signatures block (block-yod-bet) emits each line as its own paragraph,
|
||||
# so its content must occupy the document's tail — after the body block.
|
||||
body_idx = text_lines.index("רקע עובדתי")
|
||||
sig_idx = next(i for i, t in enumerate(text_lines) if "ניתנה פה אחד" in t)
|
||||
assert sig_idx > body_idx, (
|
||||
f"signatures must come AFTER the body, got tail={text_lines[-3:]}"
|
||||
)
|
||||
assert any("דפנה תמיר" in t for t in text_lines[sig_idx:]), text_lines[sig_idx:]
|
||||
# No template signatures table ("מזכירת ועדת ערר") leaked anywhere.
|
||||
assert all(
|
||||
"מזכירת ועדת ערר" not in (p.text or "") for p in doc.paragraphs
|
||||
), "template signatures-table text leaked into the body"
|
||||
|
||||
|
||||
# ── Heading overrides, numbered-list, dash strip ──────────────────
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user