package mail import ( "errors" "net/smtp" "strings" "testing" ) func TestNewDynamicResolvesOnEachCall(t *testing.T) { calls := 0 m := NewDynamic(func() (Config, error) { calls++ return Config{ Enabled: true, Host: "smtp.example.com", Port: "587", From: "noreply@example.com", }, nil }) if !m.Enabled() { t.Fatal("expected enabled") } if calls != 1 { t.Fatalf("calls=%d", calls) } prev := smtpSendMail smtpSendMail = func(addr string, auth smtp.Auth, from string, to []string, msg []byte) error { return nil } t.Cleanup(func() { smtpSendMail = prev }) if err := m.Send(Message{To: "a@example.com", Subject: "hi", Text: "body"}); err != nil { t.Fatal(err) } if calls != 2 { t.Fatalf("expected second resolve on Send, calls=%d", calls) } } func TestNewDynamicDisabledIsNoop(t *testing.T) { m := NewDynamic(func() (Config, error) { return Config{Enabled: false}, nil }) if m.Enabled() { t.Fatal("expected disabled") } if err := m.Send(Message{To: "a@b.c", Subject: "x", Text: "y"}); err != nil { t.Fatal(err) } } func TestRequireConfiguredErrorsWhenOff(t *testing.T) { m := RequireConfigured(NewDynamic(func() (Config, error) { return Config{}, nil })) err := m.Send(Message{To: "a@b.c", Subject: "x", Text: "y"}) if !errors.Is(err, ErrNotConfigured) { t.Fatalf("got %v", err) } } func TestConfigFromPartsDefaultPort(t *testing.T) { cfg := ConfigFromParts(true, "h", "", "u", "p", "f@x") if cfg.Port != "587" { t.Fatalf("port=%q", cfg.Port) } if !cfg.Enabled || cfg.Host != "h" || !strings.Contains(cfg.From, "@") { t.Fatalf("%+v", cfg) } } func TestApplyDryRunDisablesSend(t *testing.T) { live := ConfigFromParts(true, "smtp.example.com", "587", "u", "p", "from@example.com") dry := ApplyDryRun(true, live) if dry.Enabled { t.Fatal("dry-run must force Enabled=false") } if dry.Host != "smtp.example.com" { t.Fatalf("host should be preserved, got %q", dry.Host) } if ApplyDryRun(false, live).Enabled != true { t.Fatal("dry-run=false must leave Enabled intact") } m := New(dry) if m.Enabled() { t.Fatal("New(ApplyDryRun(...)) must be noop") } }