Files
felhom.eu/hub/internal/api/mailhold_test.go
T

88 lines
2.7 KiB
Go

package api
import (
"io"
"net/http"
"os"
"path/filepath"
"strings"
"sync"
"testing"
"gitea.dooplex.hu/admin/felhom-hub/internal/mailhold"
)
// MAIL-HOLD on the two API send paths (the dispatcher's paths: internal/notify/mailhold_test.go).
// COMPANION RED-PROOF (REPORT): remove the h.mailHold.Check block from handleNotify / handleMail → these fail with the
// mail handed to Resend (the recorded transport / the fake SMTP sender).
func heldHold(t *testing.T) *mailhold.Hold {
t.Helper()
dir := t.TempDir()
if err := os.WriteFile(filepath.Join(dir, mailhold.FileName), nil, 0o644); err != nil {
t.Fatal(err)
}
return mailhold.New(dir, nil)
}
// recordingTransport stands in for api.resend.com: it records each request and never leaves the process.
type recordingTransport struct {
mu sync.Mutex
calls int
}
func (rt *recordingTransport) RoundTrip(r *http.Request) (*http.Response, error) {
rt.mu.Lock()
rt.calls++
rt.mu.Unlock()
return &http.Response{StatusCode: 200, Body: io.NopCloser(strings.NewReader(`{"id":"x"}`)), Header: http.Header{}}, nil
}
func TestMailHold_NotifySendsNothingWhileHeld(t *testing.T) {
h, st := newEventTestHandler(t)
rt := &recordingTransport{}
h.httpClient = &http.Client{Transport: rt}
h.resendAPIKey = "test-key"
if err := st.SaveNotificationPrefs("c1", "household@example.hu", []string{"backup_failed"}, 6); err != nil {
t.Fatal(err)
}
h.SetMailHold(heldHold(t))
rr := do(h, http.MethodPost, "/notify", "ckey", `{"customer_id":"c1","event_type":"backup_failed","severity":"error","message":"m"}`)
if rr.Code != http.StatusOK {
t.Fatalf("status = %d, body=%s", rr.Code, rr.Body.String())
}
if rt.calls != 0 {
t.Fatalf("MAIL-HOLD present but /notify handed %d mail(s) to Resend", rt.calls)
}
if !strings.Contains(rr.Body.String(), `"reason":"mail_hold"`) {
t.Fatalf("the answer must say the mail was held: %s", rr.Body.String())
}
}
func TestMailHold_AppMailRelayRefusesWhileHeld(t *testing.T) {
h, st, _ := newTestHandler(t)
withCustomer(t, st, "c1", "ckey")
fake := &fakeSender{}
h.SetMailRelay(fake, 30, []string{"felhom.eu"})
hold := heldHold(t)
h.SetMailHold(hold)
rr := do(h, "POST", "/mail", "ckey", mailBody(t, "vaultwarden@felhom.eu"))
if fake.callCount() != 0 {
t.Fatalf("MAIL-HOLD present but the relay sent %d mail(s)", fake.callCount())
}
if rr.Code != http.StatusServiceUnavailable {
t.Fatalf("held relay: status %d, want 503", rr.Code)
}
// Released: the relay sends again.
if err := hold.Release(); err != nil {
t.Fatal(err)
}
rr = do(h, "POST", "/mail", "ckey", mailBody(t, "vaultwarden@felhom.eu"))
if rr.Code != http.StatusOK || fake.callCount() != 1 {
t.Fatalf("after release: status %d, sends %d — want 200 and 1", rr.Code, fake.callCount())
}
}