test_matrix_exec_approval.py
1 import types 2 3 import pytest 4 from unittest.mock import AsyncMock, patch 5 6 from gateway.config import PlatformConfig 7 8 9 class TestMatrixExecApprovalReactions: 10 @pytest.mark.asyncio 11 async def test_send_exec_approval_registers_prompt_and_seeds_reactions(self, monkeypatch): 12 monkeypatch.setenv("MATRIX_ALLOWED_USERS", "@liizfq:liizfq.top") 13 from gateway.platforms.matrix import MatrixAdapter 14 15 adapter = MatrixAdapter(PlatformConfig(enabled=True, token="tok", extra={"homeserver": "https://matrix.example.org"})) 16 adapter._client = types.SimpleNamespace() 17 adapter.send = AsyncMock(return_value=types.SimpleNamespace(success=True, message_id="$evt1")) 18 adapter._send_reaction = AsyncMock(return_value="$r") 19 20 result = await adapter.send_exec_approval( 21 chat_id="!room:example.org", 22 command="rm -rf /tmp/test", 23 session_key="sess-1", 24 description="dangerous", 25 ) 26 27 assert result.success is True 28 assert adapter._approval_prompt_by_session["sess-1"] == "$evt1" 29 assert adapter._approval_prompts_by_event["$evt1"].session_key == "sess-1" 30 assert adapter._send_reaction.await_count == 2 31 emojis = [call.args[2] for call in adapter._send_reaction.await_args_list] 32 assert emojis == ["✅", "❎"] 33 34 @pytest.mark.asyncio 35 async def test_reaction_resolves_pending_approval(self, monkeypatch): 36 monkeypatch.setenv("MATRIX_ALLOWED_USERS", "@liizfq:liizfq.top") 37 from gateway.platforms.matrix import MatrixAdapter, _MatrixApprovalPrompt 38 39 adapter = MatrixAdapter(PlatformConfig(enabled=True, token="tok", extra={"homeserver": "https://matrix.example.org"})) 40 # Resolve user_id so _is_self_sender doesn't defensively drop all traffic (#15763). 41 adapter._user_id = "@bot:example.org" 42 adapter._approval_prompts_by_event["$target"] = _MatrixApprovalPrompt( 43 session_key="sess-1", chat_id="!room:example.org", message_id="$target" 44 ) 45 adapter._approval_prompt_by_session["sess-1"] = "$target" 46 47 content = {"m.relates_to": {"event_id": "$target", "key": "✅"}} 48 event = types.SimpleNamespace( 49 sender="@liizfq:liizfq.top", 50 event_id="$react1", 51 room_id="!room:example.org", 52 content=content, 53 ) 54 55 with patch("tools.approval.resolve_gateway_approval", return_value=1) as mock_resolve: 56 await adapter._on_reaction(event) 57 58 mock_resolve.assert_called_once_with("sess-1", "once") 59 assert "$target" not in adapter._approval_prompts_by_event 60 assert "sess-1" not in adapter._approval_prompt_by_session