Files
HeXi/tests/test_memes_ops.py
sansenhoshiandClaude b61d09f09f Add HeXi bot codebase: custom plugins, web frontends, tests
- hexi core: message handling, rate limiting, cooldown, plugin manager
- Custom plugins: BF stats, daily check-in, quotes, persona cards, etc.
- Community plugins vendored under hexi/plugins with local fixes
- Web admin frontends (learning-chat, persona-admin), unified hexi/web
- Tests for rate_limit/cooldown/memes/persona; poetry.lock

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-01 13:13:40 +08:00

105 lines
3.1 KiB
Python

"""表情裸词操作补丁(hexi/plugins/memes_ops)的回归测试。
验证 `对称 右` 这类“表情 + 裸词操作”能被新 matcher 正确解析为选项,
同时 `-右`/`--right` 旧形式仍然可用。
若 nonebot_plugin_memes 缺失或补丁因版本不兼容而失效,本模块整体跳过。
"""
import nonebot
import pytest
try:
nonebot.init()
from nonebot import get_loaded_plugins, load_plugin
load_plugin("hexi.plugins.memes_ops")
_memes_loaded = True
except Exception:
_memes_loaded = False
if not _memes_loaded:
pytest.skip(
"无法加载 nonebot_plugin_memes / memes_ops,跳过裸词操作补丁测试",
allow_module_level=True,
)
_patchers = [
matcher
for plugin in get_loaded_plugins()
for matcher in plugin.matcher
if matcher.priority == 11 and matcher.module_name == "hexi.plugins.memes_ops"
]
if not _patchers:
pytest.skip(
"memes_ops 补丁 matcher 未注册(版本不兼容?),跳过裸词操作补丁测试",
allow_module_level=True,
)
_cmd_start = list(nonebot.get_driver().config.command_start)[0]
def _parse(msg: str):
"""在所有新 matcher 中解析消息,返回 (选项, 文字参数) 命中集合。"""
hits = []
for matcher in _patchers:
try:
result = matcher.command().parse(msg)
except Exception:
continue
if result.matched:
options = {
key: value.value
for key, value in result.options.items()
if value.value not in (None, False)
}
params = [
seg.text for seg in result.query("meme_params", ()) if seg.text
]
hits.append((options, params))
return hits
@pytest.mark.parametrize(
("msg", "expected_options"),
[
(f"{_cmd_start}对称 右", {"right"}),
(f"{_cmd_start}对称 左", {"left"}),
(f"{_cmd_start}对称 上", {"top"}),
(f"{_cmd_start}对称 下", {"bottom"}),
(f"{_cmd_start}鬼畜 右", {"right"}),
(f"{_cmd_start}循环 下", {"bottom"}),
(f"{_cmd_start}摸 圆", {"circle"}),
(f"{_cmd_start}小丑 爷", {"person"}),
(f"{_cmd_start}小丑面具 前", {"front"}),
(f"{_cmd_start}ba说 左", {"left"}),
],
)
def test_bare_operation_maps_to_option(msg, expected_options):
hits = _parse(msg)
assert hits, f"{msg!r} 未被任何补丁 matcher 命中"
# 新 matcher 优先(priority 11),取第一个命中
options, params = hits[0]
assert set(options) == expected_options
assert params == []
@pytest.mark.parametrize(
"msg",
[f"{_cmd_start}对称 -右", f"{_cmd_start}对称 --right", f"{_cmd_start}鬼畜 --bottom"],
)
def test_dash_syntax_still_works(msg):
options, params = _parse(msg)[0]
assert options, f"{msg!r} 应解析出选项"
assert params == []
def test_non_alias_word_stays_text():
msg = f"{_cmd_start}对称 任意文本"
hits = _parse(msg)
assert hits
options, params = hits[0]
assert options == {}
assert params == ["任意文本"]