mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 19:01:08 +02:00
mana-search-go → mana-search mana-notify-go → mana-notify mana-crawler-go → mana-crawler mana-api-gateway-go → mana-api-gateway Legacy NestJS versions are deleted, suffix no longer needed. Updated all references in docker-compose, CLAUDE.md, package.json, Forgejo workflows, and service package.json files. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
166 lines
4.3 KiB
Go
166 lines
4.3 KiB
Go
package channel
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
)
|
|
|
|
func TestWebhookService_Send(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
handler http.HandlerFunc
|
|
msg WebhookMessage
|
|
wantOK bool
|
|
wantStatus int
|
|
}{
|
|
{
|
|
name: "successful POST with 200",
|
|
handler: func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
t.Errorf("expected POST, got %s", r.Method)
|
|
}
|
|
if ct := r.Header.Get("Content-Type"); ct != "application/json" {
|
|
t.Errorf("expected Content-Type application/json, got %s", ct)
|
|
}
|
|
if ua := r.Header.Get("User-Agent"); ua != "ManaNotify/1.0" {
|
|
t.Errorf("expected User-Agent ManaNotify/1.0, got %s", ua)
|
|
}
|
|
w.WriteHeader(http.StatusOK)
|
|
},
|
|
msg: WebhookMessage{Body: map[string]any{"test": true}},
|
|
wantOK: true,
|
|
wantStatus: 200,
|
|
},
|
|
{
|
|
name: "successful PUT",
|
|
handler: func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPut {
|
|
t.Errorf("expected PUT, got %s", r.Method)
|
|
}
|
|
w.WriteHeader(http.StatusOK)
|
|
},
|
|
msg: WebhookMessage{Method: "PUT", Body: map[string]any{"update": true}},
|
|
wantOK: true,
|
|
wantStatus: 200,
|
|
},
|
|
{
|
|
name: "custom headers are sent",
|
|
handler: func(w http.ResponseWriter, r *http.Request) {
|
|
if v := r.Header.Get("X-Custom"); v != "test-value" {
|
|
t.Errorf("expected X-Custom=test-value, got %s", v)
|
|
}
|
|
w.WriteHeader(http.StatusOK)
|
|
},
|
|
msg: WebhookMessage{
|
|
Headers: map[string]string{"X-Custom": "test-value"},
|
|
Body: map[string]any{},
|
|
},
|
|
wantOK: true,
|
|
wantStatus: 200,
|
|
},
|
|
{
|
|
name: "body is sent as JSON",
|
|
handler: func(w http.ResponseWriter, r *http.Request) {
|
|
body, _ := io.ReadAll(r.Body)
|
|
var m map[string]any
|
|
if err := json.Unmarshal(body, &m); err != nil {
|
|
t.Errorf("body is not valid JSON: %v", err)
|
|
}
|
|
if m["event"] != "test" {
|
|
t.Errorf("expected event=test, got %v", m["event"])
|
|
}
|
|
w.WriteHeader(http.StatusOK)
|
|
},
|
|
msg: WebhookMessage{Body: map[string]any{"event": "test"}},
|
|
wantOK: true,
|
|
wantStatus: 200,
|
|
},
|
|
{
|
|
name: "server error returns failure",
|
|
handler: func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
},
|
|
msg: WebhookMessage{Body: map[string]any{}},
|
|
wantOK: false,
|
|
wantStatus: 500,
|
|
},
|
|
{
|
|
name: "404 returns failure",
|
|
handler: func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
},
|
|
msg: WebhookMessage{Body: map[string]any{}},
|
|
wantOK: false,
|
|
wantStatus: 404,
|
|
},
|
|
{
|
|
name: "201 is treated as success",
|
|
handler: func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusCreated)
|
|
},
|
|
msg: WebhookMessage{Body: map[string]any{}},
|
|
wantOK: true,
|
|
wantStatus: 201,
|
|
},
|
|
}
|
|
|
|
svc := NewWebhookService()
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
srv := httptest.NewServer(tt.handler)
|
|
defer srv.Close()
|
|
|
|
tt.msg.URL = srv.URL
|
|
result := svc.Send(context.Background(), &tt.msg)
|
|
|
|
if result.Success != tt.wantOK {
|
|
t.Fatalf("Success = %v, want %v (error: %s)", result.Success, tt.wantOK, result.Error)
|
|
}
|
|
if tt.wantStatus != 0 && result.StatusCode != tt.wantStatus {
|
|
t.Fatalf("StatusCode = %d, want %d", result.StatusCode, tt.wantStatus)
|
|
}
|
|
if result.DurationMs < 0 {
|
|
t.Fatalf("DurationMs should be >= 0, got %d", result.DurationMs)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWebhookService_Send_InvalidURL(t *testing.T) {
|
|
svc := NewWebhookService()
|
|
result := svc.Send(context.Background(), &WebhookMessage{
|
|
URL: "http://localhost:1", // unreachable port
|
|
Body: map[string]any{},
|
|
})
|
|
|
|
if result.Success {
|
|
t.Fatal("expected failure for unreachable URL")
|
|
}
|
|
if result.Error == "" {
|
|
t.Fatal("expected non-empty error")
|
|
}
|
|
}
|
|
|
|
func TestWebhookService_Send_DefaultMethod(t *testing.T) {
|
|
var gotMethod string
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
gotMethod = r.Method
|
|
w.WriteHeader(http.StatusOK)
|
|
}))
|
|
defer srv.Close()
|
|
|
|
svc := NewWebhookService()
|
|
svc.Send(context.Background(), &WebhookMessage{
|
|
URL: srv.URL,
|
|
Body: map[string]any{},
|
|
})
|
|
|
|
if gotMethod != "POST" {
|
|
t.Fatalf("default method should be POST, got %s", gotMethod)
|
|
}
|
|
}
|