"""表情裸词操作补丁(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 == ["任意文本"]