package config import "testing" func TestLoadDefaults(t *testing.T) { // Ensure no ambient values leak into the test. for _, k := range []string{ "EMAIL_AGENT_ENV", "EMAIL_AGENT_ADDR", "EMAIL_AGENT_PORT", "EMAIL_AGENT_DB_PATH", "EMAIL_AGENT_LOG_LEVEL", "EMAIL_AGENT_PUBLIC_BASE_URL", "GMAIL_USER", "GMAIL_APP_PASSWORD", "EMAIL_AGENT_IMAP_HOST", "EMAIL_AGENT_IMAP_PORT", "EMAIL_AGENT_IMAP_LOOKBACK_DAYS", "EMAIL_AGENT_IMAP_MAX_MESSAGES", } { t.Setenv(k, "") } cfg, err := Load() if err != nil { t.Fatalf("Load() error = %v", err) } if cfg.Port != DefaultPort { t.Errorf("Port = %d, want %d", cfg.Port, DefaultPort) } if cfg.Addr != DefaultAddr { t.Errorf("Addr = %q, want %q", cfg.Addr, DefaultAddr) } if cfg.Env != DefaultEnv { t.Errorf("Env = %q, want %q", cfg.Env, DefaultEnv) } if cfg.DBPath != DefaultDB { t.Errorf("DBPath = %q, want %q", cfg.DBPath, DefaultDB) } if cfg.IMAPHost != DefaultIMAPHost { t.Errorf("IMAPHost = %q, want %q", cfg.IMAPHost, DefaultIMAPHost) } if cfg.IMAPPort != DefaultIMAPPort { t.Errorf("IMAPPort = %d, want %d", cfg.IMAPPort, DefaultIMAPPort) } if cfg.IMAPLookbackDays != DefaultIMAPLookbackDays { t.Errorf("IMAPLookbackDays = %d, want %d", cfg.IMAPLookbackDays, DefaultIMAPLookbackDays) } if cfg.IMAPMaxMessages != DefaultIMAPMaxMessages { t.Errorf("IMAPMaxMessages = %d, want %d", cfg.IMAPMaxMessages, DefaultIMAPMaxMessages) } if cfg.GmailConfigured() { t.Error("GmailConfigured() = true with no credentials") } } func TestGmailConfigured(t *testing.T) { t.Setenv("GMAIL_USER", "samuelrolfe@gmail.com") t.Setenv("GMAIL_APP_PASSWORD", "app-password") cfg, err := Load() if err != nil { t.Fatalf("Load() error = %v", err) } if !cfg.GmailConfigured() { t.Error("GmailConfigured() = false with credentials set") } t.Setenv("GMAIL_APP_PASSWORD", "") cfg, err = Load() if err != nil { t.Fatalf("Load() error = %v", err) } if cfg.GmailConfigured() { t.Error("GmailConfigured() = true with no app password") } } func TestLoadOverrides(t *testing.T) { t.Setenv("EMAIL_AGENT_ENV", "production") t.Setenv("EMAIL_AGENT_PORT", "9000") t.Setenv("EMAIL_AGENT_DB_PATH", "/tmp/custom.db") t.Setenv("EMAIL_AGENT_LOG_LEVEL", "debug") t.Setenv("EMAIL_AGENT_PUBLIC_BASE_URL", "https://example.test/") t.Setenv("EMAIL_AGENT_ADDR", "") cfg, err := Load() if err != nil { t.Fatalf("Load() error = %v", err) } if cfg.Port != 9000 { t.Errorf("Port = %d, want 9000", cfg.Port) } if cfg.Addr != ":9000" { t.Errorf("Addr = %q, want %q", cfg.Addr, ":9000") } if !cfg.IsProduction() { t.Errorf("IsProduction() = false, want true") } if cfg.PublicBaseURL != "https://example.test" { t.Errorf("PublicBaseURL = %q, want trimmed URL", cfg.PublicBaseURL) } } func TestLoadInvalidPort(t *testing.T) { t.Setenv("EMAIL_AGENT_PORT", "not-a-number") t.Setenv("EMAIL_AGENT_ADDR", "") if _, err := Load(); err == nil { t.Fatal("Load() error = nil, want error for invalid port") } } func TestLoadInvalidEnv(t *testing.T) { t.Setenv("EMAIL_AGENT_ENV", "staging") t.Setenv("EMAIL_AGENT_ADDR", "") if _, err := Load(); err == nil { t.Fatal("Load() error = nil, want error for invalid env") } } func TestHubAndAppriseConfig(t *testing.T) { for _, k := range []string{"HUB_TOKEN", "HUB_BASE_URL", "APPRISE_URL", "APPRISE_KEY", "APPRISE_URLS", "EMAIL_AGENT_SUMMARY_TO", "HUB_NOTIFY_TIMEOUT"} { t.Setenv(k, "") } cfg, err := Load() if err != nil { t.Fatalf("Load() error = %v", err) } if cfg.HubConfigured() { t.Error("HubConfigured() = true with no HUB_TOKEN") } if cfg.HubBaseURL != DefaultHubBaseURL { t.Errorf("HubBaseURL = %q, want %q", cfg.HubBaseURL, DefaultHubBaseURL) } if cfg.AppriseURL != DefaultAppriseURL { t.Errorf("AppriseURL = %q, want %q", cfg.AppriseURL, DefaultAppriseURL) } if cfg.SummaryTo != DefaultSummaryTo { t.Errorf("SummaryTo = %q, want %q", cfg.SummaryTo, DefaultSummaryTo) } if cfg.AppriseConfigured() { t.Error("AppriseConfigured() = true with no key or URLs") } t.Setenv("HUB_TOKEN", "hub-secret") t.Setenv("APPRISE_KEY", "email-summary") cfg, err = Load() if err != nil { t.Fatalf("Load() error = %v", err) } if !cfg.HubConfigured() { t.Error("HubConfigured() = false with HUB_TOKEN set") } if !cfg.AppriseConfigured() { t.Error("AppriseConfigured() = false with a key set") } // A stateless URL list also configures Apprise. t.Setenv("APPRISE_KEY", "") t.Setenv("APPRISE_URLS", "mailto://a:b@example.com, ntfy://topic") cfg, err = Load() if err != nil { t.Fatalf("Load() error = %v", err) } if !cfg.AppriseConfigured() { t.Error("AppriseConfigured() = false with APPRISE_URLS set") } if len(cfg.AppriseURLs) != 2 { t.Errorf("AppriseURLs = %v, want 2 entries", cfg.AppriseURLs) } }