106 lines
3.7 KiB
Go
106 lines
3.7 KiB
Go
package email
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.sendico.io/tech/sxchnge/notifications/model"
|
|
)
|
|
|
|
func TestDriversRenderWirePayload(t *testing.T) {
|
|
for _, driver := range []Driver{SendGrid, Resend} {
|
|
t.Run(string(driver), func(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Header.Get("Authorization") != "Bearer test-secret" {
|
|
t.Error("missing authorization")
|
|
}
|
|
var body map[string]any
|
|
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if body["subject"] != "Completed" {
|
|
t.Errorf("subject: %v", body)
|
|
}
|
|
if driver == SendGrid {
|
|
if body["template_id"] != nil {
|
|
t.Error("provider-managed templates must not be used")
|
|
}
|
|
p := body["personalizations"].([]any)[0].(map[string]any)
|
|
if p["to"].([]any)[0].(map[string]any)["email"] != "user@example.com" {
|
|
t.Error("wrong recipient")
|
|
}
|
|
content := body["content"].([]any)
|
|
if len(content) != 2 || content[1].(map[string]any)["value"] != "<p>A & B</p>" {
|
|
t.Error("wrong body")
|
|
}
|
|
} else {
|
|
if r.Header.Get("Idempotency-Key") != "delivery-id" {
|
|
t.Error("missing idempotency key")
|
|
}
|
|
if body["html"] != "<p>A & B</p>" || body["text"] != "A & B" {
|
|
t.Error("wrong body")
|
|
}
|
|
}
|
|
w.WriteHeader(http.StatusAccepted)
|
|
}))
|
|
defer server.Close()
|
|
c := client{http: server.Client(), key: "test-secret", endpoint: server.URL, settings: Settings{SenderAddress: "sender@example.com", SenderName: "SXCHNGE"}}
|
|
var sender Sender = &sendgrid{c}
|
|
if driver == Resend {
|
|
sender = &resend{c}
|
|
}
|
|
outcome := sender.Send(context.Background(), "delivery-id", model.Email{Address: "user@example.com", Subject: "Completed", HTML: "<p>A & B</p>", Text: "A & B"})
|
|
if outcome.State != model.Accepted {
|
|
t.Fatal(outcome)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
func TestProviderFailures(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
code int
|
|
state model.State
|
|
}{{429, model.RetryWait}, {400, model.Failed}, {401, model.Failed}, {403, model.Failed}, {500, model.Unknown}, {408, model.Unknown}, {302, model.Failed}} {
|
|
t.Run(http.StatusText(tc.code), func(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Retry-After", "120")
|
|
w.WriteHeader(tc.code)
|
|
_, _ = w.Write([]byte("secret provider response"))
|
|
}))
|
|
defer server.Close()
|
|
c := client{http: server.Client(), endpoint: server.URL}
|
|
out := c.post(context.Background(), "", struct{}{})
|
|
if out.State != tc.state || strings.Contains(out.Code, "secret") {
|
|
t.Fatal(out)
|
|
}
|
|
if tc.code == 429 && out.RetryAfter != 2*time.Minute {
|
|
t.Fatal(out)
|
|
}
|
|
})
|
|
}
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
c := client{http: http.DefaultClient, endpoint: "http://127.0.0.1:1"}
|
|
if out := c.post(ctx, "", struct{}{}); out.State != model.Unknown {
|
|
t.Fatal(out)
|
|
}
|
|
}
|
|
func TestDriverConfig(t *testing.T) {
|
|
t.Setenv("EMAIL_TEST_KEY", "secret")
|
|
for _, driver := range []Driver{SendGrid, Resend} {
|
|
if _, err := New(Config{Driver: driver, Settings: map[string]any{"api_key_env": "EMAIL_TEST_KEY", "sender_address": "sender@example.com"}}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
for _, settings := range []map[string]any{{"api_key_env": "MISSING_KEY", "sender_address": "sender@example.com"}, {"api_key_env": "EMAIL_TEST_KEY", "sender_address": "bad"}, {"api_key_env": "EMAIL_TEST_KEY", "sender_address": "sender@example.com", "typo": true}} {
|
|
if _, err := New(Config{Driver: Resend, Settings: settings}); err == nil {
|
|
t.Fatal("accepted invalid driver config")
|
|
}
|
|
}
|
|
}
|