mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-16 01:40:15 +08:00
- Introduced LoadedCapability class to manage plugin capabilities. - Updated load_plugin function to discover and load capabilities alongside handlers. - Enhanced Peer class to handle remote provided capabilities during initialization. - Added tests for capability registration and invocation in legacy plugins. - Improved MessageChain and message component handling in legacy plugins. - Added comprehensive tests for legacy plugin integration and compatibility. - Updated protocol messages to include provided capabilities in initialization. - Enhanced top-level module imports to include capability-related functions.
141 lines
4.5 KiB
Python
141 lines
4.5 KiB
Python
"""
|
|
Unit tests for Events module.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from astrbot_sdk.events import MessageEvent, PlainTextResult
|
|
|
|
|
|
class TestMessageEvent:
|
|
"""Tests for MessageEvent."""
|
|
|
|
def test_from_payload_creates_event(self):
|
|
"""from_payload() should create a MessageEvent from dict."""
|
|
payload = {
|
|
"text": "hello world",
|
|
"session_id": "session-1",
|
|
"user_id": "user-1",
|
|
"platform": "test",
|
|
}
|
|
event = MessageEvent.from_payload(payload)
|
|
|
|
assert event.text == "hello world"
|
|
assert event.session_id == "session-1"
|
|
assert event.user_id == "user-1"
|
|
assert event.platform == "test"
|
|
|
|
def test_from_payload_handles_missing_fields(self):
|
|
"""from_payload() should handle missing optional fields."""
|
|
payload = {"text": "test"}
|
|
event = MessageEvent.from_payload(payload)
|
|
|
|
assert event.text == "test"
|
|
assert event.session_id == "" # Falls back to empty string
|
|
assert event.user_id is None # Optional field
|
|
|
|
def test_from_payload_preserves_raw_payload(self):
|
|
"""from_payload() should preserve raw payload."""
|
|
payload = {
|
|
"text": "test",
|
|
"extra_field": "extra_value",
|
|
}
|
|
event = MessageEvent.from_payload(payload)
|
|
|
|
assert event.raw == payload
|
|
assert event.raw["extra_field"] == "extra_value"
|
|
|
|
def test_from_payload_reads_target_shape(self):
|
|
"""from_payload() should derive session/platform from structured target payload."""
|
|
event = MessageEvent.from_payload(
|
|
{
|
|
"text": "hello",
|
|
"target": {
|
|
"conversation_id": "session-1",
|
|
"platform": "test-platform",
|
|
},
|
|
}
|
|
)
|
|
|
|
assert event.session_id == "session-1"
|
|
assert event.platform == "test-platform"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_bind_reply_handler(self):
|
|
"""bind_reply_handler() should enable reply functionality."""
|
|
event = MessageEvent(text="hello", session_id="s1")
|
|
replies = []
|
|
|
|
async def capture_reply(text: str) -> None:
|
|
replies.append(text)
|
|
|
|
event.bind_reply_handler(capture_reply)
|
|
await event.reply("response")
|
|
|
|
assert replies == ["response"]
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_reply_without_handler_raises(self):
|
|
"""reply() without bound handler should raise."""
|
|
event = MessageEvent(text="hello", session_id="s1")
|
|
|
|
with pytest.raises(RuntimeError, match="未绑定 reply handler"):
|
|
await event.reply("response")
|
|
|
|
def test_to_payload(self):
|
|
"""to_payload() should serialize event to dict."""
|
|
event = MessageEvent(
|
|
text="hello",
|
|
session_id="session-1",
|
|
user_id="user-1",
|
|
platform="test",
|
|
)
|
|
payload = event.to_payload()
|
|
|
|
assert payload["text"] == "hello"
|
|
assert payload["session_id"] == "session-1"
|
|
assert payload["user_id"] == "user-1"
|
|
assert payload["platform"] == "test"
|
|
assert payload["target"]["conversation_id"] == "session-1"
|
|
|
|
def test_to_payload_preserves_extra_raw_fields(self):
|
|
"""to_payload() should preserve unmodeled raw fields during round-trip."""
|
|
event = MessageEvent.from_payload(
|
|
{
|
|
"text": "hello",
|
|
"session_id": "session-1",
|
|
"trace_id": "trace-123",
|
|
}
|
|
)
|
|
event.text = "updated"
|
|
|
|
payload = event.to_payload()
|
|
|
|
assert payload["trace_id"] == "trace-123"
|
|
assert payload["text"] == "updated"
|
|
|
|
def test_plain_result_createsPlainTextResult(self):
|
|
"""plain_result() should create PlainTextResult."""
|
|
event = MessageEvent(text="hello", session_id="s1")
|
|
result = event.plain_result("test output")
|
|
|
|
assert isinstance(result, PlainTextResult)
|
|
assert result.text == "test output"
|
|
|
|
|
|
class TestPlainTextResult:
|
|
"""Tests for PlainTextResult."""
|
|
|
|
def test_create_plain_text_result(self):
|
|
"""Should create PlainTextResult."""
|
|
result = PlainTextResult(text="hello")
|
|
assert result.text == "hello"
|
|
|
|
def test_plain_text_result_is_dataclass(self):
|
|
"""PlainTextResult should be a dataclass with slots."""
|
|
result = PlainTextResult(text="test")
|
|
# It's a dataclass, check attribute access works
|
|
assert result.text == "test"
|