diff --git a/tests/test_flow.py b/tests/test_flow.py index 7d95564..a49a29d 100644 --- a/tests/test_flow.py +++ b/tests/test_flow.py @@ -1,4 +1,6 @@ import bot +import reminders +from datetime import datetime, timedelta def _state(uid): @@ -356,6 +358,7 @@ def test_stats_runs(app): def test_admin_reminder_wizard_creates_reminder(app, monkeypatch): admin = 80001 monkeypatch.setattr(bot.config, "ADMIN_IDS", [admin]) + bot.db.set_admin_tz_offset(admin, 3) # пояс уже задан — гейт не должен мешать app.handle_message(admin, "Админка ⚙️") app.handle_message(admin, "⏰ Напоминалки") @@ -387,6 +390,7 @@ def test_admin_reminder_wizard_creates_reminder(app, monkeypatch): def test_admin_reminder_wizard_specific_recipients(app, monkeypatch): admin, other = 80003, 80004 monkeypatch.setattr(bot.config, "ADMIN_IDS", [admin, other]) + bot.db.set_admin_tz_offset(admin, 0) app.handle_message(admin, "⏰ Напоминалки") app.handle_message(admin, "➕ Добавить") @@ -406,6 +410,7 @@ def test_admin_reminder_wizard_specific_recipients(app, monkeypatch): def test_admin_reminder_delete(app, monkeypatch): admin = 80002 monkeypatch.setattr(bot.config, "ADMIN_IDS", [admin]) + bot.db.set_admin_tz_offset(admin, 0) rid = bot.db.add_reminder("Тест", "2099-01-01 09:00:00", "once", [admin], created_by=admin) app.handle_message(admin, f"напоминалка удалить {rid}") @@ -423,6 +428,7 @@ def test_admin_reminder_delete_via_picker_button(app, monkeypatch): """Удаление через кнопку «🗑 Удалить напоминание» + выбор из списка (без ввода id вручную).""" admin = 80005 monkeypatch.setattr(bot.config, "ADMIN_IDS", [admin]) + bot.db.set_admin_tz_offset(admin, 0) rid = bot.db.add_reminder("Продлить хостинг", "2099-01-01 09:00:00", "once", [admin], created_by=admin) app.handle_message(admin, "⏰ Напоминалки") @@ -432,3 +438,86 @@ def test_admin_reminder_delete_via_picker_button(app, monkeypatch): app.handle_message(admin, f"{rid}. Продлить хостинг") # клик по кнопке пикера assert _state(admin) == "FREE_CHAT" assert not bot.db.get_active_reminders() + + +def test_reminder_tz_gate_before_list(app, monkeypatch): + """Без заданного часового пояса раздел не открывается — сначала гейт.""" + admin = 80006 + monkeypatch.setattr(bot.config, "ADMIN_IDS", [admin]) + + app.handle_message(admin, "⏰ Напоминалки") + assert _state(admin) == "ADMIN_REMINDER_TZ_SETUP" + + app.handle_message(admin, "не число") # невалидный формат — остаёмся на шаге + assert _state(admin) == "ADMIN_REMINDER_TZ_SETUP" + + app.handle_message(admin, "+3") + assert _state(admin) == "FREE_CHAT" + assert bot.db.get_admin_tz_offset(admin) == 3 + + # повторный вход — пояс уже задан, гейт больше не срабатывает + app.handle_message(admin, "⏰ Напоминалки") + assert _state(admin) == "FREE_CHAT" + + +def test_reminder_creation_converts_author_local_time_to_server(app, monkeypatch): + admin = 80007 + monkeypatch.setattr(bot.config, "ADMIN_IDS", [admin]) + bot.db.set_admin_tz_offset(admin, 3) # пояс уже задан — гейт не мешает + + app.handle_message(admin, "⏰ Напоминалки") + app.handle_message(admin, "➕ Добавить") + app.handle_message(admin, "01.06.2099 09:00") # 09:00 по времени автора (UTC+3) + app.handle_message(admin, "Тест конвертации") + app.handle_message(admin, "0") + app.handle_message(admin, "Разово") + + rows = bot.db.get_active_reminders() + stored = datetime.strptime(rows[0]["remind_at"], "%Y-%m-%d %H:%M:%S") + server_offset = reminders.server_utc_offset_hours() + expected = datetime(2099, 6, 1, 9, 0) + timedelta(hours=(server_offset - 3)) + assert stored == expected + + +def test_reminder_pause_and_resume_via_picker(app, monkeypatch): + admin = 80008 + monkeypatch.setattr(bot.config, "ADMIN_IDS", [admin]) + bot.db.set_admin_tz_offset(admin, 0) + rid = bot.db.add_reminder("Продлить хостинг", "2020-01-01 09:00:00", "once", [admin], created_by=admin) + + app.handle_message(admin, "⏰ Напоминалки") + app.handle_message(admin, "⏸/▶ Пауза") + assert _state(admin) == "ADMIN_REMINDER_PAUSE_PICK" + app.handle_message(admin, f"{rid}. Продлить хостинг") + assert _state(admin) == "FREE_CHAT" + row = next(r for r in bot.db.get_active_reminders() if r["id"] == rid) + assert row["paused"] == 1 + + # напоминание давно просрочено, но на паузе — планировщик не должен его отправить + app._sent.clear() + app._check_due_reminders() + assert not app._sent + assert bot.db.get_active_reminders() # всё ещё активно (не деактивировалось) + + # возобновляем через тот же пикер + app.handle_message(admin, "⏸/▶ Пауза") + app.handle_message(admin, f"{rid}. Продлить хостинг") + row = next(r for r in bot.db.get_active_reminders() if r["id"] == rid) + assert row["paused"] == 0 + + # теперь просроченное разовое напоминание должно уйти при следующей проверке + app._check_due_reminders() + assert app._sent + assert not bot.db.get_active_reminders() # once — деактивировалось после отправки + + +def test_timezone_change_command(app, monkeypatch): + admin = 80009 + monkeypatch.setattr(bot.config, "ADMIN_IDS", [admin]) + bot.db.set_admin_tz_offset(admin, 3) + + app.handle_message(admin, "часовой пояс -5") + assert bot.db.get_admin_tz_offset(admin) == -5 + + app.handle_message(admin, "часовой пояс много") + assert bot.db.get_admin_tz_offset(admin) == -5 # невалидный ввод не поменял значение