Files
md_to_gost/tests/test_word_fix.py
Igor20264 510f7e7adf
Python application / build (push) Waiting to run
v0.5.2
Что то сделал
2026-09-08 19:37:54 +03:00

141 lines
4.9 KiB
Python

"""Tests for Word COM table/listing continuation post-process (pure + optional COM)."""
from __future__ import annotations
import os
import sys
import tempfile
import pytest
from md2gost.profiles import LISTING_CONTINUATION_MODES, TABLE_CONTINUATION_MODES
from md2gost.word_fix import (
continuation_label,
find_page_break_row,
fix_continuations,
is_caption_orphaned,
is_orphan_header_break,
parse_caption_text,
split_vmerge_spans_at_break,
)
def test_word_mode_in_profiles():
assert "word" in TABLE_CONTINUATION_MODES
assert "word" in LISTING_CONTINUATION_MODES
@pytest.mark.parametrize(
"text, kind, number, cont",
[
("Таблица 2.1 — Название", "table", "2.1", False),
("Таблица 1", "table", "1", False),
("Продолжение Таблицы 2.1", "table", "2.1", True),
("Листинг 3 — Код", "listing", "3", False),
("Продолжение Листинга 3", "listing", "3", True),
("Таблицы 1.2", "table", "1.2", False),
],
)
def test_parse_caption_text(text, kind, number, cont):
info = parse_caption_text(text)
assert info is not None
assert info.kind == kind
assert info.number == number
assert info.is_continuation is cont
def test_parse_caption_rejects_noise():
assert parse_caption_text("") is None
assert parse_caption_text("Рисунок 1 — x") is None
assert parse_caption_text("просто текст") is None
def test_find_page_break_row():
assert find_page_break_row([]) is None
assert find_page_break_row([1]) is None
assert find_page_break_row([1, 1, 1]) is None
assert find_page_break_row([1, 1, 2, 2]) == 3
assert find_page_break_row([2, 2, 3]) == 3
assert find_page_break_row([1, 2]) == 2
# typical vMerge table pages after cell-based detection
assert find_page_break_row([14, 14, 14, 14, 14, 14, 15, 15]) == 7
def test_orphan_header_and_caption_guards():
"""Method guide: no title-only / title+column-headers alone at page end."""
# Split would leave only heading row on previous page
assert is_orphan_header_break(2, had_header=True) is True
assert is_orphan_header_break(2, had_header=False) is False
assert is_orphan_header_break(3, had_header=True) is False
assert is_orphan_header_break(None, had_header=True) is False
# Caption on earlier page than first table row
assert is_caption_orphaned(5, 6) is True
assert is_caption_orphaned(5, 5) is False
assert is_caption_orphaned(None, 6) is False
def test_split_vmerge_spans_at_break():
# (row, col, span, text) — merge rows 2..6 (span 5), break at row 7 → all in first
spans = [(2, 1, 5, "A"), (7, 1, 2, "B")]
first, cont = split_vmerge_spans_at_break(spans, 7)
assert first == [(2, 1, 5, "A")]
assert cont == [(1, 1, 2, "B")]
# merge crosses break: rows 5..8, break at 7
first, cont = split_vmerge_spans_at_break([(5, 1, 4, "X")], 7)
assert first == [(5, 1, 2, "X")]
assert cont == [(1, 1, 2, "X")]
def test_continuation_label():
assert continuation_label("table", "2.1") == "Продолжение Таблицы 2.1"
assert continuation_label("listing", "4") == "Продолжение Листинга 4"
def test_word_paged_modes_include_word():
from md2gost.renderable.table import _WORD_PAGED_MODES as t
from md2gost.renderable.listing import _WORD_PAGED_MODES as L
assert "word" in t
assert "word" in L
def test_fix_continuations_missing_file():
r = fix_continuations(os.path.join(tempfile.gettempdir(), "md2gost-no-such.docx"))
assert r.ok is False
assert "не найден" in r.message.lower() or "Файл" in r.message
@pytest.mark.skipif(sys.platform != "win32", reason="Windows only")
@pytest.mark.skipif(os.environ.get("MD2GOST_TEST_WORD") != "1", reason="set MD2GOST_TEST_WORD=1 to run Word COM smoke")
def test_fix_continuations_com_smoke(tmp_path):
"""Build a tall table DOCX via python-docx, then run Word fix (opt-in)."""
try:
import win32com.client # noqa: F401
except ImportError:
pytest.skip("pywin32 not installed")
from docx import Document
from docx.shared import Pt
path = tmp_path / "tall_table.docx"
doc = Document()
p = doc.add_paragraph("Таблица 1 — Длинная")
try:
p.style = "Caption"
except KeyError:
pass
table = doc.add_table(rows=1, cols=2)
table.rows[0].cells[0].text = "A"
table.rows[0].cells[1].text = "B"
for i in range(80):
row = table.add_row()
row.cells[0].text = f"row {i}"
row.cells[1].text = "x" * 20
for cell in row.cells:
for para in cell.paragraphs:
para.paragraph_format.space_after = Pt(6)
doc.save(str(path))
result = fix_continuations(str(path), tables=True, listings=False)
assert result.ok, result.message
assert path.is_file()