fixed tests
This commit is contained in:
@@ -14,7 +14,6 @@ from app.db import init_db
|
||||
from app.main import create_app
|
||||
from app.models.history import (
|
||||
HistoryBanItem,
|
||||
HistoryListResponse,
|
||||
IpDetailResponse,
|
||||
IpTimelineEvent,
|
||||
)
|
||||
@@ -48,13 +47,26 @@ def _make_history_item(ip: str = "1.2.3.4", jail: str = "sshd") -> HistoryBanIte
|
||||
)
|
||||
|
||||
|
||||
def _make_history_list(n: int = 2) -> HistoryListResponse:
|
||||
"""Build a mock ``HistoryListResponse`` with *n* items."""
|
||||
from app.utils.pagination import create_pagination_metadata
|
||||
def _make_history_list(n: int = 2):
|
||||
"""Build a mock ``DomainHistoryList`` with *n* items."""
|
||||
from app.models.history_domain import DomainHistoryBanItem, DomainHistoryList
|
||||
|
||||
items = [_make_history_item(ip=f"1.2.3.{i}") for i in range(n)]
|
||||
pagination = create_pagination_metadata(total=n, page=1, page_size=100)
|
||||
return HistoryListResponse(items=items, pagination=pagination)
|
||||
items = [
|
||||
DomainHistoryBanItem(
|
||||
ip=f"1.2.3.{i}",
|
||||
jail="sshd",
|
||||
banned_at="2026-03-01T10:00:00+00:00",
|
||||
ban_count=3,
|
||||
failures=5,
|
||||
matches=["Mar 1 10:00:00 host sshd[123]: Failed password for root"],
|
||||
country_code="DE",
|
||||
country_name="Germany",
|
||||
asn="AS3320",
|
||||
org="Telekom",
|
||||
)
|
||||
for i in range(n)
|
||||
]
|
||||
return DomainHistoryList(items=items, total=n, page=1, page_size=100)
|
||||
|
||||
|
||||
def _make_ip_detail(ip: str = "1.2.3.4") -> IpDetailResponse:
|
||||
@@ -96,13 +108,17 @@ def _make_ip_detail(ip: str = "1.2.3.4") -> IpDetailResponse:
|
||||
@pytest.fixture
|
||||
async def history_client(tmp_path: Path) -> AsyncClient: # type: ignore[misc]
|
||||
"""Provide an authenticated ``AsyncClient`` for history endpoint tests."""
|
||||
config_dir = tmp_path / "fail2ban"
|
||||
config_dir.mkdir()
|
||||
settings = Settings(
|
||||
database_path=str(tmp_path / "history_test.db"),
|
||||
fail2ban_socket="/tmp/fake_fail2ban.sock",
|
||||
fail2ban_config_dir=str(config_dir),
|
||||
session_secret="test-history-secret-32chars-long!!",
|
||||
session_duration_minutes=60,
|
||||
timezone="UTC",
|
||||
log_level="debug",
|
||||
session_cookie_secure=False,
|
||||
)
|
||||
app = create_app(settings=settings)
|
||||
|
||||
@@ -136,9 +152,7 @@ async def history_client(tmp_path: Path) -> AsyncClient: # type: ignore[misc]
|
||||
class TestHistoryList:
|
||||
"""GET /api/history — paginated history list."""
|
||||
|
||||
async def test_returns_200_when_authenticated(
|
||||
self, history_client: AsyncClient
|
||||
) -> None:
|
||||
async def test_returns_200_when_authenticated(self, history_client: AsyncClient) -> None:
|
||||
"""Authenticated request returns HTTP 200."""
|
||||
with patch(
|
||||
"app.routers.history.history_service.list_history",
|
||||
@@ -147,9 +161,7 @@ class TestHistoryList:
|
||||
response = await history_client.get("/api/v1/history")
|
||||
assert response.status_code == 200
|
||||
|
||||
async def test_returns_401_when_unauthenticated(
|
||||
self, client: AsyncClient
|
||||
) -> None:
|
||||
async def test_returns_401_when_unauthenticated(self, client: AsyncClient) -> None:
|
||||
"""Unauthenticated request returns HTTP 401."""
|
||||
await client.post("/api/v1/setup", json=_SETUP_PAYLOAD)
|
||||
response = await client.get("/api/v1/history")
|
||||
@@ -245,9 +257,7 @@ class TestHistoryList:
|
||||
_args, kwargs = mock_fn.call_args
|
||||
assert kwargs.get("source") == "archive"
|
||||
|
||||
async def test_archive_route_forces_source_archive(
|
||||
self, history_client: AsyncClient
|
||||
) -> None:
|
||||
async def test_archive_route_forces_source_archive(self, history_client: AsyncClient) -> None:
|
||||
"""GET /api/history/archive should call list_history with source='archive'."""
|
||||
mock_fn = AsyncMock(return_value=_make_history_list(n=0))
|
||||
with patch(
|
||||
@@ -261,14 +271,16 @@ class TestHistoryList:
|
||||
|
||||
async def test_empty_result(self, history_client: AsyncClient) -> None:
|
||||
"""An empty history returns items=[] and total=0."""
|
||||
from app.utils.pagination import create_pagination_metadata
|
||||
from app.models.history_domain import DomainHistoryList
|
||||
|
||||
with patch(
|
||||
"app.routers.history.history_service.list_history",
|
||||
new=AsyncMock(
|
||||
return_value=HistoryListResponse(
|
||||
return_value=DomainHistoryList(
|
||||
items=[],
|
||||
pagination=create_pagination_metadata(total=0, page=1, page_size=100),
|
||||
total=0,
|
||||
page=1,
|
||||
page_size=100,
|
||||
)
|
||||
),
|
||||
):
|
||||
@@ -287,9 +299,7 @@ class TestHistoryList:
|
||||
class TestIpHistory:
|
||||
"""GET /api/history/{ip} — per-IP detail."""
|
||||
|
||||
async def test_returns_200_when_authenticated(
|
||||
self, history_client: AsyncClient
|
||||
) -> None:
|
||||
async def test_returns_200_when_authenticated(self, history_client: AsyncClient) -> None:
|
||||
"""Authenticated request returns HTTP 200 for a known IP."""
|
||||
with patch(
|
||||
"app.routers.history.history_service.get_ip_detail",
|
||||
@@ -298,17 +308,13 @@ class TestIpHistory:
|
||||
response = await history_client.get("/api/v1/history/1.2.3.4")
|
||||
assert response.status_code == 200
|
||||
|
||||
async def test_returns_401_when_unauthenticated(
|
||||
self, client: AsyncClient
|
||||
) -> None:
|
||||
async def test_returns_401_when_unauthenticated(self, client: AsyncClient) -> None:
|
||||
"""Unauthenticated request returns HTTP 401."""
|
||||
await client.post("/api/v1/setup", json=_SETUP_PAYLOAD)
|
||||
response = await client.get("/api/v1/history/1.2.3.4")
|
||||
assert response.status_code == 401
|
||||
|
||||
async def test_returns_404_for_unknown_ip(
|
||||
self, history_client: AsyncClient
|
||||
) -> None:
|
||||
async def test_returns_404_for_unknown_ip(self, history_client: AsyncClient) -> None:
|
||||
"""Returns 404 when the IP has no records in the database."""
|
||||
with patch(
|
||||
"app.routers.history.history_service.get_ip_detail",
|
||||
@@ -341,9 +347,7 @@ class TestIpHistory:
|
||||
assert "failures" in event
|
||||
assert "matches" in event
|
||||
|
||||
async def test_aggregation_sums_failures(
|
||||
self, history_client: AsyncClient
|
||||
) -> None:
|
||||
async def test_aggregation_sums_failures(self, history_client: AsyncClient) -> None:
|
||||
"""total_failures reflects the sum across all timeline events."""
|
||||
mock_detail = _make_ip_detail("10.0.0.1")
|
||||
mock_detail = IpDetailResponse(
|
||||
|
||||
Reference in New Issue
Block a user