"""Tests for WordRenderer — Markdown → .docx mapping (U2).""" from __future__ import annotations from pathlib import Path from docx import Document from agentkit.documents.renderers.word_renderer import WordRenderer def _render(markdown: str, tmp_path: Path) -> Path: """Render markdown to a temp .docx and return the path.""" out = tmp_path / "test.docx" WordRenderer().render(markdown, out) return out def _read_paragraphs(path: Path) -> list[str]: """Return all paragraph texts from a .docx.""" doc = Document(str(path)) return [p.text for p in doc.paragraphs] def test_heading_levels(tmp_path: Path) -> None: """# / ## / ### map to heading levels 1/2/3.""" md = "# Title\n## Subtitle\n### Section\n" path = _render(md, tmp_path) doc = Document(str(path)) headings = [(p.style.name, p.text) for p in doc.paragraphs if p.text] assert ("Heading 1", "Title") in headings assert ("Heading 2", "Subtitle") in headings assert ("Heading 3", "Section") in headings def test_paragraphs(tmp_path: Path) -> None: """Plain text lines become paragraphs.""" md = "First paragraph.\n\nSecond paragraph.\n" path = _render(md, tmp_path) texts = _read_paragraphs(path) assert "First paragraph." in texts assert "Second paragraph." in texts def test_bullet_list(tmp_path: Path) -> None: """Bullet items use List Bullet style.""" md = "- Apple\n- Banana\n- Cherry\n" path = _render(md, tmp_path) doc = Document(str(path)) bullets = [p for p in doc.paragraphs if p.style.name == "List Bullet"] assert len(bullets) == 3 assert bullets[0].text == "Apple" assert bullets[1].text == "Banana" assert bullets[2].text == "Cherry" def test_numbered_list(tmp_path: Path) -> None: """Numbered items use List Number style.""" md = "1. First\n2. Second\n3. Third\n" path = _render(md, tmp_path) doc = Document(str(path)) numbers = [p for p in doc.paragraphs if p.style.name == "List Number"] assert len(numbers) == 3 assert numbers[0].text == "First" assert numbers[1].text == "Second" def test_table(tmp_path: Path) -> None: """GFM table maps to a docx table with correct cells.""" md = "| Name | Age |\n| --- | --- |\n| Alice | 30 |\n| Bob | 25 |\n" path = _render(md, tmp_path) doc = Document(str(path)) assert len(doc.tables) == 1 table = doc.tables[0] # 3 rows (header + 2 data), 2 cols assert len(table.rows) == 3 assert len(table.columns) == 2 assert table.cell(0, 0).text == "Name" assert table.cell(0, 1).text == "Age" assert table.cell(1, 0).text == "Alice" assert table.cell(2, 1).text == "25" def test_bold_inline(tmp_path: Path) -> None: """**bold** produces a bold run.""" md = "This has **bold** text.\n" path = _render(md, tmp_path) doc = Document(str(path)) para = doc.paragraphs[0] bold_runs = [r for r in para.runs if r.bold] assert len(bold_runs) == 1 assert bold_runs[0].text == "bold" def test_italic_inline(tmp_path: Path) -> None: """*italic* produces an italic run.""" md = "This has *italic* text.\n" path = _render(md, tmp_path) doc = Document(str(path)) para = doc.paragraphs[0] italic_runs = [r for r in para.runs if r.italic] assert len(italic_runs) == 1 assert italic_runs[0].text == "italic" def test_empty_markdown(tmp_path: Path) -> None: """Empty Markdown produces a valid (empty) document.""" path = _render("", tmp_path) assert path.exists() doc = Document(str(path)) # No paragraphs with text assert all(not p.text for p in doc.paragraphs) def test_mixed_content(tmp_path: Path) -> None: """Heading + paragraph + list + table renders without error.""" md = """# Report This is the intro. - Point one - Point two | Col A | Col B | | ----- | ----- | | 1 | 2 | Final paragraph. """ path = _render(md, tmp_path) assert path.exists() doc = Document(str(path)) # Should have at least one heading, one table, two bullet items headings = [p for p in doc.paragraphs if p.style.name.startswith("Heading")] assert len(headings) >= 1 assert len(doc.tables) == 1 bullets = [p for p in doc.paragraphs if p.style.name == "List Bullet"] assert len(bullets) == 2 def test_chinese_text(tmp_path: Path) -> None: """Chinese characters render correctly in paragraphs and headings.""" md = "# 中文标题\n\n这是中文段落。\n" path = _render(md, tmp_path) texts = _read_paragraphs(path) assert "中文标题" in texts assert "这是中文段落。" in texts