Files
2026Technology-Competition/tests/test_word_template_parser.py
T

133 lines
4.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from genesis.data_models import ChapterMarker, ParsedTemplate
from genesis.parsers._word_common import heading_level
from genesis.parsers.word_template_parser import WordTemplateParser
from tests.docx_helpers import new_document, save_document
def test_heading_level_parses_numeric_suffix():
assert heading_level("Heading 1") == 1
assert heading_level("Heading 2") == 2
assert heading_level("Heading 3") == 3
def test_heading_level_fallback_on_invalid():
# 兜底分支(非数字 / 无后缀)→ 1,分支覆盖必须命中
assert heading_level("Heading X") == 1
assert heading_level("Heading") == 1
def test_parse_extracts_heading_levels(tmp_path):
doc = new_document()
doc.add_heading("1. はじめに", level=1)
doc.add_heading("2.1 画面遷移図", level=2)
doc.add_heading("2.1.1 詳細", level=3)
path = save_document(tmp_path, doc)
result = WordTemplateParser().parse(path)
assert isinstance(result, ParsedTemplate)
headings = [s for s in result.sections if s.type == "heading"]
assert [(s.name, s.level) for s in headings] == [
("1. はじめに", 1),
("2.1 画面遷移図", 2),
("2.1.1 詳細", 3),
]
def test_parse_extracts_bookmark(tmp_path):
from docx.oxml.ns import qn
doc = new_document()
para = doc.add_paragraph("アンカー")
bm_start = para._p.makeelement(qn("w:bookmarkStart"), {qn("w:id"): "0", qn("w:name"): "template_start"})
para._p.insert(0, bm_start)
# 无 name 的书签:覆盖 if name 假分支,应被跳过
bm_anon = para._p.makeelement(qn("w:bookmarkStart"), {qn("w:id"): "1"})
para._p.insert(1, bm_anon)
path = save_document(tmp_path, doc)
result = WordTemplateParser().parse(path)
bookmarks = [s for s in result.sections if s.type == "bookmark"]
assert [s.name for s in bookmarks] == ["template_start"]
def test_parse_extracts_placeholders(tmp_path):
doc = new_document()
doc.add_paragraph("{{doc_title}}")
doc.add_paragraph("{{section:introduction}}")
doc.add_paragraph("{{section:function_list}}")
path = save_document(tmp_path, doc)
result = WordTemplateParser().parse(path)
assert result.placeholders == {
"doc_title": "{{doc_title}}",
"section:introduction": "{{section:introduction}}",
"section:function_list": "{{section:function_list}}",
}
ph = [s for s in result.sections if s.type == "placeholder"]
assert [s.name for s in ph] == ["doc_title", "section:introduction", "section:function_list"]
def test_parse_invalid_placeholder_kept_as_text(tmp_path):
doc = new_document()
doc.add_paragraph("{{ invalid }}")
doc.add_paragraph("ただの {text}")
path = save_document(tmp_path, doc)
result = WordTemplateParser().parse(path)
assert result.placeholders == {}
assert [s for s in result.sections if s.type == "placeholder"] == []
def test_parse_empty_document(tmp_path):
doc = new_document()
path = save_document(tmp_path, doc)
result = WordTemplateParser().parse(path)
assert result.sections == []
assert result.placeholders == {}
assert "Normal" in result.styles["defined"]
def test_parse_styles_collected(tmp_path):
doc = new_document()
doc.add_heading("章", level=1)
doc.add_paragraph("本文")
path = save_document(tmp_path, doc)
result = WordTemplateParser().parse(path)
assert "Heading 1" in result.styles["used"]
assert "Normal" in result.styles["used"]
assert "Heading 1" in result.styles["defined"]
def test_parse_extracts_placeholder_case_insensitive(tmp_path):
# 宽容:键名大小写不敏感 → 归一为小写 section:id
doc = new_document()
doc.add_paragraph("{{Section:2}}")
path = save_document(tmp_path, doc)
result = WordTemplateParser().parse(path)
assert result.placeholders == {"section:2": "{{Section:2}}"}
ph = [s for s in result.sections if s.type == "placeholder"]
assert [s.name for s in ph] == ["section:2"]
def test_parse_extracts_placeholder_fullwidth_colon(tmp_path):
# 宽容:全角冒号(:)也视为分隔符 → 归一为半角 section:id
doc = new_document()
doc.add_paragraph("{{section2}}")
path = save_document(tmp_path, doc)
result = WordTemplateParser().parse(path)
assert result.placeholders == {"section:2": "{{section2}}"}
ph = [s for s in result.sections if s.type == "placeholder"]
assert [s.name for s in ph] == ["section:2"]