Files
KiloStar/tests/unit/test_api_onebot.py
T
zhaoxi 99520c69d7 feat(system):优化后端
1.新增后端测试
2.增加了后端的加密
3.增加了i18n(国际化)
2026-05-31 15:39:34 +00:00

169 lines
5.5 KiB
Python

"""``api/platform/onebot.py`` 中纯函数与事件分派的覆盖。"""
from __future__ import annotations
from unittest.mock import AsyncMock, MagicMock
import pytest
from fastapi import HTTPException
from kilostar.api.platform import onebot as onebot_mod
from kilostar.core.individual.regulatory_node.template import MessageResponse
# ─── _verify_token ──────────────────────────────────────────────────────────
def test_verify_token_skipped_when_env_missing(monkeypatch):
monkeypatch.delenv("ONEBOT_ACCESS_TOKEN", raising=False)
onebot_mod._verify_token(None)
onebot_mod._verify_token("anything")
def test_verify_token_accepts_bearer_prefix(monkeypatch):
monkeypatch.setenv("ONEBOT_ACCESS_TOKEN", "expected")
onebot_mod._verify_token("Bearer expected")
def test_verify_token_accepts_token_prefix(monkeypatch):
monkeypatch.setenv("ONEBOT_ACCESS_TOKEN", "expected")
onebot_mod._verify_token("Token expected")
def test_verify_token_accepts_raw_token(monkeypatch):
monkeypatch.setenv("ONEBOT_ACCESS_TOKEN", "expected")
onebot_mod._verify_token("expected")
def test_verify_token_rejects_missing(monkeypatch):
monkeypatch.setenv("ONEBOT_ACCESS_TOKEN", "expected")
with pytest.raises(HTTPException) as exc:
onebot_mod._verify_token(None)
assert exc.value.status_code == 401
def test_verify_token_rejects_wrong_token(monkeypatch):
monkeypatch.setenv("ONEBOT_ACCESS_TOKEN", "expected")
with pytest.raises(HTTPException) as exc:
onebot_mod._verify_token("Bearer wrong")
assert exc.value.status_code == 401
# ─── _extract_plain_text ────────────────────────────────────────────────────
def test_extract_plain_text_handles_string():
assert onebot_mod._extract_plain_text("hello") == "hello"
def test_extract_plain_text_handles_segment_array():
seg = [
{"type": "text", "data": {"text": "hello "}},
{"type": "image", "data": {"file": "1.png"}},
{"type": "text", "data": {"text": "world"}},
]
assert onebot_mod._extract_plain_text(seg) == "hello world"
def test_extract_plain_text_handles_unknown_type():
assert onebot_mod._extract_plain_text(None) == ""
assert onebot_mod._extract_plain_text({"foo": "bar"}) == ""
# ─── _dispatch_event ────────────────────────────────────────────────────────
@pytest.fixture
def regulatory_actor(fake_actors):
"""注入一个 regulatory_node Mock,默认返回固定的 MessageResponse。"""
inner = MagicMock()
inner.working.remote = AsyncMock(
return_value=MessageResponse(
platform="onebot", platform_id="private:1234", reply_message="pong"
)
)
fake_actors.register("regulatory_node", inner)
return inner
async def test_dispatch_event_ignores_non_message(regulatory_actor):
res = await onebot_mod._dispatch_event(
{"post_type": "meta_event", "meta_event_type": "heartbeat"}
)
assert res is None
regulatory_actor.working.remote.assert_not_called()
async def test_dispatch_event_ignores_empty_text(regulatory_actor):
res = await onebot_mod._dispatch_event(
{
"post_type": "message",
"message_type": "private",
"user_id": 1234,
"message": " ",
}
)
assert res is None
regulatory_actor.working.remote.assert_not_called()
async def test_dispatch_event_private_message_returns_quick_reply(regulatory_actor):
payload = {
"post_type": "message",
"message_type": "private",
"user_id": 1234,
"sender": {"nickname": "alice"},
"message": "ping",
}
res = await onebot_mod._dispatch_event(payload)
assert res is not None
assert res["reply"] == "pong"
assert "at_sender" not in res
assert res["_target"]["message_type"] == "private"
assert res["_target"]["user_id"] == 1234
async def test_dispatch_event_group_message_includes_at_sender(regulatory_actor):
payload = {
"post_type": "message",
"message_type": "group",
"user_id": 1234,
"group_id": 5678,
"sender": {"card": "alice", "nickname": "fallback"},
"message": [{"type": "text", "data": {"text": "ping"}}],
}
res = await onebot_mod._dispatch_event(payload)
assert res["reply"] == "pong"
assert res["at_sender"] is False
assert res["_target"]["group_id"] == 5678
async def test_dispatch_event_swallows_actor_error(regulatory_actor):
regulatory_actor.working.remote = AsyncMock(side_effect=RuntimeError("ray fail"))
payload = {
"post_type": "message",
"message_type": "private",
"user_id": 1,
"message": "hi",
}
res = await onebot_mod._dispatch_event(payload)
assert res is None
async def test_dispatch_event_returns_none_when_reply_empty(fake_actors):
inner = MagicMock()
inner.working.remote = AsyncMock(
return_value=MessageResponse(
platform="onebot", platform_id="private:1", reply_message=""
)
)
fake_actors.register("regulatory_node", inner)
payload = {
"post_type": "message",
"message_type": "private",
"user_id": 1,
"message": "hi",
}
res = await onebot_mod._dispatch_event(payload)
assert res is None