Files
takopi/tests/test_telegram_topics_command.py
T

190 lines
5.2 KiB
Python

from dataclasses import replace
from pathlib import Path
import pytest
from takopi.settings import TelegramTopicsSettings
from takopi.config import ProjectConfig, ProjectsConfig
from takopi.runners.mock import Return, ScriptRunner
from takopi.telegram.chat_sessions import ChatSessionStore
from takopi.telegram.chat_prefs import ChatPrefsStore, resolve_prefs_path
from takopi.telegram.commands.topics import (
_handle_chat_ctx_command,
_handle_chat_new_command,
_handle_ctx_command,
_handle_new_command,
_handle_topic_command,
)
from takopi.telegram.topic_state import TopicStateStore
from takopi.telegram.types import TelegramIncomingMessage
from tests.telegram_fakes import (
DEFAULT_ENGINE_ID,
FakeTransport,
_make_router,
make_cfg,
)
from takopi.transport_runtime import TransportRuntime
def _msg(
text: str,
*,
chat_id: int = 123,
message_id: int = 1,
thread_id: int | None = None,
chat_type: str | None = "private",
) -> TelegramIncomingMessage:
return TelegramIncomingMessage(
transport="telegram",
chat_id=chat_id,
message_id=message_id,
text=text,
reply_to_message_id=None,
reply_to_text=None,
sender_id=1,
thread_id=thread_id,
chat_type=chat_type,
)
def _runtime(tmp_path: Path) -> tuple[TransportRuntime, Path]:
runner = ScriptRunner([Return(answer="ok")], engine=DEFAULT_ENGINE_ID)
projects = ProjectsConfig(
projects={
"alpha": ProjectConfig(
alias="Alpha",
path=tmp_path,
worktrees_dir=Path(".worktrees"),
)
},
default_project="alpha",
)
state_path = tmp_path / "takopi.toml"
runtime = TransportRuntime(
router=_make_router(runner),
projects=projects,
config_path=state_path,
)
return runtime, state_path
@pytest.mark.anyio
async def test_ctx_command_requires_topic(tmp_path: Path) -> None:
transport = FakeTransport()
cfg = replace(
make_cfg(transport),
topics=TelegramTopicsSettings(enabled=True, scope="all"),
)
store = TopicStateStore(tmp_path / "topics.json")
msg = _msg("/ctx")
await _handle_ctx_command(
cfg,
msg,
args_text="",
store=store,
resolved_scope="all",
scope_chat_ids=frozenset({msg.chat_id}),
)
text = transport.send_calls[-1]["message"].text
assert "only works inside a topic" in text
@pytest.mark.anyio
async def test_chat_ctx_command_sets_binding(tmp_path: Path) -> None:
transport = FakeTransport()
runtime, state_path = _runtime(tmp_path)
cfg = replace(make_cfg(transport), runtime=runtime, session_mode="chat")
store = ChatPrefsStore(resolve_prefs_path(state_path))
msg = _msg("/ctx set alpha @dev", chat_type="private")
await _handle_chat_ctx_command(
cfg,
msg,
args_text="set alpha @dev",
chat_prefs=store,
)
msg_show = _msg("/ctx", chat_type="private")
await _handle_chat_ctx_command(
cfg,
msg_show,
args_text="",
chat_prefs=store,
)
text = transport.send_calls[-1]["message"].text
assert "bound ctx: Alpha @dev" in text
@pytest.mark.anyio
async def test_new_command_requires_topic(tmp_path: Path) -> None:
transport = FakeTransport()
cfg = replace(
make_cfg(transport),
topics=TelegramTopicsSettings(enabled=True, scope="all"),
)
store = TopicStateStore(tmp_path / "topics.json")
msg = _msg("/new")
await _handle_new_command(
cfg,
msg,
store=store,
resolved_scope="all",
scope_chat_ids=frozenset({msg.chat_id}),
)
text = transport.send_calls[-1]["message"].text
assert "only works inside a topic" in text
@pytest.mark.anyio
async def test_chat_new_command_no_sessions(tmp_path: Path) -> None:
transport = FakeTransport()
cfg = make_cfg(transport)
store = ChatSessionStore(tmp_path / "sessions.json")
msg = _msg("/new", chat_type="private")
await _handle_chat_new_command(cfg, msg, store, session_key=None)
text = transport.send_calls[-1]["message"].text
assert "no stored sessions" in text
@pytest.mark.anyio
async def test_chat_new_command_group_clears(tmp_path: Path) -> None:
transport = FakeTransport()
cfg = make_cfg(transport)
store = ChatSessionStore(tmp_path / "sessions.json")
msg = _msg("/new", chat_type="supergroup")
await _handle_chat_new_command(cfg, msg, store, session_key=(msg.chat_id, 1))
text = transport.send_calls[-1]["message"].text
assert "cleared stored sessions for you in this chat" in text
@pytest.mark.anyio
async def test_topic_command_requires_args(tmp_path: Path) -> None:
transport = FakeTransport()
cfg = replace(
make_cfg(transport),
topics=TelegramTopicsSettings(enabled=True, scope="all"),
)
store = TopicStateStore(tmp_path / "topics.json")
msg = _msg("/topic")
await _handle_topic_command(
cfg,
msg,
args_text="",
store=store,
resolved_scope="all",
scope_chat_ids=frozenset({msg.chat_id}),
)
text = transport.send_calls[-1]["message"].text
assert "usage: /topic" in text