ai-lawyer-agent/testing/tests/test_tools.py
2026-03-23 09:07:12 +01:00

265 lines
10 KiB
Python

import pytest
import httpx
import respx
from api.fetch_api_data import _cache
from api.config import JUSTICE_API_BASE
from api.tools import (
court_search,
court_id,
court_autocomplete,
judge_search,
judge_id,
judge_autocomplete,
decision_search,
decision_id,
decision_autocomplete,
contract_search,
contract_id,
contract_autocomplete,
civil_proceedings_search,
civil_proceedings_id,
civil_proceedings_autocomplete,
admin_proceedings_search,
admin_proceedings_id,
admin_proceedings_autocomplete,
)
EMPTY_LIST_RESPONSE = {"content": [], "totalElements": 0, "numberOfElements": 0}
@pytest.fixture(autouse=True)
def clear_cache():
_cache.clear()
yield
_cache.clear()
def make_response(body: dict = None):
return httpx.Response(200, json=body or EMPTY_LIST_RESPONSE)
@pytest.mark.asyncio
class TestCourtTools:
@respx.mock
async def test_court_search_calls_correct_url(self):
mock = respx.get(f"{JUSTICE_API_BASE}/v1/sud").mock(return_value=make_response())
await court_search.on_invoke_tool(None, '{"params": {"query": "Bratislava"}}')
assert mock.called
@respx.mock
async def test_court_id_calls_correct_url(self):
mock = respx.get(f"{JUSTICE_API_BASE}/v1/sud/sud_175").mock(
return_value=httpx.Response(200, json={"id": "sud_175", "foto": "data"})
)
await court_id.on_invoke_tool(None, '{"params": {"id": "175"}}')
assert mock.called
@respx.mock
async def test_court_id_removes_foto_key(self):
respx.get(f"{JUSTICE_API_BASE}/v1/sud/sud_1").mock(
return_value=httpx.Response(200, json={"name": "Súd", "foto": "base64"})
)
result = await court_id.on_invoke_tool(None, '{"params": {"id": "1"}}')
assert "foto" not in str(result)
@respx.mock
async def test_court_autocomplete_calls_correct_url(self):
mock = respx.get(f"{JUSTICE_API_BASE}/v1/sud/autocomplete").mock(return_value=make_response())
await court_autocomplete.on_invoke_tool(None, '{"params": {"query": "Kraj"}}')
assert mock.called
@respx.mock
async def test_court_search_empty_params(self):
mock = respx.get(f"{JUSTICE_API_BASE}/v1/sud").mock(return_value=make_response())
await court_search.on_invoke_tool(None, '{"params": {}}')
assert mock.called
@pytest.mark.asyncio
class TestJudgeTools:
@respx.mock
async def test_judge_search_calls_correct_url(self):
mock = respx.get(f"{JUSTICE_API_BASE}/v1/sudca").mock(return_value=make_response())
await judge_search.on_invoke_tool(None, '{"params": {"query": "Novák"}}')
assert mock.called
@respx.mock
async def test_judge_id_normalizes_digit_id(self):
mock = respx.get(f"{JUSTICE_API_BASE}/v1/sudca/sudca_1").mock(
return_value=httpx.Response(200, json={"id": "sudca_1"})
)
await judge_id.on_invoke_tool(None, '{"params": {"id": "1"}}')
assert mock.called
@respx.mock
async def test_judge_id_with_prefix(self):
mock = respx.get(f"{JUSTICE_API_BASE}/v1/sudca/sudca_42").mock(
return_value=httpx.Response(200, json={"id": "sudca_42"})
)
await judge_id.on_invoke_tool(None, '{"params": {"id": "sudca_42"}}')
assert mock.called
@respx.mock
async def test_judge_autocomplete_passes_guid_sud(self):
mock = respx.get(f"{JUSTICE_API_BASE}/v1/sudca/autocomplete").mock(return_value=make_response())
await judge_autocomplete.on_invoke_tool(None, '{"params": {"query": "Novák", "guidSud": "sud_100"}}')
assert mock.called
params = dict(mock.calls[0].request.url.params)
assert params.get("guidSud") == "sud_100"
@respx.mock
async def test_judge_autocomplete_without_guid(self):
mock = respx.get(f"{JUSTICE_API_BASE}/v1/sudca/autocomplete").mock(return_value=make_response())
await judge_autocomplete.on_invoke_tool(None, '{"params": {"query": "Kováč", "limit": 5}}')
assert mock.called
params = dict(mock.calls[0].request.url.params)
assert params.get("query") == "Kováč"
@pytest.mark.asyncio
class TestDecisionTools:
@respx.mock
async def test_decision_search_with_date_range(self):
mock = respx.get(f"{JUSTICE_API_BASE}/v1/rozhodnutie").mock(return_value=make_response())
await decision_search.on_invoke_tool(
None, '{"params": {"vydaniaOd": "01.01.2024", "vydaniaDo": "31.01.2024"}}'
)
assert mock.called
params = dict(mock.calls[0].request.url.params)
assert params.get("vydaniaOd") == "01.01.2024"
@respx.mock
async def test_decision_search_with_guid_sudca(self):
mock = respx.get(f"{JUSTICE_API_BASE}/v1/rozhodnutie").mock(return_value=make_response())
await decision_search.on_invoke_tool(None, '{"params": {"guidSudca": "sudca_1"}}')
assert mock.called
params = dict(mock.calls[0].request.url.params)
assert params.get("guidSudca") == "sudca_1"
@respx.mock
async def test_decision_id_calls_correct_url(self):
"""Covers missing lines 128-130 in tools.py"""
mock = respx.get(f"{JUSTICE_API_BASE}/v1/rozhodnutie/rozhodnutie_99").mock(
return_value=httpx.Response(200, json={"id": "rozhodnutie_99"})
)
await decision_id.on_invoke_tool(None, '{"params": {"id": "rozhodnutie_99"}}')
assert mock.called
@respx.mock
async def test_decision_autocomplete_calls_correct_url(self):
"""Covers missing lines 141-143 in tools.py"""
mock = respx.get(f"{JUSTICE_API_BASE}/v1/rozhodnutie/autocomplete").mock(
return_value=make_response()
)
await decision_autocomplete.on_invoke_tool(None, '{"params": {"query": "Rozsudok", "limit": 5}}')
assert mock.called
params = dict(mock.calls[0].request.url.params)
assert params.get("query") == "Rozsudok"
@pytest.mark.asyncio
class TestContractTools:
@respx.mock
async def test_contract_search_with_guid_sud(self):
mock = respx.get(f"{JUSTICE_API_BASE}/v1/zmluvy").mock(return_value=make_response())
await contract_search.on_invoke_tool(None, '{"params": {"guidSud": "sud_7"}}')
assert mock.called
params = dict(mock.calls[0].request.url.params)
assert params.get("guidSud") == "sud_7"
@respx.mock
async def test_contract_search_typ_dokumentu_filter(self):
mock = respx.get(f"{JUSTICE_API_BASE}/v1/zmluvy").mock(return_value=make_response())
await contract_search.on_invoke_tool(None, '{"params": {"typDokumentuFacetFilter": ["ZMLUVA"]}}')
assert mock.called
@respx.mock
async def test_contract_id_calls_correct_url(self):
"""Covers missing lines 172-174 in tools.py"""
mock = respx.get(f"{JUSTICE_API_BASE}/v1/zmluvy/2156252").mock(
return_value=httpx.Response(200, json={"idZmluvy": "2156252"})
)
await contract_id.on_invoke_tool(None, '{"params": {"idZmluvy": "2156252"}}')
assert mock.called
@respx.mock
async def test_contract_autocomplete_calls_correct_url(self):
"""Covers missing lines 185-187 in tools.py"""
mock = respx.get(f"{JUSTICE_API_BASE}/v1/zmluvy/autocomplete").mock(
return_value=make_response()
)
await contract_autocomplete.on_invoke_tool(None, '{"params": {"query": "Slovak Telekom"}}')
assert mock.called
params = dict(mock.calls[0].request.url.params)
assert params.get("query") == "Slovak Telekom"
@pytest.mark.asyncio
class TestCivilAndAdminTools:
@respx.mock
async def test_civil_proceedings_search(self):
mock = respx.get(f"{JUSTICE_API_BASE}/v1/obcianPojednavania").mock(return_value=make_response())
await civil_proceedings_search.on_invoke_tool(None, '{"params": {"query": "test"}}')
assert mock.called
@respx.mock
async def test_civil_proceedings_id_calls_correct_url(self):
"""Covers missing lines 217-219 in tools.py"""
uid = "121e4d31-695e-41e1-9191-7c9ad5d8d484"
mock = respx.get(f"{JUSTICE_API_BASE}/v1/obcianPojednavania/{uid}").mock(
return_value=httpx.Response(200, json={"id": uid})
)
await civil_proceedings_id.on_invoke_tool(None, f'{{"params": {{"id": "{uid}"}}}}')
assert mock.called
@respx.mock
async def test_civil_proceedings_autocomplete_calls_correct_url(self):
"""Covers missing lines 230-232 in tools.py"""
mock = respx.get(f"{JUSTICE_API_BASE}/v1/obcianPojednavania/autocomplete").mock(
return_value=make_response()
)
await civil_proceedings_autocomplete.on_invoke_tool(
None, '{"params": {"query": "test", "limit": 5}}'
)
assert mock.called
@respx.mock
async def test_admin_proceedings_search(self):
mock = respx.get(f"{JUSTICE_API_BASE}/v1/spravneKonanie").mock(return_value=make_response())
await admin_proceedings_search.on_invoke_tool(None, '{"params": {"query": "test"}}')
assert mock.called
@respx.mock
async def test_admin_proceedings_id_calls_correct_url(self):
"""Covers missing lines 260-262 in tools.py"""
mock = respx.get(f"{JUSTICE_API_BASE}/v1/spravneKonanie/spravneKonanie_103").mock(
return_value=httpx.Response(200, json={"id": "spravneKonanie_103"})
)
await admin_proceedings_id.on_invoke_tool(None, '{"params": {"id": "103"}}')
assert mock.called
@respx.mock
async def test_admin_proceedings_autocomplete_calls_correct_url(self):
"""Covers missing lines 273-275 in tools.py"""
mock = respx.get(f"{JUSTICE_API_BASE}/v1/spravneKonanie/autocomplete").mock(
return_value=make_response()
)
await admin_proceedings_autocomplete.on_invoke_tool(
None, '{"params": {"query": "konanie", "limit": 10}}'
)
assert mock.called
@respx.mock
async def test_civil_proceedings_date_params(self):
mock = respx.get(f"{JUSTICE_API_BASE}/v1/obcianPojednavania").mock(return_value=make_response())
await civil_proceedings_search.on_invoke_tool(
None, '{"params": {"pojednavaniaOd": "01.01.2024", "pojednavaniaDo": "31.01.2024"}}'
)
assert mock.called