package config import ( "path/filepath" "testing" "time" ) func setRequiredEnv(t *testing.T) { t.Helper() t.Setenv("GENIUSRUN_PUBLIC_BASE_URL", "https://geniusrun.example.com") t.Setenv("GENIUSRUN_OIDC_ISSUER_URL", "https://keycloak.example.com/realms/myrealm") t.Setenv("GENIUSRUN_OIDC_CLIENT_ID", "geniusrun") t.Setenv("GENIUSRUN_OIDC_CLIENT_SECRET", "client-secret") t.Setenv("GENIUSRUN_SESSION_SECRET", "a-session-secret-that-is-at-least-32-bytes-long") } func TestLoad_DerivesOIDCSettingsFromPublicBaseURL(t *testing.T) { setRequiredEnv(t) cfg, err := Load() if err != nil { t.Fatalf("Load: %v", err) } if cfg.OIDCRedirectURL != "https://geniusrun.example.com/api/session/callback" { t.Errorf("OIDCRedirectURL = %q", cfg.OIDCRedirectURL) } if !cfg.SessionSecure { t.Error("SessionSecure = false, want true for an https base URL") } if cfg.OIDCRequiredRole != "geniusrun-user" { t.Errorf("OIDCRequiredRole = %q, want default", cfg.OIDCRequiredRole) } if cfg.SessionDuration != 720*time.Hour { t.Errorf("SessionDuration = %v, want default 720h", cfg.SessionDuration) } } func TestLoad_HTTPBaseURLYieldsInsecureCookies(t *testing.T) { setRequiredEnv(t) t.Setenv("GENIUSRUN_PUBLIC_BASE_URL", "http://localhost:8080") cfg, err := Load() if err != nil { t.Fatalf("Load: %v", err) } if cfg.SessionSecure { t.Error("SessionSecure = true, want false for an http base URL") } if cfg.OIDCRedirectURL != "http://localhost:8080/api/session/callback" { t.Errorf("OIDCRedirectURL = %q", cfg.OIDCRedirectURL) } } func TestLoad_MissingRequiredOIDCVars(t *testing.T) { cases := []string{ "GENIUSRUN_PUBLIC_BASE_URL", "GENIUSRUN_OIDC_ISSUER_URL", "GENIUSRUN_OIDC_CLIENT_ID", "GENIUSRUN_OIDC_CLIENT_SECRET", } for _, missing := range cases { t.Run(missing, func(t *testing.T) { setRequiredEnv(t) t.Setenv(missing, "") if _, err := Load(); err == nil { t.Fatalf("expected error when %s is unset", missing) } }) } } func TestLoad_SessionSecretTooShort(t *testing.T) { setRequiredEnv(t) t.Setenv("GENIUSRUN_SESSION_SECRET", "too-short") if _, err := Load(); err == nil { t.Fatal("expected error for a session secret under 32 characters") } } func TestLoad_GarminTokenStoreRootDefaultsNextToDBPath(t *testing.T) { setRequiredEnv(t) t.Setenv("GARMIN_TOKENSTORE", "") t.Setenv("GENIUSRUN_DB_PATH", "/var/lib/geniusrun/geniusrun.db") cfg, err := Load() if err != nil { t.Fatalf("Load: %v", err) } want := filepath.Join("/var/lib/geniusrun", "garmin-tokenstores") if cfg.GarminTokenStoreRoot != want { t.Errorf("GarminTokenStoreRoot = %q, want %q", cfg.GarminTokenStoreRoot, want) } } func TestLoad_GarminTokenStoreRootExplicitOverridesDefault(t *testing.T) { setRequiredEnv(t) t.Setenv("GARMIN_TOKENSTORE", "/custom/tokenstores") t.Setenv("GENIUSRUN_DB_PATH", "/var/lib/geniusrun/geniusrun.db") cfg, err := Load() if err != nil { t.Fatalf("Load: %v", err) } if cfg.GarminTokenStoreRoot != "/custom/tokenstores" { t.Errorf("GarminTokenStoreRoot = %q, want explicit override to take precedence", cfg.GarminTokenStoreRoot) } } func TestLoad_GarminPythonPathDefaultsToPython3(t *testing.T) { setRequiredEnv(t) t.Setenv("GARMIN_WRAPPER_PYTHON", "") cfg, err := Load() if err != nil { t.Fatalf("Load: %v", err) } if cfg.GarminPythonPath != "python3" { t.Errorf("GarminPythonPath = %q, want default %q", cfg.GarminPythonPath, "python3") } } func TestLoad_GarminPythonPathExplicitOverridesDefault(t *testing.T) { setRequiredEnv(t) t.Setenv("GARMIN_WRAPPER_PYTHON", "/opt/venv/bin/python3") cfg, err := Load() if err != nil { t.Fatalf("Load: %v", err) } if cfg.GarminPythonPath != "/opt/venv/bin/python3" { t.Errorf("GarminPythonPath = %q, want explicit override", cfg.GarminPythonPath) } } func TestLoad_FrontendURLDefaultsToPublicBaseURL(t *testing.T) { setRequiredEnv(t) t.Setenv("GENIUSRUN_FRONTEND_URL", "") cfg, err := Load() if err != nil { t.Fatalf("Load: %v", err) } if cfg.FrontendURL != cfg.PublicBaseURL { t.Errorf("FrontendURL = %q, want it to default to PublicBaseURL %q", cfg.FrontendURL, cfg.PublicBaseURL) } } func TestLoad_FrontendURLExplicitOverridesDefault(t *testing.T) { setRequiredEnv(t) t.Setenv("GENIUSRUN_FRONTEND_URL", "http://localhost:5173/") cfg, err := Load() if err != nil { t.Fatalf("Load: %v", err) } if cfg.FrontendURL != "http://localhost:5173" { t.Errorf("FrontendURL = %q, want http://localhost:5173 (trailing slash trimmed)", cfg.FrontendURL) } } func TestLoad_CustomRoleAndDuration(t *testing.T) { setRequiredEnv(t) t.Setenv("GENIUSRUN_OIDC_REQUIRED_ROLE", "admin") t.Setenv("GENIUSRUN_SESSION_DURATION", "24h") cfg, err := Load() if err != nil { t.Fatalf("Load: %v", err) } if cfg.OIDCRequiredRole != "admin" { t.Errorf("OIDCRequiredRole = %q", cfg.OIDCRequiredRole) } if cfg.SessionDuration != 24*time.Hour { t.Errorf("SessionDuration = %v", cfg.SessionDuration) } }