Files
Cyrene_v2/plugins/channels/webhook/webhook_test.go
T

182 lines
4.8 KiB
Go

package webhook
import (
"bytes"
"context"
"errors"
"net/http"
"net/http/httptest"
"testing"
"time"
"git.yeij.top/AskaEth/Cyrene_v2/internal/channel/adapter"
)
func TestName(t *testing.T) {
t.Parallel()
if got := New().Name(); got != "webhook" {
t.Errorf("Name() = %q, want webhook", got)
}
}
func TestConfigSnapshot(t *testing.T) {
t.Parallel()
cfg := Config{
EndpointPath: "/cb",
ChannelID: "ch-1",
ChannelName: "My Hook",
Secret: "s3cr3t",
Methods: []string{http.MethodPost, http.MethodPut},
}
got := New(WithConfig(cfg)).Config()
if got["endpointPath"] != "/cb" {
t.Errorf("Config() endpointPath = %v, want /cb", got["endpointPath"])
}
if got["channelId"] != "ch-1" {
t.Errorf("Config() channelId = %v, want ch-1", got["channelId"])
}
if got["secret"] != "s3cr3t" {
t.Errorf("Config() secret = %v, want s3cr3t", got["secret"])
}
if got["signatureHeader"] != defaultSignatureHeader {
t.Errorf("Config() signatureHeader = %v, want %s", got["signatureHeader"], defaultSignatureHeader)
}
}
func TestConnectDisconnectHealthCheck(t *testing.T) {
t.Parallel()
a := New()
if a.IsConnected() {
t.Error("IsConnected() = true before Connect, want false")
}
if err := a.HealthCheck(context.Background()); !errors.Is(err, adapter.ErrNotConnected) {
t.Errorf("HealthCheck() before connect error = %v, want ErrNotConnected", err)
}
if err := a.Connect(context.Background()); err != nil {
t.Errorf("Connect() error = %v", err)
}
if !a.IsConnected() {
t.Error("IsConnected() = false after Connect, want true")
}
if err := a.HealthCheck(context.Background()); err != nil {
t.Errorf("HealthCheck() after connect error = %v", err)
}
if err := a.Disconnect(context.Background()); err != nil {
t.Errorf("Disconnect() error = %v", err)
}
if a.IsConnected() {
t.Error("IsConnected() = true after Disconnect, want false")
}
// Idempotent.
if err := a.Disconnect(context.Background()); err != nil {
t.Errorf("Disconnect() second call error = %v", err)
}
if err := a.Connect(context.Background()); err != nil {
t.Errorf("Connect() second call error = %v", err)
}
}
func TestCapabilitiesProactiveDisabled(t *testing.T) {
t.Parallel()
caps := New().Capabilities()
if caps.Proactive {
t.Error("Capabilities().Proactive = true, want false")
}
if caps.MaxMessageLength <= 0 {
t.Errorf("Capabilities().MaxMessageLength = %d, want normalized nonzero", caps.MaxMessageLength)
}
if caps.RecommendBurstMax <= 0 {
t.Errorf("Capabilities().RecommendBurstMax = %d, want normalized nonzero", caps.RecommendBurstMax)
}
}
func TestListChannelsConfigured(t *testing.T) {
t.Parallel()
a := New(WithConfig(Config{ChannelID: "ch-1", ChannelName: "Hook"}))
chans, err := a.ListChannels(context.Background())
if err != nil {
t.Fatalf("ListChannels() error = %v", err)
}
if len(chans) != 1 {
t.Fatalf("ListChannels() len = %d, want 1", len(chans))
}
if chans[0].ChannelID != "ch-1" || chans[0].ChannelName != "Hook" {
t.Errorf("ListChannels()[0] = %+v, want {ch-1 Hook}", chans[0])
}
}
func TestListChannelsEmpty(t *testing.T) {
t.Parallel()
chans, err := New().ListChannels(context.Background())
if err != nil {
t.Fatalf("ListChannels() error = %v", err)
}
if len(chans) != 0 {
t.Errorf("ListChannels() len = %d, want 0", len(chans))
}
}
func TestSendProactiveUnsupported(t *testing.T) {
t.Parallel()
err := New().SendProactive(context.Background(), adapter.UnifiedMessage{})
if !errors.Is(err, adapter.ErrUnsupported) {
t.Errorf("SendProactive() error = %v, want ErrUnsupported", err)
}
}
func TestSendMessageUnsupported(t *testing.T) {
t.Parallel()
err := New().SendMessage(context.Background(), adapter.UnifiedResponse{})
if !errors.Is(err, adapter.ErrUnsupported) {
t.Errorf("SendMessage() error = %v, want ErrUnsupported", err)
}
}
func TestSetMessageHandlerAndClear(t *testing.T) {
t.Parallel()
a := New()
a.SetMessageHandler(func(context.Context, adapter.UnifiedMessage) {})
// A nil handler clears the installed one, so delivery must fail.
a.SetMessageHandler(nil)
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, "/webhook",
bytes.NewReader([]byte(`{"content":"hi"}`)))
req.Header.Set("Content-Type", "application/json")
a.InboundHandler().ServeHTTP(rec, req)
if rec.Code != http.StatusServiceUnavailable {
t.Errorf("status = %d, want 503", rec.Code)
}
}
func TestReadMessagesBlocksUntilCancel(t *testing.T) {
a := New()
ctx, cancel := context.WithCancel(context.Background())
cancel() // pre-cancel so the loop returns deterministically
done := make(chan struct{})
go func() {
a.ReadMessages(ctx, func(adapter.UnifiedMessage) {})
close(done)
}()
select {
case <-done:
case <-time.After(2 * time.Second):
t.Fatal("ReadMessages() did not return on canceled context")
}
}