from __future__ import annotations
from unittest.mock import AsyncMock, Mock
import pytest
from langchain_core.tools import ToolException
import msagent.tools.web_search as web_search_module
from msagent.tools.web_search import (
WebSearchInput,
WebSearchNoResultsError,
_run_duckduckgo_search,
web_search,
)
def test_web_search_input_normalizes_query() -> None:
payload = WebSearchInput(query=" langchain deepagents ")
assert payload.query == "langchain deepagents"
@pytest.mark.asyncio
async def test_run_duckduckgo_search_returns_plain_text(monkeypatch: pytest.MonkeyPatch) -> None:
tool = Mock()
tool.ainvoke = AsyncMock(return_value="deepagents search result")
monkeypatch.setattr(web_search_module, "_get_duckduckgo_search_tool", Mock(return_value=tool))
result = await _run_duckduckgo_search("deepagents")
assert result == "deepagents search result"
@pytest.mark.asyncio
async def test_web_search_returns_plain_text_results(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(
web_search_module,
"_run_duckduckgo_search",
AsyncMock(return_value="deepagents search result"),
)
result = await web_search.coroutine(query="deepagents")
assert result == "deepagents search result"
@pytest.mark.asyncio
async def test_web_search_reports_no_results_as_business_message(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(
web_search_module,
"_run_duckduckgo_search",
AsyncMock(side_effect=WebSearchNoResultsError("DuckDuckGo search returned no results")),
)
result = await web_search.coroutine(query="deepagents")
assert "Unable to complete web search for query: deepagents" in result
assert "reason=DuckDuckGo search returned no results" in result
assert "do not retry web_search again for this request" in result
@pytest.mark.asyncio
async def test_web_search_reraises_execution_failures(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(
web_search_module,
"_run_duckduckgo_search",
AsyncMock(side_effect=ToolException("DuckDuckGo search timed out after 10s")),
)
with pytest.raises(ToolException, match="DuckDuckGo search timed out after 10s"):
await web_search.coroutine(query="deepagents")