diff --git a/backend/src/settings.rs b/backend/src/settings.rs index 51c2ed6..bbd3a6e 100644 --- a/backend/src/settings.rs +++ b/backend/src/settings.rs @@ -336,4 +336,115 @@ mod tests { assert_eq!(settings.burst_size, 100); // default assert_eq!(settings.per_seconds, 60); // default } + + // T009: Tests for CorsSettings struct (TDD - write tests first) + #[test] + fn cors_settings_deserialize_from_yaml() { + let yaml = r#" + allowed_origins: + - "http://localhost:5173" + - "https://sta.example.com" + allow_credentials: true + max_age_secs: 7200 + "#; + let settings: CorsSettings = serde_yaml::from_str(yaml).unwrap(); + assert_eq!(settings.allowed_origins.len(), 2); + assert_eq!(settings.allowed_origins[0], "http://localhost:5173"); + assert_eq!(settings.allowed_origins[1], "https://sta.example.com"); + assert!(settings.allow_credentials); + assert_eq!(settings.max_age_secs, 7200); + } + + #[test] + fn cors_settings_default_has_empty_origins() { + let settings = CorsSettings::default(); + assert!( + settings.allowed_origins.is_empty(), + "Default CorsSettings should have empty allowed_origins for restrictive fail-safe" + ); + assert!( + !settings.allow_credentials, + "Default CorsSettings should have credentials disabled" + ); + assert_eq!( + settings.max_age_secs, 3600, + "Default CorsSettings should have 1 hour max_age" + ); + } + + #[test] + fn cors_settings_with_wildcard_deserializes() { + let yaml = r#" + allowed_origins: + - "*" + allow_credentials: false + max_age_secs: 3600 + "#; + let settings: CorsSettings = serde_yaml::from_str(yaml).unwrap(); + assert_eq!(settings.allowed_origins.len(), 1); + assert_eq!(settings.allowed_origins[0], "*"); + assert!(!settings.allow_credentials); + assert_eq!(settings.max_age_secs, 3600); + } + + #[test] + fn settings_loads_cors_section_from_yaml() { + // Create a temporary settings file with CORS configuration + let yaml_content = r#" +application: + name: "test-app" + version: "1.0.0" + port: 3100 + host: "127.0.0.1" + base_url: "http://127.0.0.1:3100" + protocol: "http" + +debug: false +frontend_url: "http://localhost:5173" + +rate_limit: + enabled: true + burst_size: 100 + per_seconds: 60 + +cors: + allowed_origins: + - "http://localhost:5173" + allow_credentials: false + max_age_secs: 3600 + +modbus: + host: "192.168.0.200" + port: 502 + slave_id: 0 + timeout_secs: 5 + +relay: + label_max_length: 50 + "#; + + // Use serde_yaml to deserialize directly + let settings: Settings = serde_yaml::from_str(yaml_content).unwrap(); + + // Verify CORS settings were loaded + assert_eq!(settings.cors.allowed_origins.len(), 1); + assert_eq!(settings.cors.allowed_origins[0], "http://localhost:5173"); + assert!(!settings.cors.allow_credentials); + assert_eq!(settings.cors.max_age_secs, 3600); + } + + #[test] + fn cors_settings_deserialize_with_defaults() { + // Test partial deserialization using serde defaults + let yaml = r#" + allowed_origins: + - "https://example.com" + "#; + let settings: CorsSettings = serde_yaml::from_str(yaml).unwrap(); + assert_eq!(settings.allowed_origins.len(), 1); + assert_eq!(settings.allowed_origins[0], "https://example.com"); + // These should use defaults + assert!(!settings.allow_credentials); + assert_eq!(settings.max_age_secs, 3600); + } }