Go · 3137 bytes Raw Blame History
1 // SPDX-License-Identifier: AGPL-3.0-or-later
2
3 package email
4
5 import (
6 "context"
7 "encoding/json"
8 "io"
9 "net/http"
10 "net/http/httptest"
11 "strings"
12 "testing"
13 )
14
15 func TestResendSender_Send_SuccessShapesRequest(t *testing.T) {
16 t.Parallel()
17 var (
18 gotMethod string
19 gotPath string
20 gotAuth string
21 gotCT string
22 gotBody resendPayload
23 )
24 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
25 gotMethod = r.Method
26 gotPath = r.URL.Path
27 gotAuth = r.Header.Get("Authorization")
28 gotCT = r.Header.Get("Content-Type")
29 raw, _ := io.ReadAll(r.Body)
30 _ = json.Unmarshal(raw, &gotBody)
31 w.WriteHeader(http.StatusOK)
32 _, _ = w.Write([]byte(`{"id":"00000000-0000-0000-0000-000000000000"}`))
33 }))
34 defer srv.Close()
35
36 s := &ResendSender{
37 APIKey: "re_test_secret",
38 From: "noreply@shithub.sh",
39 Endpoint: srv.URL,
40 }
41 err := s.Send(context.Background(), Message{
42 To: "alice@example.com", Subject: "hi", HTML: "<b>hi</b>", Text: "hi",
43 })
44 if err != nil {
45 t.Fatalf("Send: %v", err)
46 }
47 if gotMethod != http.MethodPost {
48 t.Errorf("method = %q, want POST", gotMethod)
49 }
50 if gotPath != "/" {
51 t.Errorf("path = %q, want /", gotPath)
52 }
53 if gotAuth != "Bearer re_test_secret" {
54 t.Errorf("Authorization = %q, want Bearer re_test_secret", gotAuth)
55 }
56 if gotCT != "application/json" {
57 t.Errorf("Content-Type = %q, want application/json", gotCT)
58 }
59 if gotBody.From != "noreply@shithub.sh" {
60 t.Errorf("body.From = %q, want default From", gotBody.From)
61 }
62 if gotBody.To != "alice@example.com" || gotBody.Subject != "hi" ||
63 gotBody.HTML != "<b>hi</b>" || gotBody.Text != "hi" {
64 t.Errorf("body fields wrong: %+v", gotBody)
65 }
66 }
67
68 func TestResendSender_Send_PerMessageFromOverridesDefault(t *testing.T) {
69 t.Parallel()
70 var gotFrom string
71 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
72 var p resendPayload
73 raw, _ := io.ReadAll(r.Body)
74 _ = json.Unmarshal(raw, &p)
75 gotFrom = p.From
76 w.WriteHeader(http.StatusOK)
77 }))
78 defer srv.Close()
79
80 s := &ResendSender{APIKey: "k", From: "default@x", Endpoint: srv.URL}
81 if err := s.Send(context.Background(), Message{
82 From: "override@x", To: "a@x", Subject: "s", HTML: "H", Text: "T",
83 }); err != nil {
84 t.Fatalf("Send: %v", err)
85 }
86 if gotFrom != "override@x" {
87 t.Errorf("From = %q, want override@x", gotFrom)
88 }
89 }
90
91 func TestResendSender_Send_PropagatesAPIError(t *testing.T) {
92 t.Parallel()
93 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
94 w.WriteHeader(http.StatusUnauthorized)
95 _, _ = w.Write([]byte(`{"name":"missing_api_key","message":"API key is missing"}`))
96 }))
97 defer srv.Close()
98
99 s := &ResendSender{APIKey: "bad", From: "noreply@x", Endpoint: srv.URL}
100 err := s.Send(context.Background(), Message{To: "a@x", Subject: "s", HTML: "H", Text: "T"})
101 if err == nil {
102 t.Fatal("expected error on 401, got nil")
103 }
104 if !strings.Contains(err.Error(), "401") {
105 t.Errorf("error missing status code: %v", err)
106 }
107 if !strings.Contains(err.Error(), "missing_api_key") {
108 t.Errorf("error missing API body snippet: %v", err)
109 }
110 }
111