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

@@ -16,14 +16,12 @@ Bugs covered:
from __future__ import annotations
import inspect
import json
import time
from pathlib import Path
from typing import Any
from unittest.mock import AsyncMock, patch
import aiosqlite
import pytest
# ── Bug 1 ─────────────────────────────────────────────────────────────────
@@ -43,17 +41,13 @@ class TestHistoryOriginParameter:
"the router passes origin=… which would cause a TypeError"
)
async def test_list_history_forwards_origin_to_repo(
self, tmp_path: Path
) -> None:
async def test_list_history_forwards_origin_to_repo(self, tmp_path: Path) -> None:
"""``list_history(origin='blocklist')`` must forward origin to the DB repo."""
from app.services import history_service
db_path = str(tmp_path / "f2b.db")
async with aiosqlite.connect(db_path) as db:
await db.execute(
"CREATE TABLE jails (name TEXT, enabled INTEGER DEFAULT 1)"
)
await db.execute("CREATE TABLE jails (name TEXT, enabled INTEGER DEFAULT 1)")
await db.execute(
"CREATE TABLE bans "
"(jail TEXT, ip TEXT, timeofban INTEGER, bantime INTEGER, "
@@ -70,16 +64,14 @@ class TestHistoryOriginParameter:
await db.commit()
with patch(
"app.services.history_service.get_fail2ban_db_path",
"app.services.history_service._get_fail2ban_db_path",
new=AsyncMock(return_value=db_path),
):
result = await history_service.list_history(
"fake_socket", origin="blocklist"
)
result = await history_service.list_history("fake_socket", origin="blocklist")
assert all(
item.jail == "blocklist-import" for item in result.items
), "origin='blocklist' must filter to blocklist-import jail only"
assert all(item.jail == "blocklist-import" for item in result.items), (
"origin='blocklist' must filter to blocklist-import jail only"
)
# -- Repository layer --
@@ -88,22 +80,15 @@ class TestHistoryOriginParameter:
from app.repositories import fail2ban_db_repo
sig = inspect.signature(fail2ban_db_repo.get_history_page)
assert "origin" in sig.parameters, (
"get_history_page() is missing the 'origin' parameter"
)
assert "origin" in sig.parameters, "get_history_page() is missing the 'origin' parameter"
async def test_get_history_page_filters_by_origin(
self, tmp_path: Path
) -> None:
async def test_get_history_page_filters_by_origin(self, tmp_path: Path) -> None:
"""``get_history_page(origin='selfblock')`` excludes blocklist-import."""
from app.repositories import fail2ban_db_repo
db_path = str(tmp_path / "f2b.db")
async with aiosqlite.connect(db_path) as db:
await db.execute(
"CREATE TABLE bans "
"(jail TEXT, ip TEXT, timeofban INTEGER, bancount INTEGER, data TEXT)"
)
await db.execute("CREATE TABLE bans (jail TEXT, ip TEXT, timeofban INTEGER, bancount INTEGER, data TEXT)")
await db.executemany(
"INSERT INTO bans VALUES (?, ?, ?, ?, ?)",
[
@@ -114,9 +99,7 @@ class TestHistoryOriginParameter:
)
await db.commit()
rows, total = await fail2ban_db_repo.get_history_page(
db_path=db_path, origin="selfblock"
)
rows, total = await fail2ban_db_repo.get_history_page(db_path=db_path, origin="selfblock")
assert total == 2
assert all(r.jail != "blocklist-import" for r in rows)
@@ -132,16 +115,11 @@ class TestJailConfigImports:
"""The module must successfully import ``_get_active_jail_names``."""
import app.services.jail_config_service as mod
assert hasattr(mod, "_get_active_jail_names") or callable(
getattr(mod, "_get_active_jail_names", None)
), (
"_get_active_jail_names is not available in jail_config_service — "
"any call site will raise NameError → 500"
assert hasattr(mod, "_get_active_jail_names") or callable(getattr(mod, "_get_active_jail_names", None)), (
"_get_active_jail_names is not available in jail_config_service — any call site will raise NameError → 500"
)
async def test_list_inactive_jails_does_not_raise_name_error(
self, tmp_path: Path
) -> None:
async def test_list_inactive_jails_does_not_raise_name_error(self, tmp_path: Path) -> None:
"""``list_inactive_jails`` must not crash with NameError."""
from app.services import jail_config_service
@@ -153,9 +131,7 @@ class TestJailConfigImports:
"app.services.jail_config_service._get_active_jail_names",
new=AsyncMock(return_value=set()),
):
result = await jail_config_service.list_inactive_jails(
config_dir, "/fake/socket"
)
result = await jail_config_service.list_inactive_jails(config_dir, "/fake/socket")
assert result.total >= 0
@@ -172,8 +148,7 @@ class TestFilterConfigImports:
import app.services.filter_config_service as mod
assert hasattr(mod, "_parse_jails_sync"), (
"_parse_jails_sync is not available in filter_config_service — "
"list_filters() will raise NameError → 500"
"_parse_jails_sync is not available in filter_config_service — list_filters() will raise NameError → 500"
)
async def test_get_active_jail_names_is_available(self) -> None:
@@ -185,9 +160,7 @@ class TestFilterConfigImports:
"list_filters() will raise NameError → 500"
)
async def test_list_filters_does_not_raise_name_error(
self, tmp_path: Path
) -> None:
async def test_list_filters_does_not_raise_name_error(self, tmp_path: Path) -> None:
"""``list_filters`` must not crash with NameError."""
from app.services import filter_config_service
@@ -196,9 +169,7 @@ class TestFilterConfigImports:
filter_d.mkdir(parents=True)
# Create a minimal filter file so _parse_filters_sync has something to scan.
(filter_d / "sshd.conf").write_text(
"[Definition]\nfailregex = ^Failed password\n"
)
(filter_d / "sshd.conf").write_text("[Definition]\nfailregex = ^Failed password\n")
with (
patch(
@@ -210,9 +181,7 @@ class TestFilterConfigImports:
new=AsyncMock(return_value=set()),
),
):
result = await filter_config_service.list_filters(
config_dir, "/fake/socket"
)
result = await filter_config_service.list_filters(config_dir, "/fake/socket")
assert result.total >= 0
@@ -226,9 +195,9 @@ class TestServiceStatusBanguiVersion:
async def test_online_response_contains_bangui_version(self) -> None:
"""The returned model must contain the ``bangui_version`` field."""
import app
from app.models.server import ServerStatus
from app.services import health_service
import app
online_status = ServerStatus(
online=True,
@@ -256,15 +225,13 @@ class TestServiceStatusBanguiVersion:
probe_fn=AsyncMock(return_value=online_status),
)
assert result.version == app.__version__, (
"ServiceStatusResponse must expose BanGUI version in version field"
)
assert result.version == app.__version__, "ServiceStatusResponse must expose BanGUI version in version field"
async def test_offline_response_contains_bangui_version(self) -> None:
"""Even when fail2ban is offline, ``bangui_version`` must be present."""
import app
from app.models.server import ServerStatus
from app.services import health_service
import app
offline_status = ServerStatus(online=False)