Files
MoviePilot/tests/test_slack_command_registration.py
DDSRem 2de976f6b3 Merge pull request #7050 from DDSRem-Dev/codex-comment-migration
docs: 统一全项目中文注释和结构化契约说明
2026-10-17 19:26:29 +08:00

156 lines
5.3 KiB
Python

"""
验证Slack 命令注册及渠道能力声明。
"""
from types import SimpleNamespace
from unittest.mock import Mock, patch
from app.modules.slack import SlackModule
from app.modules.slack.slack import Slack
from app.schemas.event import CommandRegisterEventData
def test_slack_module_register_commands_filters_event_subset():
"""
Slack 模块注册命令时应复用渠道级 CommandRegister 事件过滤结果。
"""
module = SlackModule()
client = SimpleNamespace(register_commands=Mock(), delete_commands=Mock())
original_commands = {
"/sites": {"description": "管理站点"},
"/version": {"description": "当前版本"},
}
event = SimpleNamespace(
event_data=CommandRegisterEventData(
commands={"/sites": {"description": "管理站点"}, "/unknown": {"description": "无效"}},
origin="SlackFilter",
service="slack-main",
)
)
with (
patch.object(
module,
"get_configs",
return_value={"slack-main": SimpleNamespace(name="slack-main", config={})},
),
patch.object(module, "get_instance", return_value=client),
patch("app.modules._base.notification.eventmanager.send_event", return_value=event),
):
module.register_commands(original_commands)
client.register_commands.assert_called_once_with({"/sites": {"description": "管理站点"}})
client.delete_commands.assert_not_called()
def test_slack_manifest_update_preserves_foreign_commands():
"""
Slack Manifest 更新应只替换 MoviePilot 本次管理的 Slash Commands。
"""
client = Slack.__new__(Slack)
manifest_client = SimpleNamespace(
apps_manifest_export=Mock(
return_value={
"ok": True,
"manifest": {
"features": {
"slash_commands": [
{"command": "/keep", "description": "保留"},
{"command": "/sites", "description": "旧站点"},
{
"command": "/old_moviepilot",
"description": "旧命令",
"usage_hint": "MoviePilot 可选参数",
},
]
}
},
}
),
apps_manifest_update=Mock(return_value={"ok": True}),
)
client._manifest_client = manifest_client
client._app_id = "A123"
client._command_request_url = "https://example.com/slack/commands"
client._registered_command_names = {"/sites"}
assert client.register_commands(
{
"/sites": {"description": "管理站点"},
"/version": {"description": "当前版本"},
}
)
manifest_client.apps_manifest_update.assert_called_once()
_, kwargs = manifest_client.apps_manifest_update.call_args
assert kwargs["app_id"] == "A123"
slash_commands = kwargs["manifest"]["features"]["slash_commands"]
assert [item["command"] for item in slash_commands] == [
"/keep",
"/sites",
"/version",
]
assert slash_commands[1]["url"] == "https://example.com/slack/commands"
assert client._registered_command_names == {"/sites", "/version"}
def test_slack_command_registration_skips_without_manifest_credentials():
"""
未配置 Slack Manifest 凭据时不应尝试自动注册。
"""
client = Slack.__new__(Slack)
client._manifest_client = None
client._app_id = ""
assert client.register_commands({"/sites": {"description": "管理站点"}}) is False
def test_slack_normalizes_slash_command_names():
"""
Slack 命令名称应符合平台 Slash Command 约束。
"""
assert Slack._normalize_slack_command("/sites") == "/sites"
assert Slack._normalize_slack_command("CLEAR_CACHE") == "/clear_cache"
assert Slack._normalize_slack_command("/中文") == ""
assert Slack._normalize_slack_command("/" + "a" * 32) == ""
def test_slack_plain_text_interaction_buttons_render_and_clear_on_edit():
"""
纯文本交互必须显示按钮,后续无按钮编辑应清除旧操作区。
"""
client = Slack.__new__(Slack)
client._client = Mock()
client._client.chat_postMessage.return_value = {"ok": True, "ts": "1", "channel": "C1"}
client._client.chat_update.return_value = {"ok": True, "ts": "1", "channel": "C1"}
buttons = [[{"text": "确认升级", "callback_data": "update:req:download"}]]
assert (
client.send_msg(
title="发现更新",
text="v3.0.0 -> v3.1.0",
userid="C1",
buttons=buttons,
)[0]
is True
)
posted = client._client.chat_postMessage.call_args.kwargs
assert posted["text"] == "发现更新\nv3.0.0 -> v3.1.0"
assert [block["type"] for block in posted["blocks"]] == ["section", "actions"]
assert posted["blocks"][1]["elements"][0]["value"] == "update:req:download"
assert (
client.send_msg(
title="正在下载",
text="50%",
original_message_id="1",
original_chat_id="C1",
)[0]
is True
)
updated = client._client.chat_update.call_args.kwargs
assert updated["text"] == "正在下载\n50%"
assert updated["blocks"] == []