package config import ( "os" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" ) func TestLoad(t *testing.T) { // Sauvegarder les valeurs originales originalDBPassword := os.Getenv("DB_PASSWORD") originalJWTSecret := os.Getenv("JWT_SECRET") originalAppPort := os.Getenv("APP_PORT") // Nettoyer après le test defer func() { if originalDBPassword != "" { os.Setenv("DB_PASSWORD", originalDBPassword) } else { os.Unsetenv("DB_PASSWORD") } if originalJWTSecret != "" { os.Setenv("JWT_SECRET", originalJWTSecret) } else { os.Unsetenv("JWT_SECRET") } if originalAppPort != "" { os.Setenv("APP_PORT", originalAppPort) } else { os.Unsetenv("APP_PORT") } }() // Définir les variables requises os.Setenv("DB_PASSWORD", "test_password") os.Setenv("JWT_SECRET", "test_secret") config, err := Load() require.NoError(t, err) require.NotNil(t, config) // Vérifier les valeurs par défaut assert.Equal(t, 8080, config.AppPort) assert.Equal(t, "development", config.AppEnv) assert.Equal(t, "localhost", config.DBHost) assert.Equal(t, 5432, config.DBPort) assert.Equal(t, "veza", config.DBUser) assert.Equal(t, "veza_db", config.DBName) assert.Equal(t, "redis://localhost:6379", config.RedisURL) // Vérifier les valeurs requises assert.Equal(t, "test_password", config.DBPassword) assert.Equal(t, "test_secret", config.JWTSecret) } func TestLoad_WithCustomValues(t *testing.T) { // Sauvegarder les valeurs originales originalDBPassword := os.Getenv("DB_PASSWORD") originalJWTSecret := os.Getenv("JWT_SECRET") originalAppPort := os.Getenv("APP_PORT") originalDBHost := os.Getenv("DB_HOST") originalDBPort := os.Getenv("DB_PORT") // Nettoyer après le test defer func() { if originalDBPassword != "" { os.Setenv("DB_PASSWORD", originalDBPassword) } else { os.Unsetenv("DB_PASSWORD") } if originalJWTSecret != "" { os.Setenv("JWT_SECRET", originalJWTSecret) } else { os.Unsetenv("JWT_SECRET") } if originalAppPort != "" { os.Setenv("APP_PORT", originalAppPort) } else { os.Unsetenv("APP_PORT") } if originalDBHost != "" { os.Setenv("DB_HOST", originalDBHost) } else { os.Unsetenv("DB_HOST") } if originalDBPort != "" { os.Setenv("DB_PORT", originalDBPort) } else { os.Unsetenv("DB_PORT") } }() // Définir des valeurs personnalisées os.Setenv("DB_PASSWORD", "custom_password") os.Setenv("JWT_SECRET", "custom_secret") os.Setenv("APP_PORT", "9090") os.Setenv("DB_HOST", "custom_host") os.Setenv("DB_PORT", "3306") config, err := Load() require.NoError(t, err) assert.Equal(t, 9090, config.AppPort) assert.Equal(t, "custom_host", config.DBHost) assert.Equal(t, 3306, config.DBPort) assert.Equal(t, "custom_password", config.DBPassword) assert.Equal(t, "custom_secret", config.JWTSecret) } func TestLoad_MissingRequiredVariable_DBPassword(t *testing.T) { // Sauvegarder les valeurs originales originalDBPassword := os.Getenv("DB_PASSWORD") originalJWTSecret := os.Getenv("JWT_SECRET") // Nettoyer après le test defer func() { if originalDBPassword != "" { os.Setenv("DB_PASSWORD", originalDBPassword) } else { os.Unsetenv("DB_PASSWORD") } if originalJWTSecret != "" { os.Setenv("JWT_SECRET", originalJWTSecret) } else { os.Unsetenv("JWT_SECRET") } }() // Supprimer les variables requises os.Unsetenv("DB_PASSWORD") os.Setenv("JWT_SECRET", "test_secret") // MOD-P0-002: getEnvRequired() returns error, not panic - verify error is returned _, err := Load() assert.Error(t, err, "Should return error when DB_PASSWORD is missing") assert.Contains(t, err.Error(), "DB_PASSWORD", "Error message should mention DB_PASSWORD") } func TestLoad_MissingRequiredVariable_JWTSecret(t *testing.T) { // Sauvegarder les valeurs originales originalDBPassword := os.Getenv("DB_PASSWORD") originalJWTSecret := os.Getenv("JWT_SECRET") // Nettoyer après le test defer func() { if originalDBPassword != "" { os.Setenv("DB_PASSWORD", originalDBPassword) } else { os.Unsetenv("DB_PASSWORD") } if originalJWTSecret != "" { os.Setenv("JWT_SECRET", originalJWTSecret) } else { os.Unsetenv("JWT_SECRET") } }() // Supprimer les variables requises os.Setenv("DB_PASSWORD", "test_password") os.Unsetenv("JWT_SECRET") // MOD-P0-002: getEnvRequired() returns error, not panic - verify error is returned _, err := Load() assert.Error(t, err, "Should return error when JWT_SECRET is missing") assert.Contains(t, err.Error(), "JWT_SECRET", "Error message should mention JWT_SECRET") } func TestGetEnv(t *testing.T) { // Sauvegarder la valeur originale originalValue := os.Getenv("TEST_VAR") defer func() { if originalValue != "" { os.Setenv("TEST_VAR", originalValue) } else { os.Unsetenv("TEST_VAR") } }() // Test avec valeur définie os.Setenv("TEST_VAR", "test_value") assert.Equal(t, "test_value", getEnv("TEST_VAR", "default")) // Test sans valeur (devrait retourner défaut) os.Unsetenv("TEST_VAR") assert.Equal(t, "default", getEnv("TEST_VAR", "default")) } func TestGetEnvInt(t *testing.T) { // Sauvegarder la valeur originale originalValue := os.Getenv("TEST_INT") defer func() { if originalValue != "" { os.Setenv("TEST_INT", originalValue) } else { os.Unsetenv("TEST_INT") } }() // Test avec valeur entière valide os.Setenv("TEST_INT", "42") assert.Equal(t, 42, getEnvInt("TEST_INT", 10)) // Test sans valeur (devrait retourner défaut) os.Unsetenv("TEST_INT") assert.Equal(t, 10, getEnvInt("TEST_INT", 10)) // Test avec valeur invalide (devrait retourner défaut) os.Setenv("TEST_INT", "not_a_number") assert.Equal(t, 10, getEnvInt("TEST_INT", 10)) } func TestGetEnvRequired(t *testing.T) { // Sauvegarder la valeur originale originalValue := os.Getenv("TEST_REQUIRED") defer func() { if originalValue != "" { os.Setenv("TEST_REQUIRED", originalValue) } else { os.Unsetenv("TEST_REQUIRED") } }() // Test avec valeur définie os.Setenv("TEST_REQUIRED", "required_value") val, err := getEnvRequired("TEST_REQUIRED") require.NoError(t, err) assert.Equal(t, "required_value", val) // Test sans valeur (devrait retourner une erreur) os.Unsetenv("TEST_REQUIRED") _, err = getEnvRequired("TEST_REQUIRED") assert.Error(t, err, "Should return error when required variable is missing") } func TestLoad_DefaultValues(t *testing.T) { // Sauvegarder les valeurs originales originalDBPassword := os.Getenv("DB_PASSWORD") originalJWTSecret := os.Getenv("JWT_SECRET") originalAppEnv := os.Getenv("APP_ENV") originalRedisURL := os.Getenv("REDIS_URL") // Nettoyer après le test defer func() { if originalDBPassword != "" { os.Setenv("DB_PASSWORD", originalDBPassword) } else { os.Unsetenv("DB_PASSWORD") } if originalJWTSecret != "" { os.Setenv("JWT_SECRET", originalJWTSecret) } else { os.Unsetenv("JWT_SECRET") } if originalAppEnv != "" { os.Setenv("APP_ENV", originalAppEnv) } else { os.Unsetenv("APP_ENV") } if originalRedisURL != "" { os.Setenv("REDIS_URL", originalRedisURL) } else { os.Unsetenv("REDIS_URL") } }() // Définir seulement les variables requises os.Setenv("DB_PASSWORD", "test") os.Setenv("JWT_SECRET", "secret") // Supprimer les variables optionnelles pour tester les valeurs par défaut os.Unsetenv("APP_ENV") os.Unsetenv("REDIS_URL") config, err := Load() require.NoError(t, err) // Vérifier que les valeurs par défaut sont utilisées assert.Equal(t, "development", config.AppEnv) assert.Equal(t, "redis://localhost:6379", config.RedisURL) } // TestNewConfig_RequiresJWTSecret vérifie que NewConfig() refuse de démarrer sans JWT_SECRET // Ce test valide la correction de sécurité qui empêche l'utilisation d'une valeur par défaut hardcodée func TestNewConfig_RequiresJWTSecret(t *testing.T) { // Sauvegarder les valeurs originales originalJWTSecret := os.Getenv("JWT_SECRET") originalDatabaseURL := os.Getenv("DATABASE_URL") // Nettoyer après le test defer func() { if originalJWTSecret != "" { os.Setenv("JWT_SECRET", originalJWTSecret) } else { os.Unsetenv("JWT_SECRET") } if originalDatabaseURL != "" { os.Setenv("DATABASE_URL", originalDatabaseURL) } else { os.Unsetenv("DATABASE_URL") } }() // Supprimer JWT_SECRET - devrait causer une erreur os.Unsetenv("JWT_SECRET") // Définir DATABASE_URL pour éviter une erreur sur cette variable (on teste seulement JWT_SECRET) os.Setenv("DATABASE_URL", "postgresql://test:test@localhost:5432/test_db") // MOD-P0-002: getEnvRequired() returns error, not panic - verify error is returned _, err := NewConfig() assert.Error(t, err, "NewConfig should return error when JWT_SECRET is missing") assert.Contains(t, err.Error(), "JWT_SECRET", "Error message should mention JWT_SECRET") } // TestNewConfig_RequiresDatabaseURL vérifie que NewConfig() refuse de démarrer sans DATABASE_URL // Ce test valide la correction de sécurité qui empêche l'utilisation d'une valeur par défaut avec credentials func TestNewConfig_RequiresDatabaseURL(t *testing.T) { // Sauvegarder les valeurs originales originalJWTSecret := os.Getenv("JWT_SECRET") originalDatabaseURL := os.Getenv("DATABASE_URL") // Nettoyer après le test defer func() { if originalJWTSecret != "" { os.Setenv("JWT_SECRET", originalJWTSecret) } else { os.Unsetenv("JWT_SECRET") } if originalDatabaseURL != "" { os.Setenv("DATABASE_URL", originalDatabaseURL) } else { os.Unsetenv("DATABASE_URL") } }() // Définir JWT_SECRET (minimum 32 caractères pour passer la validation) os.Setenv("JWT_SECRET", "test-jwt-secret-key-minimum-32-characters-long") // Supprimer DATABASE_URL - devrait causer une erreur os.Unsetenv("DATABASE_URL") // MOD-P0-002: getEnvRequired() returns error, not panic - verify error is returned _, err := NewConfig() assert.Error(t, err, "NewConfig should return error when DATABASE_URL is missing") assert.Contains(t, err.Error(), "DATABASE_URL", "Error message should mention DATABASE_URL") } // ============================================================================ // P0-SECURITY: Tests pour la sécurisation de la configuration CORS // ============================================================================ // TestLoadConfig_DevDefaults vérifie que les defaults dev sont corrects (P0-SECURITY) func TestLoadConfig_DevDefaults(t *testing.T) { // Sauvegarder les valeurs originales originalEnv := os.Getenv("APP_ENV") originalJWTSecret := os.Getenv("JWT_SECRET") originalDatabaseURL := os.Getenv("DATABASE_URL") originalCORSOrigins := os.Getenv("CORS_ALLOWED_ORIGINS") // Nettoyer après le test defer func() { if originalEnv != "" { os.Setenv("APP_ENV", originalEnv) } else { os.Unsetenv("APP_ENV") } if originalJWTSecret != "" { os.Setenv("JWT_SECRET", originalJWTSecret) } else { os.Unsetenv("JWT_SECRET") } if originalDatabaseURL != "" { os.Setenv("DATABASE_URL", originalDatabaseURL) } else { os.Unsetenv("DATABASE_URL") } if originalCORSOrigins != "" { os.Setenv("CORS_ALLOWED_ORIGINS", originalCORSOrigins) } else { os.Unsetenv("CORS_ALLOWED_ORIGINS") } }() // Configuration pour développement os.Setenv("APP_ENV", "development") os.Setenv("JWT_SECRET", "test-jwt-secret-key-minimum-32-characters-long") os.Setenv("DATABASE_URL", "postgresql://test:test@localhost:5432/test_db") os.Unsetenv("CORS_ALLOWED_ORIGINS") // Pas défini pour tester les defaults // Note: NewConfig() nécessite Redis et DB, donc on teste seulement getCORSOrigins origins := getCORSOrigins("development", "veza.fr") require.NotEmpty(t, origins, "Development should have default CORS origins") assert.Contains(t, origins, "http://veza.fr:3000", "Should include domain:3000") assert.Contains(t, origins, "http://veza.fr:5173", "Should include domain:5173") assert.NotContains(t, origins, "*", "Should not contain wildcard") } // TestLoadConfig_ProdMissingCritical vérifie que prod refuse si CORS manquant (P0-SECURITY) func TestLoadConfig_ProdMissingCritical(t *testing.T) { // Sauvegarder les valeurs originales originalEnv := os.Getenv("APP_ENV") originalJWTSecret := os.Getenv("JWT_SECRET") originalDatabaseURL := os.Getenv("DATABASE_URL") originalCORSOrigins := os.Getenv("CORS_ALLOWED_ORIGINS") // Nettoyer après le test defer func() { if originalEnv != "" { os.Setenv("APP_ENV", originalEnv) } else { os.Unsetenv("APP_ENV") } if originalJWTSecret != "" { os.Setenv("JWT_SECRET", originalJWTSecret) } else { os.Unsetenv("JWT_SECRET") } if originalDatabaseURL != "" { os.Setenv("DATABASE_URL", originalDatabaseURL) } else { os.Unsetenv("DATABASE_URL") } if originalCORSOrigins != "" { os.Setenv("CORS_ALLOWED_ORIGINS", originalCORSOrigins) } else { os.Unsetenv("CORS_ALLOWED_ORIGINS") } }() // Configuration pour production sans CORS os.Setenv("APP_ENV", "production") os.Setenv("JWT_SECRET", "test-jwt-secret-key-minimum-32-characters-long") os.Setenv("DATABASE_URL", "postgresql://test:test@localhost:5432/test_db") os.Unsetenv("CORS_ALLOWED_ORIGINS") // Manquant intentionnellement // Créer une config minimale pour tester la validation cfg := &Config{ Env: "production", JWTSecret: "test-jwt-secret-key-minimum-32-characters-long", DatabaseURL: "postgresql://test:test@localhost:5432/test_db", RedisURL: "redis://localhost:6379", AppPort: 8080, LogLevel: "INFO", RateLimitLimit: 100, // Valeur valide pour passer Validate() RateLimitWindow: 60, // Valeur valide pour passer Validate() CORSOrigins: []string{}, // Vide - mode strict (rejette toutes origines) - MOD-P0-001: Acceptable en prod } // Créer un logger minimal pour la config logger, _ := zap.NewDevelopment() cfg.Logger = logger // MOD-P0-001: CORS_ALLOWED_ORIGINS vide en production doit échouer (fail-fast) // La validation doit retourner une erreur car CORS vide rend le service inaccessible err := cfg.ValidateForEnvironment() require.Error(t, err, "Production config with empty CORS_ALLOWED_ORIGINS should fail validation (fail-fast)") assert.Contains(t, err.Error(), "CORS_ALLOWED_ORIGINS is required", "Error message should mention CORS_ALLOWED_ORIGINS requirement") } // TestNewConfig_ProductionCORSRequired vérifie que NewConfig() refuse de démarrer en production sans CORS // MOD-P0-001: Fail-fast si CORS_ALLOWED_ORIGINS est vide en production func TestNewConfig_ProductionCORSRequired(t *testing.T) { // Sauvegarder les valeurs originales originalEnv := os.Getenv("APP_ENV") originalJWTSecret := os.Getenv("JWT_SECRET") originalDatabaseURL := os.Getenv("DATABASE_URL") originalCORSOrigins := os.Getenv("CORS_ALLOWED_ORIGINS") originalRedisEnable := os.Getenv("REDIS_ENABLE") originalRabbitMQEnable := os.Getenv("RABBITMQ_ENABLE") // Nettoyer après le test defer func() { if originalEnv != "" { os.Setenv("APP_ENV", originalEnv) } else { os.Unsetenv("APP_ENV") } if originalJWTSecret != "" { os.Setenv("JWT_SECRET", originalJWTSecret) } else { os.Unsetenv("JWT_SECRET") } if originalDatabaseURL != "" { os.Setenv("DATABASE_URL", originalDatabaseURL) } else { os.Unsetenv("DATABASE_URL") } if originalCORSOrigins != "" { os.Setenv("CORS_ALLOWED_ORIGINS", originalCORSOrigins) } else { os.Unsetenv("CORS_ALLOWED_ORIGINS") } if originalRedisEnable != "" { os.Setenv("REDIS_ENABLE", originalRedisEnable) } else { os.Unsetenv("REDIS_ENABLE") } if originalRabbitMQEnable != "" { os.Setenv("RABBITMQ_ENABLE", originalRabbitMQEnable) } else { os.Unsetenv("RABBITMQ_ENABLE") } }() // Configuration pour production sans CORS os.Setenv("APP_ENV", "production") os.Setenv("JWT_SECRET", "test-jwt-secret-key-minimum-32-characters-long") os.Setenv("DATABASE_URL", "postgresql://test:test@localhost:5432/test_db") os.Unsetenv("CORS_ALLOWED_ORIGINS") // Manquant intentionnellement os.Setenv("REDIS_ENABLE", "false") // Désactiver Redis pour éviter erreur de connexion os.Setenv("RABBITMQ_ENABLE", "false") // Désactiver RabbitMQ pour éviter erreur de connexion // MOD-P0-001: NewConfig() doit retourner une erreur car CORS est vide en production // La validation ValidateForEnvironment() est appelée dans NewConfig() et doit échouer _, err := NewConfig() require.Error(t, err, "NewConfig should return error when CORS_ALLOWED_ORIGINS is empty in production") // Le message d'erreur peut varier, vérifier qu'il mentionne CORS_ALLOWED_ORIGINS assert.Contains(t, err.Error(), "CORS_ALLOWED_ORIGINS", "Error message should mention CORS_ALLOWED_ORIGINS requirement") } // TestNewConfig_JWTSecretTooShort vérifie que NewConfig() refuse de démarrer si JWT_SECRET < 32 chars // MOD-P0-002: Validation JWT secret length func TestNewConfig_JWTSecretTooShort(t *testing.T) { // Sauvegarder les valeurs originales originalJWTSecret := os.Getenv("JWT_SECRET") originalDatabaseURL := os.Getenv("DATABASE_URL") // Nettoyer après le test defer func() { if originalJWTSecret != "" { os.Setenv("JWT_SECRET", originalJWTSecret) } else { os.Unsetenv("JWT_SECRET") } if originalDatabaseURL != "" { os.Setenv("DATABASE_URL", originalDatabaseURL) } else { os.Unsetenv("DATABASE_URL") } }() // Définir JWT_SECRET trop court (< 32 chars) os.Setenv("JWT_SECRET", "short-secret") // 12 chars seulement os.Setenv("DATABASE_URL", "postgresql://test:test@localhost:5432/test_db") os.Setenv("REDIS_ENABLE", "false") os.Setenv("RABBITMQ_ENABLE", "false") // MOD-P0-002: NewConfig() doit retourner une erreur car JWT_SECRET est trop court // La validation Validate() est appelée dans NewConfig() et doit échouer _, err := NewConfig() require.Error(t, err, "NewConfig should return error when JWT_SECRET is too short") assert.Contains(t, err.Error(), "JWT_SECRET validation failed", "Error message should mention JWT_SECRET validation") assert.Contains(t, err.Error(), "32", "Error message should mention minimum length of 32") } // TestLoadConfig_ProdWildcard vérifie que prod refuse le wildcard (P0-SECURITY) func TestLoadConfig_ProdWildcard(t *testing.T) { // Sauvegarder les valeurs originales originalEnv := os.Getenv("APP_ENV") originalCORSOrigins := os.Getenv("CORS_ALLOWED_ORIGINS") // Nettoyer après le test defer func() { if originalEnv != "" { os.Setenv("APP_ENV", originalEnv) } else { os.Unsetenv("APP_ENV") } if originalCORSOrigins != "" { os.Setenv("CORS_ALLOWED_ORIGINS", originalCORSOrigins) } else { os.Unsetenv("CORS_ALLOWED_ORIGINS") } }() // Configuration pour production avec wildcard os.Setenv("APP_ENV", "production") // Créer une config minimale avec wildcard cfg := &Config{ Env: "production", JWTSecret: "test-jwt-secret-key-minimum-32-characters-long", DatabaseURL: "postgresql://test:test@localhost:5432/test_db", RedisURL: "redis://localhost:6379", AppPort: 8080, LogLevel: "INFO", RateLimitLimit: 100, // Valeur valide pour passer Validate() RateLimitWindow: 60, // Valeur valide pour passer Validate() CORSOrigins: []string{"*"}, // Wildcard - devrait échouer en prod } // Créer un logger minimal pour la config logger, _ := zap.NewDevelopment() cfg.Logger = logger // La validation devrait échouer err := cfg.ValidateForEnvironment() require.Error(t, err, "Production config should fail validation when CORS contains wildcard") assert.Contains(t, err.Error(), "wildcard", "Error should mention wildcard prohibition") } // TestLoadConfig_ProdValid vérifie qu'une config prod valide passe (P0-SECURITY) func TestLoadConfig_ProdValid(t *testing.T) { // Sauvegarder les valeurs originales originalEnv := os.Getenv("APP_ENV") originalCORSOrigins := os.Getenv("CORS_ALLOWED_ORIGINS") // Nettoyer après le test defer func() { if originalEnv != "" { os.Setenv("APP_ENV", originalEnv) } else { os.Unsetenv("APP_ENV") } if originalCORSOrigins != "" { os.Setenv("CORS_ALLOWED_ORIGINS", originalCORSOrigins) } else { os.Unsetenv("CORS_ALLOWED_ORIGINS") } }() // Configuration pour production valide os.Setenv("APP_ENV", "production") // Créer une config minimale valide cfg := &Config{ Env: "production", JWTSecret: "test-jwt-secret-key-minimum-32-characters-long", DatabaseURL: "postgresql://test:test@localhost:5432/test_db", RedisURL: "redis://localhost:6379", AppPort: 8080, LogLevel: "INFO", RateLimitLimit: 100, // Valeur valide pour passer Validate() RateLimitWindow: 60, // Valeur valide pour passer Validate() CORSOrigins: []string{"https://app.veza.com", "https://www.veza.com"}, // Valide - pas de wildcard } // Créer un logger minimal pour la config logger, _ := zap.NewDevelopment() cfg.Logger = logger // La validation devrait passer err := cfg.ValidateForEnvironment() assert.NoError(t, err, "Valid production config should pass validation") } // TestGetCORSOrigins_EnvironmentDefaults teste les defaults selon l'environnement (P0-SECURITY) func TestGetCORSOrigins_EnvironmentDefaults(t *testing.T) { tests := []struct { name string env string expected []string }{ { name: "development defaults", env: "development", expected: []string{"http://veza.fr", "http://veza.fr:3000", "http://veza.fr:5173", "http://veza.fr:8080"}, }, { name: "staging defaults", env: "staging", expected: []string{"http://veza.fr", "http://veza.fr:3000", "http://veza.fr:5173", "http://veza.fr:8080"}, }, { name: "production no defaults", env: "production", expected: []string{}, }, { name: "test no defaults", env: "test", expected: []string{}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Sauvegarder CORS_ALLOWED_ORIGINS originalCORSOrigins := os.Getenv("CORS_ALLOWED_ORIGINS") defer func() { if originalCORSOrigins != "" { os.Setenv("CORS_ALLOWED_ORIGINS", originalCORSOrigins) } else { os.Unsetenv("CORS_ALLOWED_ORIGINS") } }() // S'assurer que CORS_ALLOWED_ORIGINS n'est pas défini os.Unsetenv("CORS_ALLOWED_ORIGINS") origins := getCORSOrigins(tt.env, "veza.fr") assert.Equal(t, tt.expected, origins, "CORS origins should match expected defaults for %s", tt.env) }) } } // TestGetCORSOrigins_ExplicitValue teste que les valeurs explicites sont utilisées (P0-SECURITY) func TestGetCORSOrigins_ExplicitValue(t *testing.T) { // Sauvegarder CORS_ALLOWED_ORIGINS originalCORSOrigins := os.Getenv("CORS_ALLOWED_ORIGINS") defer func() { if originalCORSOrigins != "" { os.Setenv("CORS_ALLOWED_ORIGINS", originalCORSOrigins) } else { os.Unsetenv("CORS_ALLOWED_ORIGINS") } }() // Définir explicitement CORS_ALLOWED_ORIGINS os.Setenv("CORS_ALLOWED_ORIGINS", "https://example.com,https://app.example.com") origins := getCORSOrigins("production", "veza.fr") assert.Equal(t, []string{"https://example.com", "https://app.example.com"}, origins, "Should use explicit CORS_ALLOWED_ORIGINS value") }