legal-ai-assistant/tests/unit/test_http.py

120 lines
3.8 KiB
Python

import pytest
import httpx
from unittest.mock import AsyncMock, MagicMock, patch
from backend.tools.api.http_request_handler import http_request
class TestSuccessfulRequest:
"""
checks successful HTTP request, parameter
passing, and response structure.
"""
@pytest.mark.asyncio
async def test_returns_data_key(self, mock_client, make_response) -> None:
mock_client.get.return_value = make_response({"items": [{"id": "sud_7"}]})
result = await http_request("/sud", {})
assert "data" in result
assert result["data"]["items"][0]["id"] == "sud_7"
@pytest.mark.asyncio
async def test_returns_url_key(self, mock_client, make_response) -> None:
mock_client.get.return_value = make_response({})
result = await http_request("/sud", {})
assert "url" in result
@pytest.mark.asyncio
async def test_params_passed_to_get(self, mock_client, make_response) -> None:
mock_client.get.return_value = make_response({})
await http_request("/sud", {"query": "Bratislava", "size": 10})
args, kwargs = mock_client.get.call_args
called_url = args[0] if args else kwargs.get("url", "")
assert "query=Bratislava" in called_url
assert "size=10" in called_url
class TestRemoveKeys:
"""
verifies the removal of the given keys from
the response without errors.
"""
@pytest.mark.asyncio
async def test_key_removed_from_data(self, mock_client, make_response) -> None:
mock_client.get.return_value = make_response(
{"id": "sud_7", "_internal": "secret"}
)
result = await http_request("/sud", {}, remove_keys=["_internal"])
assert "_internal" not in result["data"]
assert result["data"]["id"] == "sud_7"
@pytest.mark.asyncio
async def test_nonexistent_key_does_not_raise(self, mock_client, make_response) -> None:
mock_client.get.return_value = make_response({"id": "1"})
result = await http_request("/sud", {}, remove_keys=["ghost"])
assert result["data"] == {"id": "1"}
class TestCaching:
"""
Checks the operation of request caching
(repeated calls do not duplicate HTTP).
"""
@pytest.mark.asyncio
async def test_same_request_called_once(self, mock_client, make_response) -> None:
mock_client.get.return_value = make_response({"data": "x"})
await http_request("/sud", {"q": "test"})
await http_request("/sud", {"q": "test"})
assert mock_client.get.call_count == 1
@pytest.mark.asyncio
async def test_different_params_not_cached(self, mock_client, make_response) -> None:
mock_client.get.return_value = make_response({})
await http_request("/sud", {"q": "Bratislava"})
await http_request("/sud", {"q": "Košice"})
assert mock_client.get.call_count == 2
class TestHTTPErrors:
"""
Checks for correct HTTP handling
and unexpected errors.
"""
@pytest.mark.asyncio
@pytest.mark.parametrize("status", [404, 500, 503])
async def test_http_error_returns_error_dict(self, status, mock_client) -> None:
mock_client.get = AsyncMock(
side_effect=httpx.HTTPStatusError(
f"HTTP {status}",
request=MagicMock(),
response=MagicMock(status_code=status),
)
)
result = await http_request("/sud", {})
assert result["error"] == "http_error"
assert "detail" in result
@pytest.mark.asyncio
async def test_unexpected_error_returns_error_dict(self, mock_client) -> None:
mock_client.get = AsyncMock(side_effect=Exception("boom"))
result = await http_request("/sud", {})
assert result["error"] == "unexpected_error"
assert "detail" in result