test: 6 parallel agents — +40 test files across core, agent, translate, services, API routes, dataset_review. core 100%, agent 100%, services 100%, translate plugin mostly done. Pending: ~10 minor failures to fix
This commit is contained in:
@@ -8,6 +8,8 @@ sys.path.append(str(Path(__file__).parent.parent.parent / "src"))
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from src.agent.document_parser import parse_pdf, parse_xlsx, parse_upload, ParseError
|
||||
@@ -188,5 +190,114 @@ def test_parse_upload_dict():
|
||||
assert "Dict test" in result
|
||||
finally:
|
||||
os.unlink(tmp_path)
|
||||
|
||||
|
||||
def test_parse_upload_file_path_fallback():
|
||||
"""parse_upload falls back to file_path key if path is missing."""
|
||||
with tempfile.NamedTemporaryFile(suffix=".txt", mode="w", delete=False) as f:
|
||||
f.write("Fallback key test")
|
||||
tmp_path = f.name
|
||||
|
||||
try:
|
||||
result = parse_upload({"name": "test.txt", "file_path": tmp_path})
|
||||
assert "Fallback" in result
|
||||
finally:
|
||||
os.unlink(tmp_path)
|
||||
# #endregion TestAgentChat.DocumentParser.ParseUpload
|
||||
|
||||
|
||||
# #region TestAgentChat.DocumentParser.ImportErrors [C:2] [TYPE Function] [SEMANTICS test,parser,import,error]
|
||||
# @BRIEF Test ImportError paths in parse_pdf and parse_xlsx.
|
||||
|
||||
def test_parse_pdf_import_error():
|
||||
"""pdfplumber import fails → ParseError."""
|
||||
import builtins
|
||||
real_import = builtins.__import__
|
||||
|
||||
def raise_on_pdfplumber(name, globals=None, locals=None, fromlist=(), level=0):
|
||||
if name == 'pdfplumber':
|
||||
raise ImportError(f"No module named pdfplumber", name=name)
|
||||
return real_import(name, globals, locals, fromlist, level)
|
||||
|
||||
with patch('builtins.__import__', side_effect=raise_on_pdfplumber):
|
||||
with pytest.raises(ParseError, match="pdfplumber not installed"):
|
||||
parse_pdf("/tmp/dummy.pdf")
|
||||
|
||||
|
||||
def test_parse_xlsx_import_error():
|
||||
"""openpyxl import fails → ParseError."""
|
||||
import builtins
|
||||
real_import = builtins.__import__
|
||||
|
||||
def raise_on_openpyxl(name, globals=None, locals=None, fromlist=(), level=0):
|
||||
if name == 'openpyxl':
|
||||
raise ImportError(f"No module named openpyxl", name=name)
|
||||
return real_import(name, globals, locals, fromlist, level)
|
||||
|
||||
with patch('builtins.__import__', side_effect=raise_on_openpyxl):
|
||||
with pytest.raises(ParseError, match="openpyxl not installed"):
|
||||
parse_xlsx("/tmp/dummy.xlsx")
|
||||
# #endregion TestAgentChat.DocumentParser.ImportErrors
|
||||
|
||||
|
||||
# #region TestAgentChat.DocumentParser.PyPDF2Fallback [C:2] [TYPE Function] [SEMANTICS test,parser,pypdf2,fallback]
|
||||
# @BRIEF When pdfplumber fails, PyPDF2 is used as fallback path.
|
||||
|
||||
def test_parse_pdf_pypdf2_fallback():
|
||||
"""pdfplumber failure triggers PyPDF2 fallback."""
|
||||
# Build mock PyPDF2 module in sys.modules
|
||||
mock_pypdf2 = MagicMock()
|
||||
mock_reader = MagicMock()
|
||||
mock_page = MagicMock()
|
||||
mock_page.extract_text.return_value = "Fallback PyPDF2 text"
|
||||
mock_reader.pages = [mock_page]
|
||||
mock_pypdf2.PdfReader = MagicMock(return_value=mock_reader)
|
||||
|
||||
with tempfile.NamedTemporaryFile(suffix=".pdf", delete=False) as f:
|
||||
f.write(b"dummy pdf content")
|
||||
tmp_path = f.name
|
||||
|
||||
try:
|
||||
# Patch pdfplumber.open directly (the real module) — NOT document_parser.pdfplumber
|
||||
# because pdfplumber is imported inside the function body, not at module level.
|
||||
with patch('pdfplumber.open', side_effect=Exception("pdfplumber error")), \
|
||||
patch.dict('sys.modules', {'PyPDF2': mock_pypdf2}):
|
||||
result = parse_pdf(tmp_path)
|
||||
assert isinstance(result, str)
|
||||
assert "PyPDF2" in result
|
||||
mock_pypdf2.PdfReader.assert_called_once()
|
||||
finally:
|
||||
os.unlink(tmp_path)
|
||||
# #endregion TestAgentChat.DocumentParser.PyPDF2Fallback
|
||||
|
||||
|
||||
# #region TestAgentChat.DocumentParser.ParseUploadBranches [C:2] [TYPE Function] [SEMANTICS test,parser,upload,branches]
|
||||
# @BRIEF Test parse_upload dispatches to correct parser for PDF, XLSX, XLS.
|
||||
|
||||
def test_parse_upload_pdf_branch():
|
||||
"""parse_upload with .pdf dispatches to parse_pdf."""
|
||||
import src.agent.document_parser as dp
|
||||
with patch.object(dp, 'parse_pdf', return_value="pdf result") as mock_parse:
|
||||
result = parse_upload({"name": "report.pdf", "path": "/tmp/report.pdf"})
|
||||
assert result == "pdf result"
|
||||
mock_parse.assert_called_once_with("/tmp/report.pdf")
|
||||
|
||||
|
||||
def test_parse_upload_xlsx_branch():
|
||||
"""parse_upload with .xlsx dispatches to parse_xlsx."""
|
||||
import src.agent.document_parser as dp
|
||||
with patch.object(dp, 'parse_xlsx', return_value="xlsx result") as mock_parse:
|
||||
result = parse_upload({"name": "data.xlsx", "path": "/tmp/data.xlsx"})
|
||||
assert result == "xlsx result"
|
||||
mock_parse.assert_called_once_with("/tmp/data.xlsx")
|
||||
|
||||
|
||||
def test_parse_upload_xls_branch():
|
||||
"""parse_upload with .xls (legacy) also dispatches to parse_xlsx."""
|
||||
import src.agent.document_parser as dp
|
||||
with patch.object(dp, 'parse_xlsx', return_value="xls result") as mock_parse:
|
||||
result = parse_upload({"name": "legacy.xls", "path": "/tmp/legacy.xls"})
|
||||
assert result == "xls result"
|
||||
mock_parse.assert_called_once_with("/tmp/legacy.xls")
|
||||
# #endregion TestAgentChat.DocumentParser.ParseUploadBranches
|
||||
# #endregion TestAgentChat.DocumentParser
|
||||
|
||||
Reference in New Issue
Block a user