from pathlib import Path
from unittest.mock import MagicMock, patch
import xml.etree.ElementTree as ET
from crewai_tools import ArxivPaperTool
import pytest
import requests
@pytest.fixture
def tool():
return ArxivPaperTool(download_pdfs=False)
@pytest.fixture(autouse=True)
def mock_validate_url():
with patch(
"crewai_tools.tools.arxiv_paper_tool.arxiv_paper_tool.validate_url",
side_effect=lambda url: url,
):
yield
def mock_arxiv_response():
return """
http://arxiv.org/abs/1234.5678
Sample Paper
This is a summary of the sample paper.
2022-01-01T00:00:00Z
John Doe
"""
@patch("crewai_tools.tools.arxiv_paper_tool.arxiv_paper_tool.requests.get")
def test_fetch_arxiv_data(mock_get, tool):
mock_response = MagicMock()
mock_response.text = mock_arxiv_response()
mock_get.return_value = mock_response
results = tool.fetch_arxiv_data("transformer", 1)
assert isinstance(results, list)
assert results[0]["title"] == "Sample Paper"
@patch(
"crewai_tools.tools.arxiv_paper_tool.arxiv_paper_tool.requests.get",
side_effect=requests.RequestException("Timeout"),
)
def test_fetch_arxiv_data_network_error(mock_get, tool):
with pytest.raises(requests.RequestException):
tool.fetch_arxiv_data("transformer", 1)
@patch("urllib.request.urlretrieve")
def test_download_pdf_success(mock_urlretrieve):
tool = ArxivPaperTool()
tool.download_pdf("http://arxiv.org/pdf/1234.5678.pdf", Path("test.pdf"))
mock_urlretrieve.assert_called_once()
@patch("urllib.request.urlretrieve", side_effect=OSError("Permission denied"))
def test_download_pdf_oserror(mock_urlretrieve):
tool = ArxivPaperTool()
with pytest.raises(OSError):
tool.download_pdf(
"http://arxiv.org/pdf/1234.5678.pdf", Path("/restricted/test.pdf")
)
@patch("crewai_tools.tools.arxiv_paper_tool.arxiv_paper_tool.requests.get")
@patch("urllib.request.urlretrieve")
def test_run_with_download(mock_urlretrieve, mock_get):
mock_response = MagicMock()
mock_response.text = mock_arxiv_response()
mock_get.return_value = mock_response
tool = ArxivPaperTool(download_pdfs=True)
output = tool._run("transformer", 1)
assert "Title: Sample Paper" in output
mock_urlretrieve.assert_called_once()
@patch("crewai_tools.tools.arxiv_paper_tool.arxiv_paper_tool.requests.get")
def test_run_no_download(mock_get):
mock_response = MagicMock()
mock_response.text = mock_arxiv_response()
mock_get.return_value = mock_response
tool = ArxivPaperTool(download_pdfs=False)
result = tool._run("transformer", 1)
assert "Title: Sample Paper" in result
@patch("pathlib.Path.mkdir")
def test_validate_save_path_creates_directory(mock_mkdir):
path = ArxivPaperTool._validate_save_path("new_folder")
mock_mkdir.assert_called_once_with(parents=True, exist_ok=True)
assert isinstance(path, Path)
@patch("crewai_tools.tools.arxiv_paper_tool.arxiv_paper_tool.requests.get")
def test_run_handles_exception(mock_get):
mock_get.side_effect = Exception("API failure")
tool = ArxivPaperTool()
result = tool._run("transformer", 1)
assert "Failed to fetch or download Arxiv papers" in result
@patch("crewai_tools.tools.arxiv_paper_tool.arxiv_paper_tool.requests.get")
def test_invalid_xml_response(mock_get, tool):
mock_response = MagicMock()
mock_response.text = ""
mock_get.return_value = mock_response
with pytest.raises(ET.ParseError):
tool.fetch_arxiv_data("quantum", 1)
@patch.object(ArxivPaperTool, "fetch_arxiv_data")
def test_run_with_max_results(mock_fetch, tool):
mock_fetch.return_value = [
{
"arxiv_id": f"test_{i}",
"title": f"Title {i}",
"summary": "Summary",
"authors": ["Author"],
"published_date": "2023-01-01",
"pdf_url": None,
}
for i in range(100)
]
result = tool._run(search_query="test", max_results=100)
assert result.count("Title:") == 100