В Pachca/Telegram текст сразу после открывающих тройных бэктиков трактуется как указатель языка code-блока и не отображается. Из-за этого пропадала первая строка уведомления — [время] METHOD host/URI, то есть путь и метод запроса не были видны. Добавлен \n после фенса; тест теперь проверяет перевод строки и наличие URI в выводе. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
155 lines
4.0 KiB
Go
155 lines
4.0 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
var errSend = errors.New("send failed")
|
|
|
|
func sampleData() RequestData {
|
|
return RequestData{
|
|
Time: time.Date(2026, 6, 14, 10, 0, 0, 0, time.UTC),
|
|
Method: "POST",
|
|
Host: "example.com",
|
|
URL: "/telegram",
|
|
RemoteAddr: "1.2.3.4",
|
|
Header: http.Header{"X-Test": []string{"v"}},
|
|
Body: "payload<>",
|
|
}
|
|
}
|
|
|
|
func TestFormatMarkdown(t *testing.T) {
|
|
out := formatMarkdown(sampleData())
|
|
if !strings.HasPrefix(out, "```\n") || !strings.HasSuffix(out, "```") {
|
|
// Перевод строки после открывающего фенса обязателен: иначе markdown
|
|
// в Pachca/Telegram съедает первую строку как указатель языка, и путь
|
|
// запроса (METHOD host/url) пропадает из уведомления.
|
|
t.Fatalf("expected ```\\n wrapping, got: %q", out)
|
|
}
|
|
if !strings.Contains(out, "/telegram") {
|
|
t.Errorf("missing request path/url: %q", out)
|
|
}
|
|
if !strings.Contains(out, "POST") || !strings.Contains(out, "1.2.3.4") {
|
|
t.Errorf("missing fields: %q", out)
|
|
}
|
|
if !strings.Contains(out, "X-Test: v") {
|
|
t.Errorf("missing header: %q", out)
|
|
}
|
|
}
|
|
|
|
func TestFormatHTML(t *testing.T) {
|
|
out := formatHTML(sampleData())
|
|
if !strings.Contains(out, "<pre>") || !strings.Contains(out, "</pre>") {
|
|
t.Fatalf("expected <pre> wrapping, got: %q", out)
|
|
}
|
|
if !strings.Contains(out, "payload<>") {
|
|
t.Errorf("body not escaped: %q", out)
|
|
}
|
|
if strings.Contains(out, "payload<>") {
|
|
t.Errorf("unescaped body present: %q", out)
|
|
}
|
|
}
|
|
|
|
type mockNotifier struct {
|
|
called bool
|
|
err error
|
|
}
|
|
|
|
func (m *mockNotifier) Send(d RequestData) error {
|
|
m.called = true
|
|
return m.err
|
|
}
|
|
|
|
func TestHandlerRouting(t *testing.T) {
|
|
tg := &mockNotifier{}
|
|
h := makeHandler(map[string]Notifier{"telegram": tg})
|
|
|
|
rec := httptest.NewRecorder()
|
|
h(rec, httptest.NewRequest("POST", "/telegram", strings.NewReader("x")))
|
|
if rec.Code != 200 || !tg.called {
|
|
t.Fatalf("telegram: code=%d called=%v", rec.Code, tg.called)
|
|
}
|
|
|
|
rec = httptest.NewRecorder()
|
|
h(rec, httptest.NewRequest("POST", "/unknown", strings.NewReader("x")))
|
|
if rec.Code != 404 {
|
|
t.Fatalf("unknown: code=%d", rec.Code)
|
|
}
|
|
|
|
rec = httptest.NewRecorder()
|
|
h(rec, httptest.NewRequest("POST", "/", nil))
|
|
if rec.Code != 404 {
|
|
t.Fatalf("empty: code=%d", rec.Code)
|
|
}
|
|
}
|
|
|
|
func TestHandlerSendError(t *testing.T) {
|
|
failing := &mockNotifier{err: errSend}
|
|
h := makeHandler(map[string]Notifier{"telegram": failing})
|
|
rec := httptest.NewRecorder()
|
|
h(rec, httptest.NewRequest("POST", "/telegram", strings.NewReader("x")))
|
|
if rec.Code != 502 {
|
|
t.Fatalf("expected 502, got %d", rec.Code)
|
|
}
|
|
}
|
|
|
|
func TestBuildNotifiersEmpty(t *testing.T) {
|
|
n, err := BuildNotifiers(&Config{})
|
|
if err != nil {
|
|
t.Fatalf("unexpected err: %v", err)
|
|
}
|
|
if len(n) != 0 {
|
|
t.Fatalf("expected empty map, got %d", len(n))
|
|
}
|
|
}
|
|
|
|
func TestBuildNotifiersPachcaMissingURL(t *testing.T) {
|
|
_, err := BuildNotifiers(&Config{Pachca: &ConfigPachca{}})
|
|
if err == nil {
|
|
t.Fatal("expected error for empty webhook_url")
|
|
}
|
|
}
|
|
|
|
func TestBuildNotifiersEmailNoRecipients(t *testing.T) {
|
|
_, err := BuildNotifiers(&Config{Email: &ConfigEmail{
|
|
SMTPAddr: "smtp.example.com:587",
|
|
From: "logger@example.com",
|
|
To: nil,
|
|
}})
|
|
if err == nil {
|
|
t.Fatal("expected error for zero recipients")
|
|
}
|
|
}
|
|
|
|
func TestBuildNotifiersEmailBadSMTPAddr(t *testing.T) {
|
|
_, err := BuildNotifiers(&Config{Email: &ConfigEmail{
|
|
SMTPAddr: "no-port",
|
|
From: "logger@example.com",
|
|
To: []string{"a@example.com"},
|
|
}})
|
|
if err == nil {
|
|
t.Fatal("expected error for smtp_addr without port")
|
|
}
|
|
}
|
|
|
|
func TestBuildNotifiersEmailOK(t *testing.T) {
|
|
n, err := BuildNotifiers(&Config{Email: &ConfigEmail{
|
|
SMTPAddr: "smtp.example.com:587",
|
|
Username: "u",
|
|
Password: "p",
|
|
From: "logger@example.com",
|
|
To: []string{"a@example.com"},
|
|
}})
|
|
if err != nil {
|
|
t.Fatalf("unexpected err: %v", err)
|
|
}
|
|
if _, ok := n["email"]; !ok {
|
|
t.Fatal("email notifier not built")
|
|
}
|
|
}
|