deer-flow/backend/tests/test_upload_conversion.py
2026-08-06 10:11:10 +08:00

93 lines
3.2 KiB
Python

"""Tests for publication of system-owned Markdown upload conversions."""
from pathlib import Path
from unittest.mock import AsyncMock, patch
import pytest
from deerflow.uploads.conversion import convert_uploaded_file_to_markdown
from deerflow.uploads.layout import conversion_path_for_upload
@pytest.mark.asyncio
async def test_conversion_uses_owned_full_filename_target(tmp_path):
uploads = tmp_path / "user-data" / "uploads"
uploads.mkdir(parents=True)
pdf = uploads / "report.pdf"
docx = uploads / "report.docx"
pdf.write_bytes(b"PDF")
docx.write_bytes(b"DOCX")
async def fake_convert(source: Path, output_path: Path | None = None):
assert output_path is not None
output_path.write_text(f"from:{source.name}", encoding="utf-8")
return output_path
with patch(
"deerflow.uploads.conversion.convert_file_to_markdown",
AsyncMock(side_effect=fake_convert),
):
pdf_md = await convert_uploaded_file_to_markdown(pdf)
docx_md = await convert_uploaded_file_to_markdown(docx)
assert pdf_md == conversion_path_for_upload(pdf)
assert docx_md == conversion_path_for_upload(docx)
assert pdf_md.read_text(encoding="utf-8") == "from:report.pdf"
assert docx_md.read_text(encoding="utf-8") == "from:report.docx"
@pytest.mark.asyncio
async def test_conversion_failure_cleans_stage_and_keeps_user_markdown(tmp_path):
uploads = tmp_path / "user-data" / "uploads"
uploads.mkdir(parents=True)
source = uploads / "report.pdf"
source.write_bytes(b"PDF")
user_markdown = uploads / "report.md"
user_markdown.write_text("user", encoding="utf-8")
with patch(
"deerflow.uploads.conversion.convert_file_to_markdown",
AsyncMock(return_value=None),
):
assert await convert_uploaded_file_to_markdown(source) is None
assert user_markdown.read_text(encoding="utf-8") == "user"
conversion_dir = uploads.parent / ".upload-conversions"
assert not list(conversion_dir.glob(".upload-*.part"))
@pytest.mark.asyncio
async def test_conversion_directory_symlink_is_rejected(tmp_path):
uploads = tmp_path / "user-data" / "uploads"
uploads.mkdir(parents=True)
source = uploads / "report.pdf"
source.write_bytes(b"PDF")
outside = tmp_path / "outside"
outside.mkdir()
(uploads.parent / ".upload-conversions").symlink_to(outside, target_is_directory=True)
with pytest.raises(ValueError, match="conversion directory"):
await convert_uploaded_file_to_markdown(source)
assert list(outside.iterdir()) == []
@pytest.mark.asyncio
async def test_unexpected_converter_output_is_rejected_and_cleaned(tmp_path):
uploads = tmp_path / "user-data" / "uploads"
uploads.mkdir(parents=True)
source = uploads / "report.pdf"
source.write_bytes(b"PDF")
unexpected = uploads / "report.md"
with patch(
"deerflow.uploads.conversion.convert_file_to_markdown",
AsyncMock(return_value=unexpected),
):
with pytest.raises(ValueError, match="unexpected output path"):
await convert_uploaded_file_to_markdown(source)
assert not unexpected.exists()
conversion_dir = uploads.parent / ".upload-conversions"
assert not list(conversion_dir.glob(".upload-*.part"))