ForcePilot/backend/test/unit/gateway/protocol/test_init.py
Kris 3264900bc9 test: 新增多渠道单元测试用例并配置测试环境变量
新增了Twitch、Telegram、Discord、Slack、Mattermost、WeChat、Zalo等多渠道的单元测试用例,覆盖了令牌处理、速率限制、消息去重、会话解析、格式转换、安全策略等模块
同时在测试配置中添加了测试用的OpenAI API密钥环境变量
2026-05-12 00:56:47 +08:00

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