a9b6234208
Motivation: 让通知模板能够将 action、event 等原始枚举值映射为可读中文文案,并支持按事件名后缀匹配;同时简化 SafeW 消息发送格式,避免 Markdown 转义引入的显示问题。 Changes: * 新增 `case` 模板函数,按值匹配 key/文案并支持末尾奇数参数作为默认值 * `case` 匹配兼容事件名后缀(如 trade.close 匹配 .close) * `line` 前缀自动去除末尾冒号,避免重复冒号 * 模板渲染前自动注入 event 字段,便于模板按事件名取值 * SafeW 消息改为纯文本发送,移除 MarkdownV2 转义
147 lines
4.3 KiB
Go
147 lines
4.3 KiB
Go
package adapter
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"aiaa-notification-service/internal/config"
|
|
)
|
|
|
|
func TestNewSenderSafew(t *testing.T) {
|
|
s, err := NewSender("safew", &config.SMTPConfig{}, nil)
|
|
if err != nil {
|
|
t.Fatalf("NewSender(safew): %v", err)
|
|
}
|
|
if s.Type() != "safew" {
|
|
t.Fatalf("Type() = %q, want safew", s.Type())
|
|
}
|
|
}
|
|
|
|
func TestSafeWSenderSendSuccess(t *testing.T) {
|
|
var gotPath string
|
|
var gotBody map[string]any
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
gotPath = r.URL.Path
|
|
raw, _ := io.ReadAll(r.Body)
|
|
if err := json.Unmarshal(raw, &gotBody); err != nil {
|
|
t.Errorf("unmarshal request: %v", err)
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_, _ = w.Write([]byte(`{"ok":true,"result":{}}`))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
sender := &SafeWSender{apiBase: srv.URL}
|
|
cfg, _ := json.Marshal(map[string]any{"token": "tok-1", "chat_id": "123456789"})
|
|
if err := sender.Send("hello_world.", "price=1.5", cfg); err != nil {
|
|
t.Fatalf("Send: %v", err)
|
|
}
|
|
if gotPath != "/bottok-1/sendMessage" {
|
|
t.Fatalf("path = %q, want /bottok-1/sendMessage", gotPath)
|
|
}
|
|
if gotBody["chat_id"] != "123456789" {
|
|
t.Fatalf("chat_id = %#v, want \"123456789\"", gotBody["chat_id"])
|
|
}
|
|
if gotBody["parse_mode"] != nil && gotBody["parse_mode"] != "" {
|
|
t.Fatalf("parse_mode = %#v, want omitted/plain", gotBody["parse_mode"])
|
|
}
|
|
wantText := "hello_world.\nprice=1.5"
|
|
if gotBody["text"] != wantText {
|
|
t.Fatalf("text = %#v, want %#v", gotBody["text"], wantText)
|
|
}
|
|
}
|
|
|
|
func TestSafeWSenderSendNumericChatID(t *testing.T) {
|
|
var gotBody map[string]any
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
raw, _ := io.ReadAll(r.Body)
|
|
_ = json.Unmarshal(raw, &gotBody)
|
|
w.WriteHeader(http.StatusOK)
|
|
_, _ = w.Write([]byte(`{"ok":true}`))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
sender := &SafeWSender{apiBase: srv.URL}
|
|
cfg := json.RawMessage(`{"token":"tok","chat_id":123456789}`)
|
|
if err := sender.Send("t", "c", cfg); err != nil {
|
|
t.Fatalf("Send: %v", err)
|
|
}
|
|
if gotBody["chat_id"] != "123456789" {
|
|
t.Fatalf("chat_id = %#v, want string \"123456789\"", gotBody["chat_id"])
|
|
}
|
|
}
|
|
|
|
func TestSafeWSenderSendOKFalse(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
_, _ = w.Write([]byte(`{"ok":false,"description":"chat not found"}`))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
sender := &SafeWSender{apiBase: srv.URL}
|
|
cfg, _ := json.Marshal(map[string]string{"token": "tok", "chat_id": "1"})
|
|
err := sender.Send("t", "c", cfg)
|
|
if err == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
if !strings.Contains(err.Error(), "chat not found") {
|
|
t.Fatalf("error %q should contain description", err)
|
|
}
|
|
}
|
|
|
|
func TestSafeWSenderSendHTTPError(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
_, _ = w.Write([]byte(`{"ok":false,"description":"Unauthorized"}`))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
sender := &SafeWSender{apiBase: srv.URL}
|
|
cfg, _ := json.Marshal(map[string]string{"token": "bad", "chat_id": "1"})
|
|
err := sender.Send("t", "c", cfg)
|
|
if err == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
if !strings.Contains(err.Error(), "Unauthorized") {
|
|
t.Fatalf("error %q should contain description", err)
|
|
}
|
|
}
|
|
|
|
func TestSafeWSenderSendMissingFields(t *testing.T) {
|
|
hits := 0
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
hits++
|
|
w.WriteHeader(http.StatusOK)
|
|
_, _ = w.Write([]byte(`{"ok":true}`))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
sender := &SafeWSender{apiBase: srv.URL}
|
|
cases := []json.RawMessage{
|
|
json.RawMessage(`{"chat_id":"1"}`),
|
|
json.RawMessage(`{"token":"tok"}`),
|
|
json.RawMessage(`{"token":" ","chat_id":"1"}`),
|
|
json.RawMessage(`{"token":"tok","chat_id":""}`),
|
|
json.RawMessage(`{"token":"tok","chat_id":null}`),
|
|
}
|
|
for _, cfg := range cases {
|
|
if err := sender.Send("t", "c", cfg); err == nil {
|
|
t.Fatalf("expected error for config %s", cfg)
|
|
}
|
|
}
|
|
if hits != 0 {
|
|
t.Fatalf("unexpected HTTP calls: %d", hits)
|
|
}
|
|
|
|
if err := sender.Send("t", "c", json.RawMessage(`{`)); err == nil {
|
|
t.Fatal("expected error for invalid json")
|
|
}
|
|
if hits != 0 {
|
|
t.Fatalf("unexpected HTTP calls after invalid json: %d", hits)
|
|
}
|
|
}
|