import os
import shutil
import sys
import tempfile
import zipfile
from pathlib import Path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from docx_comments import apply_docx_comments
from models import ReviewFinding
def _finding(
*,
finding_id: str = "test_finding_1",
paragraph_id: str = "P_0008",
target_text: str = "",
anchor_mode: str = "paragraph",
) -> ReviewFinding:
return ReviewFinding(
id=finding_id,
risk_level="high",
clause_type="Indemnification",
issue="Test issue",
comment="This is a test comment from the Mike system.",
review_reasoning={"clause_section": "test", "violated_standard": "test", "zamil_exposure": "Manual test run"},
target_text=target_text,
anchor_mode=anchor_mode,
start_paragraph_id=paragraph_id,
end_paragraph_id=paragraph_id,
start_anchor=target_text[:220],
end_anchor=target_text[-220:] if target_text else "",
before_anchor="",
after_anchor="",
confidence=1.0,
)
def _write_minimal_table_docx(path: Path) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
with zipfile.ZipFile(path, "w") as zf:
zf.writestr(
"[Content_Types].xml",
"""
""",
)
zf.writestr(
"_rels/.rels",
"""
""",
)
zf.writestr(
"word/document.xml",
"""Body paragraph.Table cell clause.""",
)
def test_apply_paragraph_comment_without_target_text():
if shutil.which("dotnet") is None:
import pytest
pytest.skip("dotnet is required for the DOCX commenter integration test")
root = Path(__file__).resolve().parents[1]
sample_docx = root / "data" / "uploads" / "run_20260508_120049_e4b2552b55" / "test_contract.docx"
output_docx = root / "data" / "artifacts" / "test_comments_output.docx"
work_dir = root / "data" / "artifacts" / "test_comments_work"
findings = [_finding(target_text="")]
assert sample_docx.exists(), f"Missing test DOCX fixture: {sample_docx}"
import tempfile
with tempfile.TemporaryDirectory() as tmpdir:
work_dir = Path(tmpdir)
results = apply_docx_comments(
input_docx=sample_docx,
output_docx=output_docx,
findings=findings,
work_dir=work_dir,
)
assert results
assert results[0].id == "test_finding_1"
assert results[0].status == "applied"
assert results[0].failure_code == "editable"
assert results[0].resolve_strategy == "paragraph_anchor"
def test_apply_paragraph_comment_ignores_non_matching_quote_hint():
if shutil.which("dotnet") is None:
import pytest
pytest.skip("dotnet is required for the DOCX commenter integration test")
root = Path(__file__).resolve().parents[1]
sample_docx = root / "data" / "uploads" / "run_20260508_120049_e4b2552b55" / "test_contract.docx"
output_docx = root / "data" / "artifacts" / "test_comments_output.docx"
with tempfile.TemporaryDirectory() as tmpdir:
results = apply_docx_comments(
input_docx=sample_docx,
output_docx=output_docx,
findings=[_finding(target_text="this exact quote does not exist")],
work_dir=Path(tmpdir),
)
assert results[0].status == "applied"
def test_apply_exact_comment_still_uses_target_text():
if shutil.which("dotnet") is None:
import pytest
pytest.skip("dotnet is required for the DOCX commenter integration test")
root = Path(__file__).resolve().parents[1]
sample_docx = root / "data" / "uploads" / "run_20260508_120049_e4b2552b55" / "test_contract.docx"
output_docx = root / "data" / "artifacts" / "test_comments_output.docx"
with tempfile.TemporaryDirectory() as tmpdir:
results = apply_docx_comments(
input_docx=sample_docx,
output_docx=output_docx,
findings=[_finding(paragraph_id="P_0007", target_text="Article 3: Indemnification", anchor_mode="exact")],
work_dir=Path(tmpdir),
)
assert results[0].status == "applied"
assert results[0].resolve_strategy == "exact"
def test_apply_paragraph_comment_invalid_block_id():
if shutil.which("dotnet") is None:
import pytest
pytest.skip("dotnet is required for the DOCX commenter integration test")
root = Path(__file__).resolve().parents[1]
sample_docx = root / "data" / "uploads" / "run_20260508_120049_e4b2552b55" / "test_contract.docx"
output_docx = root / "data" / "artifacts" / "test_comments_output.docx"
with tempfile.TemporaryDirectory() as tmpdir:
results = apply_docx_comments(
input_docx=sample_docx,
output_docx=output_docx,
findings=[_finding(paragraph_id="P_9999")],
work_dir=Path(tmpdir),
)
assert results[0].status == "not_applied"
assert results[0].failure_code == "paragraph_not_found"
def test_apply_paragraph_comment_hash_mismatch_reports_expected_and_actual():
if shutil.which("dotnet") is None:
import pytest
pytest.skip("dotnet is required for the DOCX commenter integration test")
root = Path(__file__).resolve().parents[1]
sample_docx = root / "data" / "uploads" / "run_20260508_120049_e4b2552b55" / "test_contract.docx"
output_docx = root / "data" / "artifacts" / "test_comments_output.docx"
finding = _finding().model_copy(update={"text_hash": "definitely_wrong"})
with tempfile.TemporaryDirectory() as tmpdir:
results = apply_docx_comments(
input_docx=sample_docx,
output_docx=output_docx,
findings=[finding],
work_dir=Path(tmpdir),
)
assert results[0].status == "not_applied"
assert results[0].failure_code == "anchor_stale"
assert results[0].expected_text_hash == "definitely_wrong"
assert results[0].actual_text_hash
assert results[0].actual_text_hash != results[0].expected_text_hash
def test_apply_paragraph_comment_inside_table_cell():
if shutil.which("dotnet") is None:
import pytest
pytest.skip("dotnet is required for the DOCX commenter integration test")
with tempfile.TemporaryDirectory() as tmpdir:
tmp = Path(tmpdir)
input_docx = tmp / "table.docx"
output_docx = tmp / "table_commented.docx"
_write_minimal_table_docx(input_docx)
results = apply_docx_comments(
input_docx=input_docx,
output_docx=output_docx,
findings=[_finding(paragraph_id="P_0002")],
work_dir=tmp / "work",
)
assert results[0].status == "applied"
assert results[0].paragraph_id == "P_0002"
if __name__ == "__main__":
test_apply_paragraph_comment_without_target_text()