from aiogram.fsm.state import State, StatesGroup from aiogram.fsm.storage.base import StorageKey from sqlalchemy import func, select from app.bot.fsm_storage import SqlStorage, key_to_str from app.db.models import FsmState from app.db.session import SessionMaker KEY = StorageKey(bot_id=42, chat_id=7, user_id=7) class Flow(StatesGroup): name = State() async def test_state_and_data_survive_a_new_storage(sessions: SessionMaker) -> None: first = SqlStorage(sessions) await first.set_state(KEY, Flow.name) await first.set_data(KEY, {"path": "services/a", "page": 2}) # A fresh storage on the same DB = the bot after a restart second = SqlStorage(sessions) assert await second.get_state(KEY) == Flow.name.state assert await second.get_data(KEY) == {"path": "services/a", "page": 2} async def test_unknown_key_is_empty(sessions: SessionMaker) -> None: storage = SqlStorage(sessions) assert await storage.get_state(KEY) is None assert await storage.get_data(KEY) == {} async def test_cleared_state_removes_row(sessions: SessionMaker) -> None: storage = SqlStorage(sessions) await storage.set_state(KEY, "x") await storage.set_data(KEY, {"a": 1}) await storage.set_state(KEY, None) await storage.set_data(KEY, {}) await storage.close() async with sessions() as s: assert await s.scalar(select(func.count()).select_from(FsmState)) == 0 def test_key_includes_every_part() -> None: key = StorageKey(bot_id=1, chat_id=2, user_id=3, thread_id=4, business_connection_id="b", destiny="d") assert key_to_str(key) == "1:2:3:4:b:d" assert key_to_str(KEY) == "42:7:7:::default"