Files
iOSBuildServer/tests/test_notification.py
T
shenleiandClaude Sonnet 5 dae14a8a10 fix: App_Store 钉钉通知因缺少关键词「打包」被拦截,标题改回含「打包」
钉钉机器人启用了自定义关键词校验。9ace2c8 将 App_Store 标题改为
「【iOS】App_Store 包信息」,丢掉了「打包」二字,导致消息被钉钉拒收
(errmsg: 关键词不匹配),任务日志出现「钉钉通知未发送」。

标题改回「【iOS】App_Store 打包信息」,重新包含关键词;测试同步更新。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014FETBaqMgRqx3kdpzccKg1
2026-09-01 11:34:57 +09:00

134 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""钉钉通知测试。"""
from unittest.mock import MagicMock, patch
import pytest
from backend.services.notification import NotificationError, build_dingtalk_payload, send_dingtalk_notification
def _build_config():
return {
"SERVER": "测试环境",
"VERSION": "2.195.0",
"APPID_NAME": "阅门户测试App",
"BUNDLE_ID": "cn.touchv.a4YX061",
"APPID": "647372741900537856",
}
def test_dingtalk_payload_matches_autopacking_content():
payload = build_dingtalk_payload(
_build_config(),
"https://download.example.com/app.html",
"https://download.example.com/app.png",
)
text = payload["markdown"]["text"]
assert payload["markdown"]["title"] == "iOS应用下载"
assert "## 【iOS】打包信息" in text
assert "**环境:** 测试环境" in text
assert "**版本:** 2.195.0" in text
assert "**APP名称:** 阅门户测试App" in text
assert "**包名:** cn.touchv.a4YX061" in text
assert "**App Guid** 647372741900537856" in text
assert "**iOS 下载链接:** https://download.example.com/app.html" in text
assert "![image](https://download.example.com/app.png)" in text
def test_dingtalk_payload_at_mobiles_appended_to_text_and_at_field():
payload = build_dingtalk_payload(
_build_config(),
"https://download.example.com/app.html",
at_mobiles=["13800000000", " 13900000001 ", "13800000000", ""],
)
# 去重去空后写入 at.atMobiles,并在正文追加 @手机号(钉钉 markdown 必需)
assert payload["at"]["atMobiles"] == ["13800000000", "13900000001"]
assert "@13800000000" in payload["markdown"]["text"]
assert "@13900000001" in payload["markdown"]["text"]
def test_dingtalk_payload_without_at_mobiles_has_empty_at():
payload = build_dingtalk_payload(_build_config(), "https://download.example.com/app.html")
assert payload["at"]["atMobiles"] == []
assert "@" not in payload["markdown"]["text"]
def test_dingtalk_notification_forwards_at_mobiles():
response = MagicMock(status_code=200)
response.json.return_value = {"errcode": 0}
with patch("backend.services.notification.httpx.post", return_value=response) as post:
send_dingtalk_notification(
{
"enabled": True,
"webhook_url": "https://example.com/robot",
"at_mobiles": ["13800000000", "13900000001"],
},
_build_config(),
"https://download.example.com/app.html",
)
sent = post.call_args.kwargs["json"]
assert sent["at"]["atMobiles"] == ["13800000000", "13900000001"]
assert "@13800000000" in sent["markdown"]["text"]
def test_dingtalk_payload_app_store_heading_and_no_qr():
config = {**_build_config(), "BUILD_TYPE": "App_Store"}
# App_Store 流程不传二维码地址(publish_ipa 返回空串)
payload = build_dingtalk_payload(
config, "https://oss.example.com/readoor/iOS/app_2_197_1.ipa"
)
text = payload["markdown"]["text"]
# 标题保留「打包」二字,避免命中钉钉自定义关键词拦截
assert "## 【iOS】App_Store 打包信息" in text
assert "**iOS 下载链接:** https://oss.example.com/readoor/iOS/app_2_197_1.ipa" in text
assert "![image]" not in text
def test_dingtalk_notification_app_store_uses_own_at_list():
response = MagicMock(status_code=200)
response.json.return_value = {"errcode": 0}
dingtalk_config = {
"enabled": True,
"webhook_url": "https://example.com/robot",
"at_mobiles": ["13800000000"],
"at_mobiles_app_store": ["13911111111", "13922222222"],
}
with patch("backend.services.notification.httpx.post", return_value=response) as post:
send_dingtalk_notification(
dingtalk_config,
{**_build_config(), "BUILD_TYPE": "App_Store"},
"https://oss.example.com/app.ipa",
)
sent = post.call_args.kwargs["json"]
assert sent["at"]["atMobiles"] == ["13911111111", "13922222222"]
assert "## 【iOS】App_Store 打包信息" in sent["markdown"]["text"]
assert "@13800000000" not in sent["markdown"]["text"]
def test_dingtalk_notification_skips_when_disabled():
with patch("backend.services.notification.httpx.post") as post:
assert send_dingtalk_notification({}, _build_config(), "https://download.example.com/app") is False
post.assert_not_called()
def test_dingtalk_notification_sends_markdown():
response = MagicMock(status_code=200)
response.json.return_value = {"errcode": 0}
with patch("backend.services.notification.httpx.post", return_value=response) as post:
assert send_dingtalk_notification(
{"enabled": True, "webhook_url": "https://example.com/robot"},
_build_config(),
"https://download.example.com/app.html",
"https://download.example.com/app.png",
) is True
assert post.call_args.kwargs["json"]["markdown"]["title"] == "iOS应用下载"
def test_dingtalk_notification_requires_webhook_when_enabled():
with pytest.raises(NotificationError, match="Webhook"):
send_dingtalk_notification({"enabled": True}, _build_config(), "https://download.example.com/app")