mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-08-07 09:13:04 +02:00
Async bot invocation -- hopefully won't have too bad of user collisions
This commit is contained in:
@@ -183,6 +183,38 @@ class TestContactMessageCLIFiltering:
|
||||
# Should NOT update contact last_contacted
|
||||
mock_contact_repo.update_last_contacted.assert_not_called()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_normal_message_schedules_bot_in_background(self):
|
||||
"""Normal messages should schedule bot execution without blocking."""
|
||||
from app.event_handlers import on_contact_message
|
||||
|
||||
def _capture_task(coro):
|
||||
coro.close()
|
||||
return MagicMock()
|
||||
|
||||
with (
|
||||
patch("app.event_handlers.MessageRepository") as mock_repo,
|
||||
patch("app.event_handlers.ContactRepository") as mock_contact_repo,
|
||||
patch("app.event_handlers.broadcast_event"),
|
||||
patch("app.event_handlers.asyncio.create_task", side_effect=_capture_task) as mock_task,
|
||||
patch("app.bot.run_bot_for_message", new_callable=AsyncMock) as mock_bot,
|
||||
):
|
||||
mock_repo.create = AsyncMock(return_value=42)
|
||||
mock_contact_repo.get_by_key_or_prefix = AsyncMock(return_value=None)
|
||||
|
||||
class MockEvent:
|
||||
payload = {
|
||||
"pubkey_prefix": "abc123def456",
|
||||
"text": "Hello, bot",
|
||||
"txt_type": 0,
|
||||
"sender_timestamp": 1700000000,
|
||||
}
|
||||
|
||||
await on_contact_message(MockEvent())
|
||||
|
||||
mock_task.assert_called_once()
|
||||
mock_bot.assert_called_once()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_normal_message_still_processed(self):
|
||||
"""Normal messages (txt_type=0) are still processed normally."""
|
||||
|
||||
@@ -495,6 +495,40 @@ class TestAckPipeline:
|
||||
class TestCreateMessageFromDecrypted:
|
||||
"""Test the shared message creation function used by both real-time and historical decryption."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_schedules_bot_in_background(self, test_db, captured_broadcasts):
|
||||
"""Bot execution is scheduled and does not block channel message persistence."""
|
||||
from app.packet_processor import create_message_from_decrypted
|
||||
|
||||
packet_id, _ = await RawPacketRepository.create(b"test_packet_bot_channel", 1700000000)
|
||||
broadcasts, mock_broadcast = captured_broadcasts
|
||||
|
||||
def _capture_task(coro):
|
||||
coro.close()
|
||||
return MagicMock()
|
||||
|
||||
with (
|
||||
patch("app.packet_processor.broadcast_event", mock_broadcast),
|
||||
patch(
|
||||
"app.packet_processor.asyncio.create_task", side_effect=_capture_task
|
||||
) as mock_task,
|
||||
patch("app.bot.run_bot_for_message", new_callable=AsyncMock) as mock_bot,
|
||||
):
|
||||
msg_id = await create_message_from_decrypted(
|
||||
packet_id=packet_id,
|
||||
channel_key="ABC123DEF456",
|
||||
sender="BotTrigger",
|
||||
message_text="Hello from channel",
|
||||
timestamp=1700000000,
|
||||
received_at=1700000001,
|
||||
trigger_bot=True,
|
||||
)
|
||||
|
||||
assert msg_id is not None
|
||||
mock_task.assert_called_once()
|
||||
mock_bot.assert_called_once()
|
||||
assert mock_bot.await_count == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_creates_message_and_broadcasts(self, test_db, captured_broadcasts):
|
||||
"""create_message_from_decrypted creates message and broadcasts correctly."""
|
||||
@@ -712,6 +746,48 @@ class TestCreateDMMessageFromDecrypted:
|
||||
FACE12_PUB = "FACE123334789E2B81519AFDBC39A3C9EB7EA3457AD367D3243597A484847E46"
|
||||
A1B2C3_PUB = "a1b2c3d3ba9f5fa8705b9845fe11cc6f01d1d49caaf4d122ac7121663c5beec7"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_schedules_bot_in_background(self, test_db, captured_broadcasts):
|
||||
"""Bot execution is scheduled and does not block DM persistence."""
|
||||
from app.decoder import DecryptedDirectMessage
|
||||
from app.packet_processor import create_dm_message_from_decrypted
|
||||
|
||||
packet_id, _ = await RawPacketRepository.create(b"test_packet_bot_dm", 1700000000)
|
||||
decrypted = DecryptedDirectMessage(
|
||||
timestamp=1700000000,
|
||||
flags=0,
|
||||
message="Hello from DM",
|
||||
dest_hash="fa",
|
||||
src_hash="a1",
|
||||
)
|
||||
broadcasts, mock_broadcast = captured_broadcasts
|
||||
|
||||
def _capture_task(coro):
|
||||
coro.close()
|
||||
return MagicMock()
|
||||
|
||||
with (
|
||||
patch("app.packet_processor.broadcast_event", mock_broadcast),
|
||||
patch(
|
||||
"app.packet_processor.asyncio.create_task", side_effect=_capture_task
|
||||
) as mock_task,
|
||||
patch("app.bot.run_bot_for_message", new_callable=AsyncMock) as mock_bot,
|
||||
):
|
||||
msg_id = await create_dm_message_from_decrypted(
|
||||
packet_id=packet_id,
|
||||
decrypted=decrypted,
|
||||
their_public_key=self.A1B2C3_PUB,
|
||||
our_public_key=self.FACE12_PUB,
|
||||
received_at=1700000001,
|
||||
outgoing=False,
|
||||
trigger_bot=True,
|
||||
)
|
||||
|
||||
assert msg_id is not None
|
||||
mock_task.assert_called_once()
|
||||
mock_bot.assert_called_once()
|
||||
assert mock_bot.await_count == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_creates_dm_message_and_broadcasts(self, test_db, captured_broadcasts):
|
||||
"""create_dm_message_from_decrypted creates message and broadcasts correctly."""
|
||||
|
||||
Reference in New Issue
Block a user