feat(bot): точка входа, конфиг, главное меню, доступ для ADMIN_IDS, healthcheck
- config: pydantic-settings по подсистемам, ADMIN_IDS через запятую - texts.yaml + валидация при старте (лишний/пропущенный ключ — ошибка сразу) - меню: reply-клавиатура разделов (Участники — только админам), инлайн «Назад»/«Отмена» с редактированием сообщения на месте, /start, /menu, /help - AccessMiddleware (outer) на сообщениях и кнопках: до #25 пускает только ADMIN_IDS, постороннему — одна фраза в сутки, устаревшие кнопки молча гасятся - heartbeat-файл + HEALTHCHECK в Dockerfile; JSON-логи - FSM пока в памяти (фабрика), хранилище в БД — в #5 - тесты на фейковой сессии aiogram через настоящий Dispatcher Refs #4 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
import asyncio
|
||||
import contextlib
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from app import health
|
||||
|
||||
|
||||
def test_missing_file_is_dead(tmp_path: Path) -> None:
|
||||
assert not health.is_alive(tmp_path / "hb", max_age=30)
|
||||
|
||||
|
||||
def test_age_decides(tmp_path: Path) -> None:
|
||||
hb = tmp_path / "hb"
|
||||
hb.touch()
|
||||
os.utime(hb, (1000, 1000))
|
||||
assert health.is_alive(hb, max_age=30, now=1029)
|
||||
assert not health.is_alive(hb, max_age=30, now=1031)
|
||||
|
||||
|
||||
async def test_heartbeat_touches_file(tmp_path: Path) -> None:
|
||||
hb = tmp_path / "hb"
|
||||
task = asyncio.create_task(health.heartbeat(hb, interval=10))
|
||||
await asyncio.sleep(0)
|
||||
assert hb.exists()
|
||||
task.cancel()
|
||||
with contextlib.suppress(asyncio.CancelledError):
|
||||
await task
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("touch", "code"), [(True, 0), (False, 1)])
|
||||
def test_cli_exit_code(tmp_path: Path, monkeypatch: pytest.MonkeyPatch, touch: bool, code: int) -> None:
|
||||
hb = tmp_path / "hb"
|
||||
if touch:
|
||||
hb.touch()
|
||||
monkeypatch.setenv("HEARTBEAT_FILE", str(hb))
|
||||
with pytest.raises(SystemExit) as exc:
|
||||
health.main()
|
||||
assert exc.value.code == code
|
||||
Reference in New Issue
Block a user