86 lines
2.7 KiB
Go
86 lines
2.7 KiB
Go
package integration_test
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"testing"
|
|
"time"
|
|
|
|
"galaxy/integration/testenv"
|
|
)
|
|
|
|
// TestMailFlow_LoginCodeAndAdminListing triggers a login code email
|
|
// (which uses backend's mail outbox), waits for mailpit to capture
|
|
// the SMTP delivery, and verifies the admin endpoints expose the
|
|
// same delivery via the typed list response.
|
|
//
|
|
// Resend on a `sent` row returns 409 (per OpenAPI/decision record);
|
|
// this test asserts that contract by attempting a resend on the
|
|
// captured (and now sent) delivery.
|
|
func TestMailFlow_LoginCodeAndAdminListing(t *testing.T) {
|
|
plat := testenv.Bootstrap(t, testenv.BootstrapOptions{})
|
|
ctx, cancel := context.WithTimeout(context.Background(), 90*time.Second)
|
|
defer cancel()
|
|
|
|
// Trigger a login code, which writes one mail_deliveries row and
|
|
// drains via the worker into mailpit.
|
|
sess := testenv.RegisterSession(t, plat, "pilot+mail@example.com")
|
|
if sess.DeviceSessionID == "" {
|
|
t.Fatalf("session not established")
|
|
}
|
|
|
|
admin := testenv.NewBackendAdminClient(plat.Backend.HTTPURL, plat.Backend.AdminUser, plat.Backend.AdminPassword)
|
|
raw, resp, err := admin.Do(ctx, http.MethodGet, "/api/v1/admin/mail/deliveries?page=1&page_size=10", nil)
|
|
if err != nil {
|
|
t.Fatalf("list deliveries: %v", err)
|
|
}
|
|
if resp.StatusCode != http.StatusOK {
|
|
t.Fatalf("list deliveries: status %d body=%s", resp.StatusCode, string(raw))
|
|
}
|
|
var list struct {
|
|
Items []struct {
|
|
DeliveryID string `json:"delivery_id"`
|
|
Status string `json:"status"`
|
|
TemplateID string `json:"template_id"`
|
|
} `json:"items"`
|
|
}
|
|
if err := json.Unmarshal(raw, &list); err != nil {
|
|
t.Fatalf("decode list: %v", err)
|
|
}
|
|
if len(list.Items) == 0 {
|
|
t.Fatalf("admin list returned no deliveries; expected at least the login code row")
|
|
}
|
|
|
|
var sent string
|
|
deadline := time.Now().Add(15 * time.Second)
|
|
for time.Now().Before(deadline) && sent == "" {
|
|
raw, resp, err = admin.Do(ctx, http.MethodGet, "/api/v1/admin/mail/deliveries?page=1&page_size=10", nil)
|
|
if err != nil || resp.StatusCode != http.StatusOK {
|
|
t.Fatalf("list deliveries during wait: %v status=%v", err, resp)
|
|
}
|
|
_ = json.Unmarshal(raw, &list)
|
|
for _, it := range list.Items {
|
|
if it.Status == "sent" {
|
|
sent = it.DeliveryID
|
|
break
|
|
}
|
|
}
|
|
if sent == "" {
|
|
time.Sleep(300 * time.Millisecond)
|
|
}
|
|
}
|
|
if sent == "" {
|
|
t.Fatalf("no delivery reached `sent` within 15s; admin list = %+v", list.Items)
|
|
}
|
|
|
|
// Resend on a sent row must return 409.
|
|
raw, resp, err = admin.Do(ctx, http.MethodPost, "/api/v1/admin/mail/deliveries/"+sent+"/resend", nil)
|
|
if err != nil {
|
|
t.Fatalf("resend sent delivery: %v", err)
|
|
}
|
|
if resp.StatusCode != http.StatusConflict {
|
|
t.Fatalf("resend on sent delivery: status %d body=%s, want 409", resp.StatusCode, string(raw))
|
|
}
|
|
}
|