mirror of
https://ghfast.top/https://github.com/aeroxw/tick-stock-panel.git
synced 2026-09-12 17:54:15 +08:00
150 lines
5.2 KiB
Python
150 lines
5.2 KiB
Python
"""Webhook 测试消息功能 — 向已保存的 Webhook 地址发送测试消息验证配置。
|
|
|
|
纯逻辑,不触网(monkeypatch webhook_adapter.send_*),直接调用 settings 端点函数。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
from pydantic import ValidationError
|
|
|
|
from app.api.settings import (
|
|
WebhookTestIn,
|
|
)
|
|
from app.api.settings import (
|
|
test_webhook as run_webhook_test,
|
|
)
|
|
|
|
FEISHU_URL = "https://open.feishu.cn/open-apis/bot/v2/hook/test"
|
|
WECOM_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=test-key"
|
|
|
|
|
|
def test_feishu_sends_saved_url_and_secret(monkeypatch):
|
|
calls = {}
|
|
monkeypatch.setattr("app.services.preferences.get_feishu_webhook_url", lambda: FEISHU_URL)
|
|
monkeypatch.setattr("app.services.preferences.get_feishu_webhook_secret", lambda: "my-secret")
|
|
monkeypatch.setattr(
|
|
"app.services.webhook_adapter.send_feishu",
|
|
lambda url, title, body, secret="", max_attempts=3: calls.update(
|
|
url=url, title=title, body=body, secret=secret, max_attempts=max_attempts,
|
|
) or True,
|
|
)
|
|
|
|
result = run_webhook_test(WebhookTestIn(channel="feishu"))
|
|
|
|
assert result["ok"] is True
|
|
assert calls["url"] == FEISHU_URL
|
|
assert calls["secret"] == "my-secret"
|
|
# 诊断路径单次尝试, 不等生产退避重试
|
|
assert calls["max_attempts"] == 1
|
|
assert calls["title"] == "TickFlow Stock Panel 推送测试"
|
|
assert "推送配置正确" in calls["body"]
|
|
|
|
|
|
def test_feishu_send_failure_returns_ok_false(monkeypatch):
|
|
monkeypatch.setattr("app.services.preferences.get_feishu_webhook_url", lambda: FEISHU_URL)
|
|
monkeypatch.setattr("app.services.preferences.get_feishu_webhook_secret", lambda: "")
|
|
monkeypatch.setattr("app.services.webhook_adapter.send_feishu", lambda *a, **k: False)
|
|
|
|
result = run_webhook_test(WebhookTestIn(channel="feishu"))
|
|
|
|
assert result["ok"] is False
|
|
assert "推送失败" in result["detail"]
|
|
|
|
|
|
@pytest.mark.parametrize("channel,url_getter", [
|
|
("feishu", "app.services.preferences.get_feishu_webhook_url"),
|
|
("wecom", "app.services.preferences.get_wecom_webhook_url"),
|
|
])
|
|
def test_not_configured_returns_ok_false(monkeypatch, channel, url_getter):
|
|
monkeypatch.setattr(url_getter, lambda: "")
|
|
|
|
result = run_webhook_test(WebhookTestIn(channel=channel))
|
|
|
|
assert result["ok"] is False
|
|
assert "尚未配置" in result["detail"]
|
|
|
|
|
|
def test_invalid_saved_feishu_url_returns_ok_false(monkeypatch):
|
|
monkeypatch.setattr("app.services.preferences.get_feishu_webhook_url", lambda: "https://evil.example/hook/xx")
|
|
|
|
result = run_webhook_test(WebhookTestIn(channel="feishu"))
|
|
|
|
assert result["ok"] is False
|
|
assert "地址非法" in result["detail"]
|
|
|
|
|
|
def test_wecom_sends_saved_url(monkeypatch):
|
|
calls = {}
|
|
monkeypatch.setattr("app.services.preferences.get_wecom_webhook_url", lambda: WECOM_URL)
|
|
monkeypatch.setattr(
|
|
"app.services.webhook_adapter.send_wecom",
|
|
lambda url, title, body: calls.update(url=url, title=title, body=body) or True,
|
|
)
|
|
|
|
result = run_webhook_test(WebhookTestIn(channel="wecom"))
|
|
|
|
assert result["ok"] is True
|
|
assert calls["url"] == WECOM_URL
|
|
assert calls["title"] == "TickFlow Stock Panel 推送测试"
|
|
assert "推送配置正确" in calls["body"]
|
|
|
|
|
|
def test_custom_webhook_sends_saved_url_and_secret(monkeypatch):
|
|
calls = {}
|
|
monkeypatch.setattr(
|
|
"app.services.preferences.get_custom_webhook_url",
|
|
lambda: "https://example.com/tickflow",
|
|
)
|
|
monkeypatch.setattr("app.secrets_store.get_custom_webhook_secret", lambda: "secret")
|
|
monkeypatch.setattr(
|
|
"app.services.webhook_adapter.send_custom",
|
|
lambda url, title, body, event_type, data=None, secret="", max_attempts=3:
|
|
calls.update(
|
|
url=url,
|
|
event_type=event_type,
|
|
secret=secret,
|
|
max_attempts=max_attempts,
|
|
) or True,
|
|
)
|
|
|
|
result = run_webhook_test(WebhookTestIn(channel="custom"))
|
|
|
|
assert result["ok"] is True
|
|
assert calls == {
|
|
"url": "https://example.com/tickflow",
|
|
"event_type": "test",
|
|
"secret": "secret",
|
|
"max_attempts": 1,
|
|
}
|
|
|
|
|
|
def test_email_sends_with_saved_smtp_config(monkeypatch):
|
|
calls = {}
|
|
config = {
|
|
"host": "smtp.example.com",
|
|
"port": 465,
|
|
"security": "ssl",
|
|
"username": "bot@example.com",
|
|
"from_address": "bot@example.com",
|
|
"to_addresses": ["alerts@example.com"],
|
|
}
|
|
monkeypatch.setattr("app.services.preferences.get_email_smtp_config", lambda: config)
|
|
monkeypatch.setattr("app.secrets_store.get_email_smtp_password", lambda: "password")
|
|
monkeypatch.setattr(
|
|
"app.services.email_adapter.send_email",
|
|
lambda cfg, password, subject, body, max_attempts=2:
|
|
calls.update(config=cfg, password=password, subject=subject, max_attempts=max_attempts) or True,
|
|
)
|
|
|
|
result = run_webhook_test(WebhookTestIn(channel="email"))
|
|
|
|
assert result["ok"] is True
|
|
assert calls["config"] == config
|
|
assert calls["password"] == "password"
|
|
assert calls["max_attempts"] == 1
|
|
|
|
|
|
def test_unknown_channel_rejected_by_pydantic():
|
|
with pytest.raises(ValidationError):
|
|
WebhookTestIn(channel="sms")
|