diff --git a/src/free_api_v25/current/mod.rs b/src/free_api_v25/current/mod.rs index 4b8dbe5..0c87739 100644 --- a/src/free_api_v25/current/mod.rs +++ b/src/free_api_v25/current/mod.rs @@ -34,3 +34,6 @@ pub use response::*; pub use sys::*; pub use weather::*; pub use wind::*; + +#[cfg(test)] +mod tests; diff --git a/src/free_api_v25/current/tests.rs b/src/free_api_v25/current/tests.rs new file mode 100644 index 0000000..f47e45f --- /dev/null +++ b/src/free_api_v25/current/tests.rs @@ -0,0 +1,171 @@ +use super::*; + +#[test] +fn test_success_response() { + let json = r#" + { + "coord": {"lon": -0.1257, "lat": 51.5085}, + "weather": [{ + "id": 300, + "main": "Drizzle", + "description": "light intensity drizzle", + "icon": "09d" + }], + "main": { + "temp": 280.32, + "feels_like": 278.15, + "pressure": 1012, + "humidity": 81 + }, + "wind": { + "speed": 4.1, + "deg": 240 + }, + "name": "London", + "cod": 200 + }"#; + + let response: WeatherResponse = serde_json::from_str(json).unwrap(); + + assert!(response.is_success()); + assert_eq!(response.city(), Some("London")); + assert_eq!(response.temperature(), Some(280.32)); + assert_eq!(response.feels_like(), Some(278.15)); + assert_eq!(response.pressure(), Some(1012)); + assert_eq!(response.humidity(), Some(81)); + assert_eq!(response.wind_speed(), Some(4.1)); + + let weather = response.primary_weather().unwrap(); + assert_eq!(weather.main, "Drizzle"); + assert_eq!(weather.description, "light intensity drizzle"); +} + +#[test] +fn test_error_response() { + let json = r#" + { + "cod": 404, + "message": "city not found" + }"#; + + let response: WeatherResponse = serde_json::from_str(json).unwrap(); + + assert!(!response.is_success()); + assert_eq!(response.error_message(), Some("city not found")); + assert_eq!(response.city(), None); +} + +#[test] +fn test_partial_response() { + // Test that missing fields don't cause deserialization to fail + let json = r#"{"cod": 200, "name": "Paris"}"#; + let response: WeatherResponse = serde_json::from_str(json).unwrap(); + + assert!(response.is_success()); + assert_eq!(response.city(), Some("Paris")); + assert_eq!(response.temperature(), None); +} + +#[test] +fn test_wind_direction() { + assert_eq!( + Wind { + deg: Some(0), + ..Default::default() + } + .direction(), + Some("N") + ); + assert_eq!( + Wind { + deg: Some(90), + ..Default::default() + } + .direction(), + Some("E") + ); + assert_eq!( + Wind { + deg: Some(180), + ..Default::default() + } + .direction(), + Some("S") + ); + assert_eq!( + Wind { + deg: Some(270), + ..Default::default() + } + .direction(), + Some("W") + ); + assert_eq!( + Wind { + deg: Some(45), + ..Default::default() + } + .direction(), + Some("NE") + ); +} + +#[test] +fn test_precipitation_intensity() { + let light = Precipitation { + one_hour: Some(1.0), + ..Default::default() + }; + assert_eq!(light.intensity(), Some("Light")); + + let moderate = Precipitation { + one_hour: Some(5.0), + ..Default::default() + }; + assert_eq!(moderate.intensity(), Some("Moderate")); + + let heavy = Precipitation { + one_hour: Some(10.0), + ..Default::default() + }; + assert_eq!(heavy.intensity(), Some("Heavy")); +} + +#[test] +fn test_sys_daytime_none() { + let sys = Sys { + sunrise: None, + sunset: None, + ..Default::default() + }; + assert_eq!(sys.is_daytime(), None); +} + +#[test] +fn test_wind_direction_out_of_bounds() { + assert_eq!( + Wind { + deg: Some(361), + ..Default::default() + } + .direction(), + Some("N") + ); + assert_eq!( + Wind { + deg: Some(720), + ..Default::default() + } + .direction(), + Some("N") + ); +} + +#[test] +fn test_precipitation_three_hour_only() { + let p = Precipitation { + one_hour: None, + three_hour: Some(6.0), + }; + assert_eq!(p.intensity(), Some("Moderate")); // 6/3 = 2.0 → Light +}