新增了Twitch、Telegram、Discord、Slack、Mattermost、WeChat、Zalo等多渠道的单元测试用例,覆盖了令牌处理、速率限制、消息去重、会话解析、格式转换、安全策略等模块 同时在测试配置中添加了测试用的OpenAI API密钥环境变量
127 lines
4.6 KiB
Python
127 lines
4.6 KiB
Python
from __future__ import annotations
|
|
|
|
import pytest
|
|
from pydantic import TypeAdapter, ValidationError
|
|
|
|
from yuxi.gateway.protocol import GatewayFrame, RequestFrame, ResponseFrame, EventFrame
|
|
from yuxi.gateway.protocol.errors import ErrorCode, ErrorDetail
|
|
|
|
_adapter = TypeAdapter(GatewayFrame)
|
|
|
|
|
|
class TestGatewayFrameUnion:
|
|
def test_parse_request_frame(self):
|
|
data = {"type": "req", "id": "r1", "method": "ping", "params": {}}
|
|
frame = _adapter.validate_python(data)
|
|
assert isinstance(frame, RequestFrame)
|
|
assert frame.id == "r1"
|
|
assert frame.method == "ping"
|
|
|
|
def test_parse_response_frame(self):
|
|
data = {"type": "res", "id": "r1", "ok": True}
|
|
frame = _adapter.validate_python(data)
|
|
assert isinstance(frame, ResponseFrame)
|
|
assert frame.ok is True
|
|
|
|
def test_parse_event_frame(self):
|
|
data = {"type": "event", "event": "typing"}
|
|
frame = _adapter.validate_python(data)
|
|
assert isinstance(frame, EventFrame)
|
|
assert frame.event == "typing"
|
|
|
|
def test_unknown_type_raises(self):
|
|
with pytest.raises(ValidationError):
|
|
_adapter.validate_python({"type": "unknown", "id": "x", "ok": True})
|
|
|
|
def test_parse_response_with_error(self):
|
|
error_data = {"code": -32600, "message": "bad request", "retryable": False}
|
|
data = {"type": "res", "id": "r1", "ok": False, "error": error_data}
|
|
frame = _adapter.validate_python(data)
|
|
assert isinstance(frame, ResponseFrame)
|
|
assert frame.ok is False
|
|
assert frame.error is not None
|
|
assert isinstance(frame.error, ErrorDetail)
|
|
assert frame.error.code == ErrorCode.INVALID_REQUEST
|
|
|
|
def test_parse_event_with_payload(self):
|
|
data = {
|
|
"type": "event", "event": "message.received",
|
|
"payload": {"text": "hello"}, "seq": 1, "state_version": 0,
|
|
}
|
|
frame = _adapter.validate_python(data)
|
|
assert isinstance(frame, EventFrame)
|
|
assert frame.payload == {"text": "hello"}
|
|
assert frame.seq == 1
|
|
|
|
def test_missing_type_raises(self):
|
|
with pytest.raises(ValidationError):
|
|
_adapter.validate_python({"id": "x", "ok": True})
|
|
|
|
def test_discriminator_distinguishes_types(self):
|
|
req = _adapter.validate_python({"type": "req", "id": "req-1", "method": "test"})
|
|
res = _adapter.validate_python({"type": "res", "id": "req-1", "ok": True})
|
|
evt = _adapter.validate_python({"type": "event", "event": "test.event"})
|
|
assert isinstance(req, RequestFrame)
|
|
assert isinstance(res, ResponseFrame)
|
|
assert isinstance(evt, EventFrame)
|
|
assert not isinstance(req, ResponseFrame)
|
|
assert not isinstance(req, EventFrame)
|
|
|
|
def test_model_dump_roundtrip(self):
|
|
data = {"type": "req", "id": "r1", "method": "ping", "params": {}}
|
|
frame = _adapter.validate_python(data)
|
|
output = _adapter.dump_python(frame, mode="json")
|
|
assert output["type"] == "req"
|
|
assert output["id"] == "r1"
|
|
|
|
|
|
class TestPackageImport:
|
|
def test_import_gateway_package(self):
|
|
import yuxi.gateway # noqa: F401
|
|
|
|
def test_import_gateway_protocol(self):
|
|
from yuxi.gateway import protocol # noqa: F401
|
|
|
|
def test_import_all_public_types(self):
|
|
from yuxi.gateway import (
|
|
RequestFrame,
|
|
ResponseFrame,
|
|
EventFrame,
|
|
GatewayFrame,
|
|
ErrorCode,
|
|
ErrorDetail,
|
|
PROTOCOL_VERSION,
|
|
negotiate_version,
|
|
ConnectParams,
|
|
HelloFeatures,
|
|
HelloOk,
|
|
handle_handshake,
|
|
NonEmptyString,
|
|
PositiveInt,
|
|
ChannelStatusRequest,
|
|
ChannelStartRequest,
|
|
ChannelLogoutRequest,
|
|
)
|
|
assert RequestFrame is not None
|
|
assert ResponseFrame is not None
|
|
assert EventFrame is not None
|
|
assert GatewayFrame is not None
|
|
assert ErrorCode is not None
|
|
assert ErrorDetail is not None
|
|
assert PROTOCOL_VERSION == 1
|
|
assert negotiate_version is not None
|
|
assert ConnectParams is not None
|
|
assert HelloFeatures is not None
|
|
assert HelloOk is not None
|
|
assert handle_handshake is not None
|
|
assert NonEmptyString is not None
|
|
assert PositiveInt is not None
|
|
assert ChannelStatusRequest is not None
|
|
assert ChannelStartRequest is not None
|
|
assert ChannelLogoutRequest is not None
|
|
|
|
def test_import_from_protocol_submodule(self):
|
|
from yuxi.gateway.protocol import RequestFrame, GatewayFrame
|
|
assert RequestFrame is not None
|
|
assert GatewayFrame is not None
|