DealDocumentScreening/tests/unit/test_bot_profile.py

99 lines
3.3 KiB
Python

"""Bot /profile command unit tests (ticket 005).
- ApiClient.get_profile contract against GET /api/v1/me/profile (respx)
- _format_profile pretty-printer (pure function)
The bot stays HTTP-thin; test_bot_boundary.py enforces no direct DB access.
"""
from __future__ import annotations
import httpx
import pytest
import respx
from contract_check.bot.client import ApiClient, ApiError
from contract_check.bot.config import BotSettings
from contract_check.bot.handlers import _format_profile
BASE = "http://api:8000"
_FAKE_JWT = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDAiLCJ0ZWxlZ3JhbV9pZCI6NDIsInR5cGUiOiJhY2Nlc3MiLCJleHAiOjk5OTk5OTk5OTksImlhdCI6MSwiYXVkIjoiY29udHJhY3QtY2hlY2sifQ.test-signature"
def _client() -> ApiClient:
c = ApiClient(BotSettings(bot_token="123:abc", api_url=BASE, bot_service_token="secret-token"))
c._client = httpx.AsyncClient(base_url=BASE)
return c
@respx.mock
async def test_get_profile_returns_body() -> None:
api = _client()
api._token_cache[42] = _FAKE_JWT
route = respx.get(f"{BASE}/api/v1/me/profile").mock(
return_value=httpx.Response(
200,
json={
"language": "ru",
"timezone": "Europe/Minsk",
"notif_prefs": {
"report_ready": True,
"security": False,
"marketing": False,
},
"dashboard_prefs": {
"severity_filter": "all",
"per_page": 10,
"density": "comfortable",
},
},
)
)
body = await api.get_profile(42, "cid")
assert route.called
assert body["language"] == "ru"
assert body["notif_prefs"]["security"] is False
await api.aclose()
@respx.mock
async def test_get_profile_raises_on_error() -> None:
api = _client()
api._token_cache[42] = _FAKE_JWT
respx.get(f"{BASE}/api/v1/me/profile").mock(
return_value=httpx.Response(500, json={"detail": "boom"})
)
with pytest.raises(ApiError):
await api.get_profile(42, "cid")
await api.aclose()
class TestFormatProfile:
def test_full_profile(self) -> None:
text = _format_profile(
{
"language": "ru",
"timezone": "Europe/Minsk",
"notif_prefs": {
"report_ready": True,
"security": False,
"marketing": False,
},
"dashboard_prefs": {"per_page": 10},
}
)
assert "Русский" in text
assert "Europe/Minsk" in text
assert "Отчёты готовы: ✔" in text
assert "Безопасность: ✘" in text
assert "Маркетинг: ✘" in text
assert "веб-интерфейс" in text
def test_defaults_when_unset(self) -> None:
text = _format_profile({"language": None, "timezone": None, "notif_prefs": {}})
assert "не выбран" in text
# Missing toggles render as off.
assert "Отчёты готовы: ✘" in text
def test_belarusian_language_label(self) -> None:
text = _format_profile({"language": "be"})
assert "Беларуская" in text