package config import ( "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) var required = map[string]string{ "DATABASE_URL": "postgres://u:p@db/pu", "PUBLIC_URL": "https://updater.example.com", "AGENT_URL": "wss://10.0.0.5:8090/agent", "OIDC_ISSUER": "https://auth.example.com/application/o/pu/", "OIDC_CLIENT_ID": "id", "OIDC_CLIENT_SECRET": "secret", "ALLOWED_GROUP": "updater-admins", } func setAll(t *testing.T) { for k, v := range required { t.Setenv(k, v) } for _, k := range []string{"PORT", "AGENT_PORT", "AGENT_IMAGE", "LOG_LEVEL", "UPDATER_API_KEY", "UPDATE_TIMEOUT"} { t.Setenv(k, "") } } func TestLoad_Defaults(t *testing.T) { setAll(t) cfg, err := Load() require.NoError(t, err) assert.Equal(t, "8080", cfg.Port) assert.Equal(t, "8090", cfg.AgentPort) assert.Equal(t, "gitea.shcizo.se/shcizo/package-updater:latest", cfg.AgentImage) assert.Equal(t, "info", cfg.LogLevel) assert.Equal(t, "updater-admins", cfg.AllowedGroup) assert.Empty(t, cfg.UpdaterAPIKey) assert.Equal(t, 5*time.Minute, cfg.UpdateTimeout) } func TestLoad_WebhookSettings(t *testing.T) { setAll(t) t.Setenv("UPDATER_API_KEY", "s3cret") t.Setenv("UPDATE_TIMEOUT", "90s") cfg, err := Load() require.NoError(t, err) assert.Equal(t, "s3cret", cfg.UpdaterAPIKey) assert.Equal(t, 90*time.Second, cfg.UpdateTimeout) } func TestLoad_InvalidUpdateTimeout(t *testing.T) { for _, v := range []string{"abc", "0s", "-5m", "30"} { t.Run(v, func(t *testing.T) { setAll(t) t.Setenv("UPDATE_TIMEOUT", v) _, err := Load() assert.ErrorContains(t, err, "UPDATE_TIMEOUT must be a positive duration") }) } } func TestLoad_EachRequiredVariable(t *testing.T) { for key := range required { t.Run(key, func(t *testing.T) { setAll(t) t.Setenv(key, "") _, err := Load() assert.ErrorContains(t, err, key+" is required") }) } } func TestLoad_URLFormats(t *testing.T) { cases := []struct{ key, value, wantErr string }{ {"PUBLIC_URL", "updater.example.com", "PUBLIC_URL must start with http:// or https://"}, {"AGENT_URL", "ws://10.0.0.5:8090/agent", "AGENT_URL must start with wss://"}, } for _, c := range cases { t.Run(c.key, func(t *testing.T) { setAll(t) t.Setenv(c.key, c.value) _, err := Load() assert.ErrorContains(t, err, c.wantErr) }) } }