kin: BATON-008-backend_dev
This commit is contained in:
parent
36087c3d9e
commit
fde7f57a7a
5 changed files with 48 additions and 20 deletions
|
|
@ -22,6 +22,7 @@ os.environ.setdefault("WEBHOOK_SECRET", "test-webhook-secret")
|
|||
os.environ.setdefault("WEBHOOK_URL", "https://example.com/api/webhook/telegram")
|
||||
os.environ.setdefault("FRONTEND_ORIGIN", "http://localhost:3000")
|
||||
os.environ.setdefault("ADMIN_TOKEN", "test-admin-token")
|
||||
os.environ.setdefault("ADMIN_CHAT_ID", "5694335584")
|
||||
|
||||
# ── 2. aiosqlite monkey-patch ────────────────────────────────────────────────
|
||||
import aiosqlite
|
||||
|
|
@ -69,14 +70,20 @@ def temp_db():
|
|||
|
||||
# ── 5. App client factory ────────────────────────────────────────────────────
|
||||
|
||||
def make_app_client():
|
||||
def make_app_client(capture_send_requests: list | None = None):
|
||||
"""
|
||||
Async context manager that:
|
||||
1. Assigns a fresh temp-file DB path
|
||||
2. Mocks Telegram setWebhook, sendMessage, answerCallbackQuery, editMessageText
|
||||
3. Runs the FastAPI lifespan (startup → test → shutdown)
|
||||
4. Yields an httpx.AsyncClient wired to the app
|
||||
|
||||
Args:
|
||||
capture_send_requests: if provided, each sendMessage request body (dict) is
|
||||
appended to this list, enabling HTTP-level assertions on chat_id, text, etc.
|
||||
"""
|
||||
import json as _json
|
||||
|
||||
tg_set_url = f"https://api.telegram.org/bot{config.BOT_TOKEN}/setWebhook"
|
||||
send_url = f"https://api.telegram.org/bot{config.BOT_TOKEN}/sendMessage"
|
||||
get_me_url = f"https://api.telegram.org/bot{config.BOT_TOKEN}/getMe"
|
||||
|
|
@ -95,9 +102,18 @@ def make_app_client():
|
|||
mock_router.post(tg_set_url).mock(
|
||||
return_value=httpx.Response(200, json={"ok": True, "result": True})
|
||||
)
|
||||
mock_router.post(send_url).mock(
|
||||
return_value=httpx.Response(200, json={"ok": True})
|
||||
)
|
||||
if capture_send_requests is not None:
|
||||
def _capture_send(request: httpx.Request) -> httpx.Response:
|
||||
try:
|
||||
capture_send_requests.append(_json.loads(request.content))
|
||||
except Exception:
|
||||
pass
|
||||
return httpx.Response(200, json={"ok": True})
|
||||
mock_router.post(send_url).mock(side_effect=_capture_send)
|
||||
else:
|
||||
mock_router.post(send_url).mock(
|
||||
return_value=httpx.Response(200, json={"ok": True})
|
||||
)
|
||||
mock_router.post(answer_cb_url).mock(
|
||||
return_value=httpx.Response(200, json={"ok": True})
|
||||
)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ os.environ.setdefault("WEBHOOK_SECRET", "test-webhook-secret")
|
|||
os.environ.setdefault("WEBHOOK_URL", "https://example.com/api/webhook/telegram")
|
||||
os.environ.setdefault("FRONTEND_ORIGIN", "http://localhost:3000")
|
||||
os.environ.setdefault("ADMIN_TOKEN", "test-admin-token")
|
||||
os.environ.setdefault("ADMIN_CHAT_ID", "5694335584")
|
||||
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
|
|
@ -167,20 +168,23 @@ async def test_auth_register_422_short_password():
|
|||
|
||||
@pytest.mark.asyncio
|
||||
async def test_auth_register_sends_notification_to_admin():
|
||||
"""Registration triggers send_registration_notification with correct data."""
|
||||
calls: list[dict] = []
|
||||
"""Registration triggers real HTTP sendMessage to ADMIN_CHAT_ID with correct login/email."""
|
||||
from backend import config as _cfg
|
||||
|
||||
async def _capture(reg_id, login, email, created_at):
|
||||
calls.append({"reg_id": reg_id, "login": login, "email": email})
|
||||
captured: list[dict] = []
|
||||
async with make_app_client(capture_send_requests=captured) as client:
|
||||
resp = await client.post("/api/auth/register", json=_VALID_PAYLOAD)
|
||||
assert resp.status_code == 201
|
||||
await asyncio.sleep(0)
|
||||
|
||||
async with make_app_client() as client:
|
||||
with patch("backend.telegram.send_registration_notification", side_effect=_capture):
|
||||
await client.post("/api/auth/register", json=_VALID_PAYLOAD)
|
||||
await asyncio.sleep(0)
|
||||
|
||||
assert len(calls) == 1, f"Expected 1 notification call, got {len(calls)}"
|
||||
assert calls[0]["login"] == _VALID_PAYLOAD["login"]
|
||||
assert calls[0]["email"] == _VALID_PAYLOAD["email"]
|
||||
admin_chat_id = str(_cfg.ADMIN_CHAT_ID)
|
||||
admin_msgs = [r for r in captured if str(r.get("chat_id")) == admin_chat_id]
|
||||
assert len(admin_msgs) >= 1, (
|
||||
f"Expected sendMessage to ADMIN_CHAT_ID={admin_chat_id!r}, captured: {captured}"
|
||||
)
|
||||
text = admin_msgs[0].get("text", "")
|
||||
assert _VALID_PAYLOAD["login"] in text, f"Expected login in text: {text!r}"
|
||||
assert _VALID_PAYLOAD["email"] in text, f"Expected email in text: {text!r}"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue