"""בדיקות ל-bookmark helpers ב-docx_exporter. הבדיקות מתרכזות ב-helper functions בלבד (לא בכל ה-export flow שדורש DB). """ from __future__ import annotations import zipfile from pathlib import Path from docx import Document from lxml import etree from legal_mcp.services.docx_exporter import ( _BOOKMARK_ID_START, _insert_bookmark_end, _insert_bookmark_start, _wrap_block_with_bookmarks, ) from legal_mcp.services.docx_reviser import NSMAP, _w, list_bookmarks def test_insert_bookmark_helpers_create_valid_xml(tmp_path: Path) -> None: doc = Document() p = doc.add_paragraph("תוכן בלוק י") _insert_bookmark_start(p, "block-yod", 10001) _insert_bookmark_end(p, 10001) out = tmp_path / "out.docx" doc.save(str(out)) # Verify via list_bookmarks (uses the same XML) assert list_bookmarks(out) == ["block-yod"] def test_wrap_block_with_bookmarks_wraps_multiple_paragraphs(tmp_path: Path) -> None: doc = Document() doc.add_paragraph("ראשון — לפני") # noise before bm_counter = [_BOOKMARK_ID_START] def writer() -> None: doc.add_paragraph("בלוק — פסקה 1") doc.add_paragraph("בלוק — פסקה 2") doc.add_paragraph("בלוק — פסקה 3") _wrap_block_with_bookmarks(doc, "block-yod", writer, bm_counter) doc.add_paragraph("אחרי — אחרון") # noise after out = tmp_path / "out.docx" doc.save(str(out)) # The bookmark should wrap exactly the 3 middle paragraphs with zipfile.ZipFile(out, "r") as zf: tree = etree.fromstring(zf.read("word/document.xml")) paragraphs = tree.findall(".//w:p", NSMAP) # Find para index of bookmarkStart and bookmarkEnd start_idx = end_idx = None for i, p in enumerate(paragraphs): if p.find(".//w:bookmarkStart", NSMAP) is not None: start_idx = i if p.find(".//w:bookmarkEnd", NSMAP) is not None: end_idx = i assert start_idx is not None assert end_idx is not None # The paragraph containing start must be the first new one ("פסקה 1") start_text = "".join(paragraphs[start_idx].itertext()) end_text = "".join(paragraphs[end_idx].itertext()) assert "פסקה 1" in start_text assert "פסקה 3" in end_text def test_wrap_block_skipped_when_writer_adds_nothing(tmp_path: Path) -> None: doc = Document() bm_counter = [_BOOKMARK_ID_START] _wrap_block_with_bookmarks(doc, "block-empty", lambda: None, bm_counter) out = tmp_path / "out.docx" doc.save(str(out)) assert list_bookmarks(out) == [] def test_multiple_blocks_get_unique_bookmark_ids(tmp_path: Path) -> None: doc = Document() bm_counter = [_BOOKMARK_ID_START] for name in ("block-alef", "block-bet", "block-gimel"): _wrap_block_with_bookmarks( doc, name, lambda n=name: doc.add_paragraph(f"תוכן של {n}"), bm_counter, ) out = tmp_path / "out.docx" doc.save(str(out)) with zipfile.ZipFile(out, "r") as zf: tree = etree.fromstring(zf.read("word/document.xml")) ids = [el.get(_w("id")) for el in tree.iterfind(".//w:bookmarkStart", NSMAP)] assert len(ids) == 3 assert len(set(ids)) == 3 names = list_bookmarks(out) assert set(names) == {"block-alef", "block-bet", "block-gimel"}