Files
Aetheel/tests/test_base_adapter.py
Tanmay Karande 41b2f9a593 latest updates
2026-02-15 15:02:58 -05:00

201 lines
5.6 KiB
Python

"""
Tests for the Base Adapter and IncomingMessage.
"""
import pytest
from datetime import datetime, timezone
from adapters.base import BaseAdapter, IncomingMessage
# ---------------------------------------------------------------------------
# Concrete adapter for testing (implements all abstract methods)
# ---------------------------------------------------------------------------
class MockAdapter(BaseAdapter):
"""A minimal concrete adapter for testing BaseAdapter."""
def __init__(self):
super().__init__()
self.sent_messages: list[dict] = []
self._started = False
@property
def source_name(self) -> str:
return "mock"
def start(self) -> None:
self._started = True
def start_async(self) -> None:
self._started = True
def stop(self) -> None:
self._started = False
def send_message(
self,
channel_id: str,
text: str,
thread_id: str | None = None,
) -> None:
self.sent_messages.append({
"channel_id": channel_id,
"text": text,
"thread_id": thread_id,
})
# ---------------------------------------------------------------------------
# Fixtures
# ---------------------------------------------------------------------------
@pytest.fixture
def adapter():
return MockAdapter()
@pytest.fixture
def sample_message():
return IncomingMessage(
text="Hello world",
user_id="U123",
user_name="testuser",
channel_id="C456",
channel_name="general",
conversation_id="conv-789",
source="mock",
is_dm=False,
raw_event={"thread_id": "T100"},
)
# ---------------------------------------------------------------------------
# Tests: IncomingMessage
# ---------------------------------------------------------------------------
class TestIncomingMessage:
def test_create_message(self, sample_message):
assert sample_message.text == "Hello world"
assert sample_message.user_id == "U123"
assert sample_message.user_name == "testuser"
assert sample_message.channel_id == "C456"
assert sample_message.source == "mock"
assert sample_message.is_dm is False
def test_timestamp_default(self):
msg = IncomingMessage(
text="test",
user_id="U1",
user_name="user",
channel_id="C1",
channel_name="ch",
conversation_id="conv",
source="test",
is_dm=True,
)
assert msg.timestamp is not None
assert msg.timestamp.tzinfo is not None # has timezone
def test_raw_event_default(self):
msg = IncomingMessage(
text="test",
user_id="U1",
user_name="user",
channel_id="C1",
channel_name="ch",
conversation_id="conv",
source="test",
is_dm=False,
)
assert msg.raw_event == {}
# ---------------------------------------------------------------------------
# Tests: BaseAdapter
# ---------------------------------------------------------------------------
class TestBaseAdapter:
def test_register_handler(self, adapter):
handler = lambda msg: "response"
adapter.on_message(handler)
assert len(adapter._message_handlers) == 1
def test_on_message_as_decorator(self, adapter):
@adapter.on_message
def my_handler(msg):
return "decorated response"
assert len(adapter._message_handlers) == 1
assert my_handler("test") == "decorated response"
def test_dispatch_calls_handler(self, adapter, sample_message):
responses = []
@adapter.on_message
def handler(msg):
responses.append(msg.text)
return f"reply to: {msg.text}"
adapter._dispatch(sample_message)
assert responses == ["Hello world"]
def test_dispatch_sends_response(self, adapter, sample_message):
@adapter.on_message
def handler(msg):
return "Auto reply"
adapter._dispatch(sample_message)
assert len(adapter.sent_messages) == 1
assert adapter.sent_messages[0]["text"] == "Auto reply"
assert adapter.sent_messages[0]["channel_id"] == "C456"
def test_dispatch_no_response(self, adapter, sample_message):
@adapter.on_message
def handler(msg):
return None # explicit no response
adapter._dispatch(sample_message)
assert len(adapter.sent_messages) == 0
def test_dispatch_handler_error(self, adapter, sample_message):
@adapter.on_message
def bad_handler(msg):
raise ValueError("Something broke")
# Should not raise — dispatch catches errors
adapter._dispatch(sample_message)
# Should send error message
assert len(adapter.sent_messages) == 1
assert "Something went wrong" in adapter.sent_messages[0]["text"]
def test_multiple_handlers(self, adapter, sample_message):
calls = []
@adapter.on_message
def handler1(msg):
calls.append("h1")
return None
@adapter.on_message
def handler2(msg):
calls.append("h2")
return "from h2"
adapter._dispatch(sample_message)
assert calls == ["h1", "h2"]
assert len(adapter.sent_messages) == 1 # only h2 returned a response
def test_source_name(self, adapter):
assert adapter.source_name == "mock"
def test_start_stop(self, adapter):
adapter.start()
assert adapter._started is True
adapter.stop()
assert adapter._started is False