540a7fce05
检测与测试前自动持久化 Token/Chat ID;getUpdates 清除 Webhook 并返回具体 API 错误;恢复 NOTIFY 分项开关与免密 reveal。
167 lines
5.1 KiB
Python
167 lines
5.1 KiB
Python
"""Tests for Telegram settings endpoints and notify toggle hot-reload."""
|
|
|
|
from unittest.mock import AsyncMock, MagicMock, patch
|
|
|
|
import pytest
|
|
from fastapi import HTTPException
|
|
|
|
from server.config import settings
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_telegram_test_400_when_token_missing():
|
|
from server.api.settings import telegram_test_send
|
|
|
|
settings.TELEGRAM_BOT_TOKEN = ""
|
|
settings.TELEGRAM_CHAT_ID = ""
|
|
admin = MagicMock()
|
|
|
|
with pytest.raises(HTTPException) as exc:
|
|
await telegram_test_send(admin=admin)
|
|
assert exc.value.status_code == 400
|
|
assert "TELEGRAM_BOT_TOKEN" in exc.value.detail
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_telegram_test_400_when_chat_id_missing():
|
|
from server.api.settings import telegram_test_send
|
|
|
|
settings.TELEGRAM_BOT_TOKEN = "123456:ABC"
|
|
settings.TELEGRAM_CHAT_ID = ""
|
|
admin = MagicMock()
|
|
|
|
with pytest.raises(HTTPException) as exc:
|
|
await telegram_test_send(admin=admin)
|
|
assert exc.value.status_code == 400
|
|
assert "TELEGRAM_CHAT_ID" in exc.value.detail
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_telegram_test_surfaces_api_error():
|
|
from server.api.settings import telegram_test_send
|
|
|
|
settings.TELEGRAM_BOT_TOKEN = "123456:ABC"
|
|
settings.TELEGRAM_CHAT_ID = "999"
|
|
admin = MagicMock()
|
|
|
|
mock_resp = MagicMock()
|
|
mock_resp.status_code = 400
|
|
mock_resp.json.return_value = {"ok": False, "description": "Bad Request: chat not found"}
|
|
|
|
mock_client = AsyncMock()
|
|
mock_client.__aenter__.return_value = mock_client
|
|
mock_client.__aexit__.return_value = None
|
|
mock_client.post = AsyncMock(return_value=mock_resp)
|
|
|
|
with patch("httpx.AsyncClient", return_value=mock_client):
|
|
with pytest.raises(HTTPException) as exc:
|
|
await telegram_test_send(admin=admin)
|
|
|
|
assert exc.value.status_code == 502
|
|
assert "chat not found" in exc.value.detail
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_telegram_chats_surfaces_api_error_when_ok_false():
|
|
from server.api.settings import telegram_get_chats
|
|
|
|
settings.TELEGRAM_BOT_TOKEN = "123456:ABC"
|
|
admin = MagicMock()
|
|
|
|
wh_resp = MagicMock()
|
|
wh_resp.status_code = 200
|
|
wh_resp.json.return_value = {"ok": True, "result": {"url": ""}}
|
|
|
|
updates_resp = MagicMock()
|
|
updates_resp.status_code = 200
|
|
updates_resp.json.return_value = {"ok": False, "description": "Unauthorized"}
|
|
|
|
mock_client = AsyncMock()
|
|
mock_client.__aenter__.return_value = mock_client
|
|
mock_client.__aexit__.return_value = None
|
|
mock_client.get = AsyncMock(side_effect=[wh_resp, updates_resp])
|
|
mock_client.post = AsyncMock()
|
|
|
|
with patch("httpx.AsyncClient", return_value=mock_client):
|
|
with pytest.raises(HTTPException) as exc:
|
|
await telegram_get_chats(admin=admin)
|
|
|
|
assert exc.value.status_code == 502
|
|
assert "Unauthorized" in exc.value.detail
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_telegram_chats_deletes_webhook_before_get_updates():
|
|
from server.api.settings import telegram_get_chats
|
|
|
|
settings.TELEGRAM_BOT_TOKEN = "123456:ABC"
|
|
admin = MagicMock()
|
|
|
|
wh_resp = MagicMock()
|
|
wh_resp.status_code = 200
|
|
wh_resp.json.return_value = {"ok": True, "result": {"url": "https://example.com/hook"}}
|
|
|
|
del_resp = MagicMock()
|
|
del_resp.json.return_value = {"ok": True}
|
|
|
|
updates_resp = MagicMock()
|
|
updates_resp.status_code = 200
|
|
updates_resp.json.return_value = {
|
|
"ok": True,
|
|
"result": [
|
|
{
|
|
"message": {
|
|
"chat": {"id": 42, "type": "private", "first_name": "Test"},
|
|
},
|
|
},
|
|
],
|
|
}
|
|
|
|
mock_client = AsyncMock()
|
|
mock_client.__aenter__.return_value = mock_client
|
|
mock_client.__aexit__.return_value = None
|
|
mock_client.get = AsyncMock(side_effect=[wh_resp, updates_resp])
|
|
mock_client.post = AsyncMock(return_value=del_resp)
|
|
|
|
with patch("httpx.AsyncClient", return_value=mock_client):
|
|
result = await telegram_get_chats(admin=admin)
|
|
|
|
assert result["count"] == 1
|
|
assert result["chats"][0]["id"] == 42
|
|
mock_client.post.assert_called_once()
|
|
call_args = mock_client.post.call_args
|
|
assert "deleteWebhook" in call_args[0][0]
|
|
assert call_args[1]["params"]["drop_pending_updates"] == "false"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_notify_toggle_put_hot_reload():
|
|
from server.api.schemas import SettingUpdatePayload
|
|
from server.api.settings import set_setting
|
|
from server.domain.models import Setting
|
|
|
|
settings.NOTIFY_ALERT_CPU = "true"
|
|
admin = MagicMock(username="admin")
|
|
request = MagicMock()
|
|
request.client.host = "127.0.0.1"
|
|
db = MagicMock()
|
|
|
|
mock_setting = Setting(key="notify_alert_cpu", value="false")
|
|
|
|
with patch("server.api.settings.SettingRepositoryImpl") as repo_cls, patch(
|
|
"server.api.settings.AuditLogRepositoryImpl"
|
|
) as audit_cls:
|
|
repo = repo_cls.return_value
|
|
repo.set = AsyncMock(return_value=mock_setting)
|
|
audit_cls.return_value.create = AsyncMock()
|
|
|
|
await set_setting(
|
|
"notify_alert_cpu",
|
|
SettingUpdatePayload(value="false"),
|
|
request,
|
|
admin,
|
|
db,
|
|
)
|
|
|
|
assert settings.NOTIFY_ALERT_CPU == "false"
|