/ tests / gateway / test_matrix_exec_approval.py
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