Refactor geo re-resolve endpoint into geo_service and add typed response
This commit is contained in:
@@ -48,7 +48,9 @@ async def geo_client(tmp_path: Path) -> AsyncClient: # type: ignore[misc]
|
||||
|
||||
transport = ASGITransport(app=app)
|
||||
async with AsyncClient(transport=transport, base_url="http://test") as ac:
|
||||
await ac.post("/api/setup", json=_SETUP_PAYLOAD)
|
||||
setup_payload = _SETUP_PAYLOAD.copy()
|
||||
setup_payload["database_path"] = settings.database_path
|
||||
await ac.post("/api/setup", json=setup_payload)
|
||||
login = await ac.post(
|
||||
"/api/auth/login",
|
||||
json={"password": _SETUP_PAYLOAD["master_password"]},
|
||||
@@ -170,15 +172,15 @@ class TestReResolve:
|
||||
async def test_returns_200_with_counts(self, geo_client: AsyncClient) -> None:
|
||||
"""POST /api/geo/re-resolve returns 200 with resolved/total counts."""
|
||||
with patch(
|
||||
"app.routers.geo.geo_service.lookup_batch",
|
||||
AsyncMock(return_value={}),
|
||||
"app.routers.geo.geo_service.re_resolve_all",
|
||||
AsyncMock(return_value={"resolved": 0, "total": 0}),
|
||||
):
|
||||
resp = await geo_client.post("/api/geo/re-resolve")
|
||||
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert "resolved" in data
|
||||
assert "total" in data
|
||||
assert data["resolved"] == 0
|
||||
assert data["total"] == 0
|
||||
|
||||
async def test_empty_when_no_unresolved_ips(self, geo_client: AsyncClient) -> None:
|
||||
"""Returns resolved=0, total=0 when geo_cache has no NULL country_code rows."""
|
||||
|
||||
@@ -842,6 +842,54 @@ class TestLookupCachedOnly:
|
||||
assert uncached.count("9.9.9.9") == 1
|
||||
|
||||
|
||||
class TestReResolveAll:
|
||||
"""Tests for :func:`~app.services.geo_service.re_resolve_all`."""
|
||||
|
||||
async def test_returns_zero_when_no_unresolved_ips(self) -> None:
|
||||
"""The service returns zero counts when there are no unresolved IPs."""
|
||||
db = MagicMock()
|
||||
session = MagicMock()
|
||||
|
||||
with patch(
|
||||
"app.services.geo_service.get_unresolved_ips",
|
||||
AsyncMock(return_value=[]),
|
||||
), patch("app.services.geo_service.lookup_batch", AsyncMock()) as mock_lookup, patch(
|
||||
"app.services.geo_service.clear_neg_cache",
|
||||
MagicMock(),
|
||||
) as mock_clear:
|
||||
result = await geo_service.re_resolve_all(db, session)
|
||||
|
||||
assert result == {"resolved": 0, "total": 0}
|
||||
mock_clear.assert_not_called()
|
||||
mock_lookup.assert_not_called()
|
||||
|
||||
async def test_clears_neg_cache_and_returns_counts(self) -> None:
|
||||
"""The service clears negative cache and returns resolved and total counts."""
|
||||
db = MagicMock()
|
||||
session = MagicMock()
|
||||
ips = ["1.1.1.1", "2.2.2.2"]
|
||||
geo_map = {
|
||||
"1.1.1.1": GeoInfo(country_code="DE", country_name="Germany", asn=None, org=None),
|
||||
"2.2.2.2": GeoInfo(country_code=None, country_name=None, asn=None, org=None),
|
||||
}
|
||||
|
||||
with patch(
|
||||
"app.services.geo_service.get_unresolved_ips",
|
||||
AsyncMock(return_value=ips),
|
||||
), patch(
|
||||
"app.services.geo_service.lookup_batch",
|
||||
AsyncMock(return_value=geo_map),
|
||||
) as mock_lookup, patch(
|
||||
"app.services.geo_service.clear_neg_cache",
|
||||
MagicMock(),
|
||||
) as mock_clear:
|
||||
result = await geo_service.re_resolve_all(db, session)
|
||||
|
||||
assert result == {"resolved": 1, "total": 2}
|
||||
mock_clear.assert_called_once()
|
||||
mock_lookup.assert_awaited_once_with(ips, session, db=db)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Bulk DB writes via executemany (Task 3)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user