Files
miband-bot/tests/test_bot_ui.py
T
2026-05-24 21:53:17 +03:00

117 lines
3.6 KiB
Python

# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright (C) 2026 Alexey
import asyncio
import json
from pathlib import Path
from unittest.mock import AsyncMock
import pytest
import miband_tracker.bot.app as bot_app
from miband_tracker.config import Settings
from miband_tracker.sync import SyncResult
class FakeUser:
id = 123
class FakeUpdate:
effective_user = FakeUser()
message = object()
callback_query = None
def test_service_menu_does_not_expose_invites_or_second_user() -> None:
keyboard = bot_app.more_keyboard()
labels = [
button.text
for row in keyboard.inline_keyboard
for button in row
]
rendered = "\n".join([*labels, bot_app.more_text()])
assert "Принять приглашения" not in rendered
assert "Приглашения" not in rendered
assert "втор" not in rendered.lower()
@pytest.mark.asyncio
async def test_cmd_start_without_token_shows_onboarding(monkeypatch: pytest.MonkeyPatch) -> None:
update = FakeUpdate()
context = object()
show_onboarding = AsyncMock()
show_main_menu = AsyncMock()
monkeypatch.setattr(bot_app, "is_allowed", lambda _: True)
monkeypatch.setattr(bot_app, "has_xiaomi_token", lambda: False)
monkeypatch.setattr(bot_app, "safe_delete", AsyncMock())
monkeypatch.setattr(bot_app, "show_onboarding", show_onboarding)
monkeypatch.setattr(bot_app, "show_main_menu", show_main_menu)
await bot_app.cmd_start(update, context)
show_onboarding.assert_awaited_once_with(update, context, force_new=True)
show_main_menu.assert_not_awaited()
@pytest.mark.asyncio
async def test_start_xiaomi_login_saves_token_syncs_and_opens_menu(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
update = FakeUpdate()
context = object()
token_path = tmp_path / "token_123.json"
class FakeToken:
def model_dump(self):
return {
"user_id": "456",
"c_user_id": "",
"service_token": "service",
"ssecurity": "sec",
"pass_token": "pass",
"device_id": "device",
}
class FakeAuth:
async def login_qr(self, *, qr_callback, max_wait):
await qr_callback("https://example.test/qr.png", "https://example.test/login")
return FakeToken()
async def close(self):
return None
settings = Settings(
data_dir=tmp_path,
db_path=tmp_path / "miband.db",
status_path=tmp_path / "status.json",
bot_state_db_path=tmp_path / "fitness_bot_state.db",
telegram_bot_token="token",
telegram_allowed_user_id=123,
sync_interval=900,
query_duration=2,
enable_fds_sleep_details=True,
)
run_sync = AsyncMock(return_value=SyncResult(True, user_id=123))
show_main_menu = AsyncMock()
monkeypatch.setattr(bot_app, "SETTINGS", settings)
monkeypatch.setattr(bot_app, "ALLOWED_USER_ID", 123)
monkeypatch.setattr(bot_app, "AUTH_LOCK", asyncio.Lock())
monkeypatch.setattr(bot_app, "SYNC_LOCK", asyncio.Lock())
monkeypatch.setattr(bot_app, "XiaomiAuth", FakeAuth)
monkeypatch.setattr(bot_app, "update_menu", AsyncMock())
monkeypatch.setattr(bot_app, "run_sync", run_sync)
monkeypatch.setattr(bot_app, "show_main_menu", show_main_menu)
await bot_app.start_xiaomi_login(update, context)
data = json.loads(token_path.read_text(encoding="utf-8"))
assert data["user_id"] == "456"
assert data["service_token"] == "service"
run_sync.assert_awaited_once_with(123, settings)
show_main_menu.assert_awaited_once_with(update, context)