feat: mail service
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -35,6 +36,10 @@ func TestMailServiceRESTCompatibilitySendEmailCodeSent(t *testing.T) {
|
||||
assert.Equal(t, http.StatusOK, response.StatusCode)
|
||||
assert.JSONEq(t, `{"challenge_id":"challenge-1"}`, response.Body)
|
||||
assert.Equal(t, 1, harness.mailServer.CallCount())
|
||||
deliveries := harness.mailServer.RecordedDeliveries()
|
||||
require.Len(t, deliveries, 1)
|
||||
assert.Equal(t, "en", deliveries[0].Locale)
|
||||
assert.Equal(t, "challenge-1", deliveries[0].IdempotencyKey)
|
||||
}
|
||||
|
||||
func TestMailServiceRESTCompatibilitySendEmailCodeSuppressed(t *testing.T) {
|
||||
@@ -99,6 +104,29 @@ func TestMailServiceRESTCompatibilityThrottledSendSkipsMailService(t *testing.T)
|
||||
assert.Equal(t, 1, harness.mailServer.CallCount())
|
||||
}
|
||||
|
||||
func TestMailServiceRESTCompatibilitySendEmailCodeForwardsLocalizedLocale(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
harness := newMailServiceRESTCompatibilityHarness(t, mailServiceRESTCompatibilityOptions{
|
||||
MailStatusCode: http.StatusOK,
|
||||
MailResponse: `{"outcome":"sent"}`,
|
||||
})
|
||||
|
||||
response := gatewayCompatibilityPostJSONWithHeaders(
|
||||
t,
|
||||
harness.publicBaseURL+"/api/v1/public/auth/send-email-code",
|
||||
`{"email":"pilot@example.com"}`,
|
||||
map[string]string{"Accept-Language": "fr-FR, en;q=0.8"},
|
||||
)
|
||||
assert.Equal(t, http.StatusOK, response.StatusCode)
|
||||
assert.JSONEq(t, `{"challenge_id":"challenge-1"}`, response.Body)
|
||||
|
||||
deliveries := harness.mailServer.RecordedDeliveries()
|
||||
require.Len(t, deliveries, 1)
|
||||
assert.Equal(t, "fr-FR", deliveries[0].Locale)
|
||||
assert.Equal(t, "challenge-1", deliveries[0].IdempotencyKey)
|
||||
}
|
||||
|
||||
type mailServiceRESTCompatibilityOptions struct {
|
||||
MailStatusCode int
|
||||
MailResponse string
|
||||
@@ -191,6 +219,14 @@ type mailServiceStubServer struct {
|
||||
statusCode int
|
||||
response string
|
||||
callCount int
|
||||
deliveries []mailServiceStubDelivery
|
||||
}
|
||||
|
||||
type mailServiceStubDelivery struct {
|
||||
Email string
|
||||
Code string
|
||||
Locale string
|
||||
IdempotencyKey string
|
||||
}
|
||||
|
||||
func newMailServiceStubServer(statusCode int, response string) *mailServiceStubServer {
|
||||
@@ -206,17 +242,18 @@ func (s *mailServiceStubServer) Handler() http.Handler {
|
||||
http.NotFound(writer, request)
|
||||
return
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
s.callCount++
|
||||
s.mu.Unlock()
|
||||
if strings.TrimSpace(request.Header.Get("Idempotency-Key")) == "" {
|
||||
http.Error(writer, "Idempotency-Key header must not be empty", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
decoder := json.NewDecoder(request.Body)
|
||||
decoder.DisallowUnknownFields()
|
||||
|
||||
var body struct {
|
||||
Email string `json:"email"`
|
||||
Code string `json:"code"`
|
||||
Email string `json:"email"`
|
||||
Code string `json:"code"`
|
||||
Locale string `json:"locale"`
|
||||
}
|
||||
if err := decoder.Decode(&body); err != nil {
|
||||
http.Error(writer, err.Error(), http.StatusBadRequest)
|
||||
@@ -231,6 +268,16 @@ func (s *mailServiceStubServer) Handler() http.Handler {
|
||||
return
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
s.callCount++
|
||||
s.deliveries = append(s.deliveries, mailServiceStubDelivery{
|
||||
Email: body.Email,
|
||||
Code: body.Code,
|
||||
Locale: body.Locale,
|
||||
IdempotencyKey: request.Header.Get("Idempotency-Key"),
|
||||
})
|
||||
s.mu.Unlock()
|
||||
|
||||
writer.Header().Set("Content-Type", "application/json")
|
||||
writer.WriteHeader(s.statusCode)
|
||||
_, _ = io.WriteString(writer, s.response)
|
||||
@@ -243,3 +290,12 @@ func (s *mailServiceStubServer) CallCount() int {
|
||||
|
||||
return s.callCount
|
||||
}
|
||||
|
||||
func (s *mailServiceStubServer) RecordedDeliveries() []mailServiceStubDelivery {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
cloned := make([]mailServiceStubDelivery, len(s.deliveries))
|
||||
copy(cloned, s.deliveries)
|
||||
return cloned
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user