Initial commit: Research Bridge API with Podman support
This commit is contained in:
140
tests/unit/test_searxng_client.py
Normal file
140
tests/unit/test_searxng_client.py
Normal file
@@ -0,0 +1,140 @@
|
||||
"""Unit tests for SearXNG client."""
|
||||
import json
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
from httpx import Response
|
||||
|
||||
from src.models.schemas import SearchRequest
|
||||
from src.search.searxng import SearXNGClient, SearXNGError
|
||||
|
||||
|
||||
class TestSearXNGClient:
|
||||
"""Test cases for SearXNGClient."""
|
||||
|
||||
@pytest.fixture
|
||||
def client(self):
|
||||
return SearXNGClient(base_url="http://test:8080")
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_success(self, client):
|
||||
"""Test successful search request."""
|
||||
mock_response = {
|
||||
"results": [
|
||||
{
|
||||
"title": "Test Result",
|
||||
"url": "https://example.com",
|
||||
"content": "Test content",
|
||||
"engine": "google",
|
||||
"score": 0.95
|
||||
}
|
||||
],
|
||||
"number_of_results": 1,
|
||||
"engines": ["google"]
|
||||
}
|
||||
|
||||
mock_client = AsyncMock()
|
||||
mock_response_obj = Mock()
|
||||
mock_response_obj.status_code = 200
|
||||
mock_response_obj.json = Mock(return_value=mock_response)
|
||||
mock_response_obj.text = json.dumps(mock_response)
|
||||
mock_response_obj.raise_for_status = Mock(return_value=None)
|
||||
mock_client.get.return_value = mock_response_obj
|
||||
|
||||
with patch.object(client, '_client', mock_client):
|
||||
request = SearchRequest(q="test query", engines=["google"], page=1)
|
||||
result = await client.search(request)
|
||||
|
||||
assert result.query == "test query"
|
||||
assert len(result.results) == 1
|
||||
assert result.results[0].title == "Test Result"
|
||||
assert result.results[0].source == "google"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_http_error(self, client):
|
||||
"""Test handling of HTTP errors."""
|
||||
mock_client = AsyncMock()
|
||||
|
||||
# Create proper HTTPStatusError with async side effect
|
||||
async def raise_http_error(*args, **kwargs):
|
||||
from httpx import Request, Response
|
||||
mock_request = Mock(spec=Request)
|
||||
mock_response = Response(status_code=404, text="Not found")
|
||||
raise httpx.HTTPStatusError(
|
||||
"Not found",
|
||||
request=mock_request,
|
||||
response=mock_response
|
||||
)
|
||||
|
||||
mock_client.get.side_effect = raise_http_error
|
||||
|
||||
with patch.object(client, '_client', mock_client):
|
||||
request = SearchRequest(q="test", engines=["google"], page=1)
|
||||
with pytest.raises(SearXNGError) as exc_info:
|
||||
await client.search(request)
|
||||
|
||||
assert "HTTP error" in str(exc_info.value)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_connection_error(self, client):
|
||||
"""Test handling of connection errors."""
|
||||
mock_client = AsyncMock()
|
||||
mock_client.get.side_effect = httpx.ConnectError("Connection refused")
|
||||
|
||||
with patch.object(client, '_client', mock_client):
|
||||
request = SearchRequest(q="test", engines=["google"], page=1)
|
||||
with pytest.raises(SearXNGError) as exc_info:
|
||||
await client.search(request)
|
||||
|
||||
assert "Request failed" in str(exc_info.value)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_invalid_json(self, client):
|
||||
"""Test handling of invalid JSON response."""
|
||||
mock_client = AsyncMock()
|
||||
mock_response = Mock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.json.side_effect = json.JSONDecodeError("test", "", 0)
|
||||
mock_response.text = "invalid json"
|
||||
mock_response.raise_for_status = Mock(return_value=None)
|
||||
mock_client.get.return_value = mock_response
|
||||
|
||||
with patch.object(client, '_client', mock_client):
|
||||
request = SearchRequest(q="test", engines=["google"], page=1)
|
||||
with pytest.raises(SearXNGError) as exc_info:
|
||||
await client.search(request)
|
||||
|
||||
assert "Invalid JSON" in str(exc_info.value)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_health_check_success(self, client):
|
||||
"""Test successful health check."""
|
||||
mock_client = AsyncMock()
|
||||
mock_client.get.return_value = Response(status_code=200)
|
||||
|
||||
with patch.object(client, '_client', mock_client):
|
||||
result = await client.health_check()
|
||||
|
||||
assert result is True
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_health_check_failure(self, client):
|
||||
"""Test failed health check."""
|
||||
mock_client = AsyncMock()
|
||||
mock_client.get.side_effect = httpx.ConnectError("Connection refused")
|
||||
|
||||
with patch.object(client, '_client', mock_client):
|
||||
result = await client.health_check()
|
||||
|
||||
assert result is False
|
||||
|
||||
def test_build_url(self, client):
|
||||
"""Test URL building with parameters."""
|
||||
params = {"q": "test query", "format": "json", "engines": "google,bing"}
|
||||
url = client._build_url(params)
|
||||
|
||||
assert url.startswith("http://test:8080/search")
|
||||
assert "q=test+query" in url or "q=test%20query" in url
|
||||
assert "format=json" in url
|
||||
assert "engines=google%2Cbing" in url or "engines=google,bing" in url
|
||||
Reference in New Issue
Block a user