mirror of
https://github.com/BEDOLAGA-DEV/remnawave-bedolaga-telegram-bot.git
synced 2026-01-20 11:50:27 +00:00
158 lines
5.8 KiB
Python
158 lines
5.8 KiB
Python
import json
|
|
from pathlib import Path
|
|
from types import SimpleNamespace
|
|
from unittest.mock import AsyncMock
|
|
|
|
import pytest
|
|
from fastapi import FastAPI, status
|
|
|
|
from app.config import settings
|
|
from app.services.payment_service import PaymentService
|
|
|
|
# ensure backup directory exists before importing the unified app to avoid side effects during module import
|
|
_backup_dir = Path("data/backups")
|
|
_backup_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
from app.webserver.unified_app import create_unified_app
|
|
|
|
|
|
@pytest.mark.anyio
|
|
async def test_unified_app_health_reports_features(
|
|
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
|
) -> None:
|
|
bot = AsyncMock()
|
|
dispatcher = SimpleNamespace(feed_update=AsyncMock())
|
|
payment_service = AsyncMock(spec=PaymentService)
|
|
|
|
miniapp_static_dir = tmp_path / "miniapp"
|
|
miniapp_static_dir.mkdir()
|
|
|
|
monkeypatch.setattr(settings, "WEB_API_ENABLED", True, raising=False)
|
|
monkeypatch.setattr(settings, "TRIBUTE_ENABLED", True, raising=False)
|
|
monkeypatch.setattr(settings, "WEBHOOK_URL", "https://hooks.example.com", raising=False)
|
|
monkeypatch.setattr(settings, "WEBHOOK_PATH", "/telegram-webhook", raising=False)
|
|
monkeypatch.setattr(settings, "WEBHOOK_SECRET_TOKEN", "super-secret", raising=False)
|
|
monkeypatch.setattr(settings, "BOT_RUN_MODE", "webhook", raising=False)
|
|
monkeypatch.setattr(settings, "WEBHOOK_MAX_QUEUE_SIZE", 8, raising=False)
|
|
monkeypatch.setattr(settings, "WEBHOOK_WORKERS", 1, raising=False)
|
|
monkeypatch.setattr(settings, "WEBHOOK_ENQUEUE_TIMEOUT", 0.0, raising=False)
|
|
monkeypatch.setattr(settings, "WEBHOOK_WORKER_SHUTDOWN_TIMEOUT", 1.0, raising=False)
|
|
monkeypatch.setattr(settings, "MINIAPP_STATIC_PATH", str(miniapp_static_dir), raising=False)
|
|
|
|
app = create_unified_app(
|
|
bot,
|
|
dispatcher, # type: ignore[arg-type]
|
|
payment_service,
|
|
enable_telegram_webhook=True,
|
|
)
|
|
|
|
health_route = next(
|
|
route
|
|
for route in app.routes
|
|
if getattr(route, "endpoint", None) and getattr(route.endpoint, "__name__", "") == "unified_health"
|
|
)
|
|
|
|
assert getattr(health_route, "path", None) == "/health/unified"
|
|
|
|
await app.router.startup()
|
|
try:
|
|
response = await health_route.endpoint() # type: ignore[func-returns-value]
|
|
finally:
|
|
await app.router.shutdown()
|
|
|
|
payload = json.loads(response.body.decode("utf-8")) # type: ignore[attr-defined]
|
|
|
|
assert payload["status"] == "ok"
|
|
assert payload["web_api_enabled"] is True
|
|
assert payload["bot_run_mode"] == "webhook"
|
|
assert payload["telegram_webhook"]["enabled"] is True
|
|
assert payload["telegram_webhook"]["running"] is True
|
|
assert payload["telegram_webhook"]["path"] == "/telegram-webhook"
|
|
assert payload["telegram_webhook"]["secret_configured"] is True
|
|
assert payload["payment_webhooks"]["enabled"] is True
|
|
assert payload["payment_webhooks"]["providers"]["tribute"] is True
|
|
assert payload["miniapp_static"]["mounted"] is True
|
|
assert payload["miniapp_static"]["path"].endswith("miniapp")
|
|
|
|
|
|
def _build_unified_app(monkeypatch: pytest.MonkeyPatch, docs_enabled: bool) -> FastAPI:
|
|
bot = AsyncMock()
|
|
dispatcher = SimpleNamespace(feed_update=AsyncMock())
|
|
payment_service = AsyncMock(spec=PaymentService)
|
|
|
|
monkeypatch.setattr(settings, "WEB_API_ENABLED", False, raising=False)
|
|
monkeypatch.setattr(settings, "WEB_API_DOCS_ENABLED", docs_enabled, raising=False)
|
|
monkeypatch.setattr(settings, "MINIAPP_STATIC_PATH", "miniapp", raising=False)
|
|
|
|
return create_unified_app(
|
|
bot,
|
|
dispatcher, # type: ignore[arg-type]
|
|
payment_service,
|
|
enable_telegram_webhook=False,
|
|
)
|
|
|
|
|
|
@pytest.mark.anyio
|
|
async def test_unified_app_health_path_without_admin(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
bot = AsyncMock()
|
|
dispatcher = SimpleNamespace(feed_update=AsyncMock())
|
|
payment_service = AsyncMock(spec=PaymentService)
|
|
|
|
monkeypatch.setattr(settings, "WEB_API_ENABLED", False, raising=False)
|
|
monkeypatch.setattr(settings, "MINIAPP_STATIC_PATH", "miniapp", raising=False)
|
|
|
|
app = create_unified_app(
|
|
bot,
|
|
dispatcher, # type: ignore[arg-type]
|
|
payment_service,
|
|
enable_telegram_webhook=False,
|
|
)
|
|
|
|
health_route = next(
|
|
route
|
|
for route in app.routes
|
|
if getattr(route, "endpoint", None) and getattr(route.endpoint, "__name__", "") == "unified_health"
|
|
)
|
|
|
|
assert getattr(health_route, "path", None) == "/health"
|
|
|
|
|
|
def test_unified_app_docs_disabled(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
app = _build_unified_app(monkeypatch, docs_enabled=False)
|
|
|
|
assert app.docs_url is None
|
|
assert app.redoc_url is None
|
|
assert app.openapi_url is None
|
|
|
|
registered_paths = {getattr(route, "path", None) for route in app.routes}
|
|
assert "/doc" not in registered_paths
|
|
|
|
|
|
@pytest.mark.anyio
|
|
async def test_unified_app_docs_enabled_with_alias(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
app = _build_unified_app(monkeypatch, docs_enabled=True)
|
|
|
|
assert app.docs_url == "/docs"
|
|
assert app.openapi_url == "/openapi.json"
|
|
|
|
alias_route = next(
|
|
(route for route in app.routes if getattr(route, "path", None) == "/doc"),
|
|
None,
|
|
)
|
|
assert alias_route is not None
|
|
assert getattr(alias_route, "include_in_schema", True) is False
|
|
|
|
redoc_route = next(
|
|
(route for route in app.routes if getattr(route, "path", None) == "/redoc"),
|
|
None,
|
|
)
|
|
assert redoc_route is not None
|
|
assert getattr(redoc_route, "include_in_schema", True) is False
|
|
|
|
response = await alias_route.endpoint() # type: ignore[func-returns-value]
|
|
assert response.status_code == status.HTTP_307_TEMPORARY_REDIRECT
|
|
assert response.headers["location"] == "/docs"
|
|
|
|
redoc_response = await redoc_route.endpoint() # type: ignore[func-returns-value]
|
|
assert b"ReDoc" in redoc_response.body # type: ignore[attr-defined]
|