surfaces/tests/adapter/matrix/test_send_outgoing.py
Mikhail Putilovskij 716dec5dfd test(01-05): cover matrix confirm flow round trip
- assert room_id is preserved on !yes and !no callbacks
- exercise send_outgoing to confirm and cancel with user+room scope
2026-04-03 12:27:42 +03:00

158 lines
5.5 KiB
Python

from __future__ import annotations
from types import SimpleNamespace
from unittest.mock import AsyncMock
from adapter.matrix.bot import send_outgoing
from adapter.matrix.converter import from_room_event
from adapter.matrix.handlers.confirm import make_handle_cancel, make_handle_confirm
from adapter.matrix.store import get_pending_confirm, set_room_meta
from core.auth import AuthManager
from core.chat import ChatManager
from core.protocol import OutgoingUI, UIButton
from core.settings import SettingsManager
from core.store import InMemoryStore
from sdk.mock import MockPlatformClient
async def test_mat06_outgoing_ui_renders_text_with_yes_no():
client = SimpleNamespace(room_send=AsyncMock())
store = InMemoryStore()
await set_room_meta(store, "!confirm:example.org", {"matrix_user_id": "@alice:example.org"})
event = OutgoingUI(
chat_id="C7",
text="Удалить файл?",
buttons=[UIButton(label="Подтвердить", action="confirm")],
)
await send_outgoing(client, "!confirm:example.org", event, store=store)
client.room_send.assert_awaited_once()
body = client.room_send.call_args.args[2]["body"]
assert "Удалить файл?" in body
assert "!yes" in body
assert "!no" in body
assert "Подтвердить" in body
async def test_mat07_outgoing_ui_no_reaction_sent():
client = SimpleNamespace(room_send=AsyncMock())
store = InMemoryStore()
await set_room_meta(store, "!confirm:example.org", {"matrix_user_id": "@alice:example.org"})
event = OutgoingUI(
chat_id="C7",
text="Confirm action?",
buttons=[UIButton(label="OK", action="confirm", payload={"id": 1})],
)
await send_outgoing(client, "!confirm:example.org", event, store=store)
assert client.room_send.await_count == 1
assert client.room_send.call_args.args[1] == "m.room.message"
for call in client.room_send.call_args_list:
assert call.args[1] != "m.reaction"
pending = await get_pending_confirm(store, "@alice:example.org", "!confirm:example.org")
assert pending == {
"action_id": "confirm",
"description": "Confirm action?",
"payload": {"id": 1},
}
async def test_outgoing_ui_yes_round_trip_uses_user_and_room_scope():
client = SimpleNamespace(room_send=AsyncMock())
store = InMemoryStore()
platform = MockPlatformClient()
chat_mgr = ChatManager(platform, store)
auth_mgr = AuthManager(platform, store)
settings_mgr = SettingsManager(platform, store)
await set_room_meta(store, "!confirm:example.org", {"matrix_user_id": "@alice:example.org"})
await set_room_meta(store, "!other:example.org", {"matrix_user_id": "@bob:example.org"})
await send_outgoing(
client,
"!confirm:example.org",
OutgoingUI(
chat_id="C7",
text="Archive room",
buttons=[UIButton(label="Confirm", action="archive", payload={"id": 7})],
),
store=store,
)
await send_outgoing(
client,
"!other:example.org",
OutgoingUI(
chat_id="C8",
text="Keep other room",
buttons=[UIButton(label="Confirm", action="archive", payload={"id": 8})],
),
store=store,
)
callback = from_room_event(
SimpleNamespace(
sender="@alice:example.org",
body="!yes",
event_id="$yes",
msgtype="m.text",
replyto_event_id=None,
),
room_id="!confirm:example.org",
chat_id="C7",
)
result = await make_handle_confirm(store)(callback, auth_mgr, platform, chat_mgr, settings_mgr)
assert "Archive room" in result[0].text
assert await get_pending_confirm(store, "@alice:example.org", "!confirm:example.org") is None
assert await get_pending_confirm(store, "@bob:example.org", "!other:example.org") is not None
async def test_outgoing_ui_no_round_trip_uses_user_and_room_scope():
client = SimpleNamespace(room_send=AsyncMock())
store = InMemoryStore()
platform = MockPlatformClient()
chat_mgr = ChatManager(platform, store)
auth_mgr = AuthManager(platform, store)
settings_mgr = SettingsManager(platform, store)
await set_room_meta(store, "!confirm:example.org", {"matrix_user_id": "@alice:example.org"})
await set_room_meta(store, "!other:example.org", {"matrix_user_id": "@bob:example.org"})
await send_outgoing(
client,
"!confirm:example.org",
OutgoingUI(
chat_id="C7",
text="Delete room",
buttons=[UIButton(label="Confirm", action="delete", payload={"id": 7})],
),
store=store,
)
await send_outgoing(
client,
"!other:example.org",
OutgoingUI(
chat_id="C8",
text="Keep other room",
buttons=[UIButton(label="Confirm", action="archive", payload={"id": 8})],
),
store=store,
)
callback = from_room_event(
SimpleNamespace(
sender="@alice:example.org",
body="!no",
event_id="$no",
msgtype="m.text",
replyto_event_id=None,
),
room_id="!confirm:example.org",
chat_id="C7",
)
result = await make_handle_cancel(store)(callback, auth_mgr, platform, chat_mgr, settings_mgr)
assert "отменено" in result[0].text.lower()
assert await get_pending_confirm(store, "@alice:example.org", "!confirm:example.org") is None
assert await get_pending_confirm(store, "@bob:example.org", "!other:example.org") is not None