template-monorepo/internal/model/notification/provider/email/chain_test.go

81 lines
2.3 KiB
Go
Raw Normal View History

package email_test
import (
"context"
"fmt"
"testing"
"gateway/internal/model/notification/provider/email"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const testRecipientEmail = "x@test.com"
func TestChain_Send_FailoverToSecondProvider(t *testing.T) {
primary := email.NewMockSender(
email.WithMockName("primary"),
email.WithMockSort(1),
email.WithMockError(fmt.Errorf("primary down")),
)
backup := email.NewMockSender(
email.WithMockName("backup"),
email.WithMockSort(2),
email.WithMockMessageID("backup-123"),
)
chain := email.NewChain(primary, backup)
provider, id, err := chain.Send(context.Background(), &email.Message{
From: "noreply@test.com",
To: []string{"user@test.com"},
Subject: "verify",
Body: "<p>code</p>",
})
require.NoError(t, err)
assert.Equal(t, "backup", provider)
assert.Equal(t, "backup-123", id)
assert.Len(t, primary.Calls(), 1)
assert.Len(t, backup.Calls(), 1)
}
func TestChain_Send_TriesLowerSortFirst(t *testing.T) {
var order []string
mk := func(name string, sort int, fail bool) *email.MockSender {
m := email.NewMockSender(email.WithMockName(name), email.WithMockSort(sort))
m.SendHook = func(context.Context, *email.Message) (string, error) {
order = append(order, name)
if fail {
return "", fmt.Errorf("%s failed", name)
}
return name + "-id", nil
}
return m
}
// Unsorted registration; chain must try a(1) → b(2) succeed, never c(3).
chain := email.NewChain(mk("c", 3, true), mk("a", 1, true), mk("b", 2, false))
provider, _, err := chain.Send(context.Background(), &email.Message{To: []string{testRecipientEmail}})
require.NoError(t, err)
assert.Equal(t, "b", provider)
assert.Equal(t, []string{"a", "b"}, order)
}
func TestChain_Send_AllProvidersFail(t *testing.T) {
chain := email.NewChain(
email.ErrSender("a", 1, fmt.Errorf("a fail")),
email.ErrSender("b", 2, fmt.Errorf("b fail")),
)
_, _, err := chain.Send(context.Background(), &email.Message{To: []string{testRecipientEmail}})
require.Error(t, err)
assert.Contains(t, err.Error(), "all providers failed")
}
func TestChain_Send_NoSenders(t *testing.T) {
chain := email.NewChain()
_, _, err := chain.Send(context.Background(), &email.Message{To: []string{testRecipientEmail}})
require.Error(t, err)
assert.Contains(t, err.Error(), "no senders")
}