Files
AstrBot/tests_v4/test_platform_client.py
whatevertogo 9c5ecf0a13 feat: Enhance plugin capability support and legacy compatibility
- 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.
2026-03-13 06:16:57 +08:00

241 lines
8.0 KiB
Python

"""
Tests for clients/platform.py - PlatformClient implementation.
"""
from __future__ import annotations
from unittest.mock import AsyncMock, MagicMock
import pytest
from astrbot_sdk.clients.platform import PlatformClient
from astrbot_sdk.clients._proxy import CapabilityProxy
from astrbot_sdk.protocol.descriptors import SessionRef
class TestPlatformClientInit:
"""Tests for PlatformClient initialization."""
def test_init_with_proxy(self):
"""PlatformClient should store proxy reference."""
proxy = MagicMock(spec=CapabilityProxy)
client = PlatformClient(proxy)
assert client._proxy is proxy
class TestPlatformClientSend:
"""Tests for PlatformClient.send() method."""
@pytest.mark.asyncio
async def test_send_returns_response(self):
"""send() should return response dict."""
proxy = AsyncMock(spec=CapabilityProxy)
proxy.call = AsyncMock(return_value={"message_id": "msg_123", "sent": True})
client = PlatformClient(proxy)
result = await client.send("session-1", "Hello")
proxy.call.assert_called_once_with(
"platform.send",
{"session": "session-1", "text": "Hello"},
)
assert result["message_id"] == "msg_123"
@pytest.mark.asyncio
async def test_send_with_empty_text(self):
"""send() should work with empty text."""
proxy = AsyncMock(spec=CapabilityProxy)
proxy.call = AsyncMock(return_value={})
client = PlatformClient(proxy)
await client.send("session-1", "")
call_args = proxy.call.call_args[0][1]
assert call_args["text"] == ""
@pytest.mark.asyncio
async def test_send_with_special_characters(self):
"""send() should handle special characters in text."""
proxy = AsyncMock(spec=CapabilityProxy)
proxy.call = AsyncMock(return_value={})
client = PlatformClient(proxy)
await client.send("session-1", "Hello\nWorld\t! @#$%")
call_args = proxy.call.call_args[0][1]
assert call_args["text"] == "Hello\nWorld\t! @#$%"
@pytest.mark.asyncio
async def test_send_with_session_ref_adds_target_payload(self):
"""send() should preserve structured session targets while keeping session string."""
proxy = AsyncMock(spec=CapabilityProxy)
proxy.call = AsyncMock(return_value={})
client = PlatformClient(proxy)
await client.send(
SessionRef(
conversation_id="session-1",
platform="test",
raw={"trace_id": "trace-1"},
),
"Hello",
)
proxy.call.assert_called_once_with(
"platform.send",
{
"session": "session-1",
"target": {
"conversation_id": "session-1",
"platform": "test",
"raw": {"trace_id": "trace-1"},
},
"text": "Hello",
},
)
class TestPlatformClientSendImage:
"""Tests for PlatformClient.send_image() method."""
@pytest.mark.asyncio
async def test_send_image_returns_response(self):
"""send_image() should return response dict."""
proxy = AsyncMock(spec=CapabilityProxy)
proxy.call = AsyncMock(return_value={"image_id": "img_456"})
client = PlatformClient(proxy)
result = await client.send_image("session-1", "https://example.com/image.png")
proxy.call.assert_called_once_with(
"platform.send_image",
{"session": "session-1", "image_url": "https://example.com/image.png"},
)
assert result["image_id"] == "img_456"
@pytest.mark.asyncio
async def test_send_image_with_file_url(self):
"""send_image() should work with file:// URL."""
proxy = AsyncMock(spec=CapabilityProxy)
proxy.call = AsyncMock(return_value={})
client = PlatformClient(proxy)
await client.send_image("session-1", "file:///path/to/image.jpg")
call_args = proxy.call.call_args[0][1]
assert call_args["image_url"] == "file:///path/to/image.jpg"
@pytest.mark.asyncio
async def test_send_image_with_base64_url(self):
"""send_image() should work with data URL."""
proxy = AsyncMock(spec=CapabilityProxy)
proxy.call = AsyncMock(return_value={})
client = PlatformClient(proxy)
await client.send_image("session-1", "data:image/png;base64,abc123")
call_args = proxy.call.call_args[0][1]
assert call_args["image_url"] == "data:image/png;base64,abc123"
class TestPlatformClientSendChain:
"""Tests for PlatformClient.send_chain() method."""
@pytest.mark.asyncio
async def test_send_chain_returns_response(self):
"""send_chain() should return response dict."""
proxy = AsyncMock(spec=CapabilityProxy)
proxy.call = AsyncMock(return_value={"message_id": "chain_123"})
client = PlatformClient(proxy)
result = await client.send_chain(
"session-1",
[{"type": "Plain", "text": "Hello"}],
)
proxy.call.assert_called_once_with(
"platform.send_chain",
{"session": "session-1", "chain": [{"type": "Plain", "text": "Hello"}]},
)
assert result["message_id"] == "chain_123"
@pytest.mark.asyncio
async def test_send_chain_with_multiple_components(self):
"""send_chain() should preserve the original component payloads."""
proxy = AsyncMock(spec=CapabilityProxy)
proxy.call = AsyncMock(return_value={})
client = PlatformClient(proxy)
await client.send_chain(
"session-1",
[
{"type": "Plain", "text": "Hello"},
{"type": "Image", "file": "https://example.com/a.png"},
],
)
call_args = proxy.call.call_args[0][1]
assert call_args["chain"][0]["text"] == "Hello"
assert call_args["chain"][1]["file"] == "https://example.com/a.png"
class TestPlatformClientGetMembers:
"""Tests for PlatformClient.get_members() method."""
@pytest.mark.asyncio
async def test_get_members_returns_list(self):
"""get_members() should return list of members."""
proxy = AsyncMock(spec=CapabilityProxy)
proxy.call = AsyncMock(
return_value={
"members": [
{"id": "user1", "name": "Alice"},
{"id": "user2", "name": "Bob"},
]
}
)
client = PlatformClient(proxy)
result = await client.get_members("group-1")
proxy.call.assert_called_once_with(
"platform.get_members",
{"session": "group-1"},
)
assert len(result) == 2
assert result[0]["name"] == "Alice"
@pytest.mark.asyncio
async def test_get_members_returns_empty_list(self):
"""get_members() should return empty list when no members."""
proxy = AsyncMock(spec=CapabilityProxy)
proxy.call = AsyncMock(return_value={})
client = PlatformClient(proxy)
result = await client.get_members("empty-group")
assert result == []
@pytest.mark.asyncio
async def test_get_members_returns_empty_list_for_malformed_payload(self):
"""get_members() should ignore malformed non-list payloads."""
proxy = AsyncMock(spec=CapabilityProxy)
proxy.call = AsyncMock(return_value={"members": "bad"})
client = PlatformClient(proxy)
result = await client.get_members("group-1")
assert result == []
@pytest.mark.asyncio
async def test_get_members_with_private_session(self):
"""get_members() should work with private session."""
proxy = AsyncMock(spec=CapabilityProxy)
proxy.call = AsyncMock(return_value={"members": [{"id": "single_user"}]})
client = PlatformClient(proxy)
await client.get_members("private-123")
call_args = proxy.call.call_args[0][1]
assert call_args["session"] == "private-123"