From 41844d49a0c262a0c69c1afd592d22482950d63f Mon Sep 17 00:00:00 2001 From: Vassiliy Yegorov Date: Sat, 4 Jul 2026 16:01:14 +0700 Subject: [PATCH] test(notify): assert per-channel results on decrypt-fail and unknown-type Co-Authored-By: Claude Opus 4.8 (1M context) --- internal/notify/notify_test.go | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/internal/notify/notify_test.go b/internal/notify/notify_test.go index 63ea1db..7ea50d9 100644 --- a/internal/notify/notify_test.go +++ b/internal/notify/notify_test.go @@ -3,6 +3,7 @@ package notify import ( "context" "encoding/json" + "errors" "net" "net/http" "net/http/httptest" @@ -400,9 +401,13 @@ func TestDispatcherSkipsUnknownChannelType(t *testing.T) { {ID: uuid.New(), ProjectID: projectID, Type: "carrier-pigeon", Config: json.RawMessage(`{}`), Enabled: true}, } d := NewDispatcher(&mockChannelStore{channels: channels}, &mockDecryptor{}) - if _, err := d.Send(context.Background(), projectID, Event{Project: "p", Domain: "d", Status: "drift"}); err != nil { + results, err := d.Send(context.Background(), projectID, Event{Project: "p", Domain: "d", Status: "drift"}) + if err != nil { t.Fatalf("unexpected error for unknown channel type: %v", err) } + if len(results) != 0 { + t.Fatalf("results = %d, want 0: unknown channel type must not produce a result", len(results)) + } } func TestDispatcherDecryptFailureIsAggregatedNotFatal(t *testing.T) { @@ -423,13 +428,38 @@ func TestDispatcherDecryptFailureIsAggregatedNotFatal(t *testing.T) { // default; swap in an allowPrivate webhook so this test can still hit it. d.byType["webhook"] = &Webhook{HTTP: whSrv.Client(), allowPrivate: true} - _, err := d.Send(context.Background(), projectID, Event{Project: "p", Domain: "d", Status: "drift"}) + results, err := d.Send(context.Background(), projectID, Event{Project: "p", Domain: "d", Status: "drift"}) if err == nil { t.Fatal("expected error due to decrypt failure") } if !whCalled { t.Error("expected webhook channel to still be attempted after telegram decrypt failure") } + + if len(results) != 2 { + t.Fatalf("results = %d, want 2", len(results)) + } + byType := make(map[string]ChannelResult, len(results)) + for _, r := range results { + byType[r.Type] = r + } + tg, ok := byType["telegram"] + if !ok { + t.Fatal("expected a telegram result") + } + if tg.Err == nil { + t.Fatalf("telegram result = %+v, want decrypt error", tg) + } + if !errors.Is(tg.Err, errBoom) { + t.Fatalf("telegram result err = %v, want errBoom", tg.Err) + } + wh, ok := byType["webhook"] + if !ok { + t.Fatal("expected a webhook result") + } + if wh.Err != nil { + t.Fatalf("webhook result = %+v, want ok result (decrypt failure on telegram must not fail webhook)", wh) + } } // notifierFunc adapts a function to the Notifier interface for tests.