fixed tests

This commit is contained in:
2026-05-15 20:41:05 +02:00
parent 96ce516ecf
commit 77df5d5d65
50 changed files with 1482 additions and 5089 deletions

View File

@@ -84,9 +84,7 @@ def _make_import_result() -> ImportRunResult:
def _make_log_response() -> ImportLogListResponse:
return ImportLogListResponse(
items=[], total=0, page=1, page_size=50
)
return ImportLogListResponse(items=[], total=0, page=1, page_size=50)
def _make_preview() -> PreviewResponse:
@@ -106,13 +104,17 @@ def _make_preview() -> PreviewResponse:
@pytest.fixture
async def bl_client(tmp_path: Path) -> AsyncClient: # type: ignore[misc]
"""Provide an authenticated AsyncClient for blocklist endpoint tests."""
config_dir = tmp_path / "fail2ban"
config_dir.mkdir()
settings = Settings(
database_path=str(tmp_path / "bl_router_test.db"),
fail2ban_socket="/tmp/fake_fail2ban.sock",
session_secret="test-bl-secret",
fail2ban_config_dir=str(config_dir),
session_secret="test-bl-secret-that-is-long-enough!!",
session_duration_minutes=60,
timezone="UTC",
log_level="debug",
session_cookie_secure=False,
)
app = create_app(settings=settings)
@@ -127,8 +129,13 @@ async def bl_client(tmp_path: Path) -> AsyncClient: # type: ignore[misc]
scheduler_stub.get_job = MagicMock(return_value=None)
app.state.scheduler = scheduler_stub
# Initialize GeoCache (normally done in lifespan handler)
from app.services.geo_cache import GeoCache
app.state.geo_cache = GeoCache()
transport = ASGITransport(app=app)
async with AsyncClient(transport=transport, base_url="http://test") as ac:
async with AsyncClient(transport=transport, base_url="http://test", headers={"X-BanGUI-Request": "1"}) as ac:
resp = await ac.post("/api/v1/setup", json=_SETUP_PAYLOAD)
assert resp.status_code == 201
@@ -277,12 +284,15 @@ class TestDeleteBlocklist:
class TestPreviewBlocklist:
async def test_preview_returns_200(self, bl_client: AsyncClient) -> None:
"""GET /api/blocklists/1/preview returns 200 for existing source."""
with patch(
"app.routers.blocklist.blocklist_service.get_source",
new=AsyncMock(return_value=_make_source()),
), patch(
"app.routers.blocklist.blocklist_service.preview_source",
new=AsyncMock(return_value=_make_preview()),
with (
patch(
"app.routers.blocklist.blocklist_service.get_source",
new=AsyncMock(return_value=_make_source()),
),
patch(
"app.routers.blocklist.blocklist_service.preview_source",
new=AsyncMock(return_value=_make_preview()),
),
):
resp = await bl_client.get("/api/v1/blocklists/1/preview")
assert resp.status_code == 200
@@ -296,28 +306,32 @@ class TestPreviewBlocklist:
resp = await bl_client.get("/api/v1/blocklists/999/preview")
assert resp.status_code == 404
async def test_preview_returns_502_on_download_error(
self, bl_client: AsyncClient
) -> None:
"""GET /api/blocklists/1/preview returns 502 when URL is unreachable."""
with patch(
"app.routers.blocklist.blocklist_service.get_source",
new=AsyncMock(return_value=_make_source()),
), patch(
"app.routers.blocklist.blocklist_service.preview_source",
new=AsyncMock(side_effect=ValueError("Connection refused")),
async def test_preview_returns_400_on_download_error(self, bl_client: AsyncClient) -> None:
"""GET /api/blocklists/1/preview returns 400 when URL is unreachable."""
with (
patch(
"app.routers.blocklist.blocklist_service.get_source",
new=AsyncMock(return_value=_make_source()),
),
patch(
"app.routers.blocklist.blocklist_service.preview_source",
new=AsyncMock(side_effect=ValueError("Connection refused")),
),
):
resp = await bl_client.get("/api/v1/blocklists/1/preview")
assert resp.status_code == 502
assert resp.status_code == 400
async def test_preview_response_shape(self, bl_client: AsyncClient) -> None:
"""Preview response has entries, valid_count, skipped_count, total_lines."""
with patch(
"app.routers.blocklist.blocklist_service.get_source",
new=AsyncMock(return_value=_make_source()),
), patch(
"app.routers.blocklist.blocklist_service.preview_source",
new=AsyncMock(return_value=_make_preview()),
with (
patch(
"app.routers.blocklist.blocklist_service.get_source",
new=AsyncMock(return_value=_make_source()),
),
patch(
"app.routers.blocklist.blocklist_service.preview_source",
new=AsyncMock(return_value=_make_preview()),
),
):
resp = await bl_client.get("/api/v1/blocklists/1/preview")
body = resp.json()
@@ -383,9 +397,7 @@ class TestGetSchedule:
assert "next_run_at" in body
assert "last_run_at" in body
async def test_schedule_response_includes_last_run_errors(
self, bl_client: AsyncClient
) -> None:
async def test_schedule_response_includes_last_run_errors(self, bl_client: AsyncClient) -> None:
"""GET /api/blocklists/schedule includes last_run_errors field."""
info_with_errors = ScheduleInfo(
config=ScheduleConfig(
@@ -457,15 +469,18 @@ class TestImportLog:
assert resp.status_code == 200
async def test_log_response_shape(self, bl_client: AsyncClient) -> None:
"""Log response has items, total, page, page_size."""
"""Log response has items and pagination metadata."""
resp = await bl_client.get("/api/v1/blocklists/log")
body = resp.json()
for key in ("items", "total", "page", "page_size"):
assert key in body
assert "items" in body
assert "pagination" in body
pagination = body["pagination"]
for key in ("page", "page_size", "total", "total_pages", "has_next_page", "has_prev_page"):
assert key in pagination
async def test_log_empty_when_no_runs(self, bl_client: AsyncClient) -> None:
"""Log returns empty items list when no import runs have occurred."""
resp = await bl_client.get("/api/v1/blocklists/log")
body = resp.json()
assert body["total"] == 0
assert body["pagination"]["total"] == 0
assert body["items"] == []