#[cfg(test)]
mod tests {
use chrono::Duration;
use kasl::libs::formatter::{FormattedEvent, format_duration};
use serial_test::serial;
#[serial]
#[test]
fn test_format_duration_zero() {
let duration = Duration::zero();
assert_eq!(format_duration(&duration), "00:00");
}
#[serial]
#[test]
fn test_format_duration_minutes_only() {
let duration = Duration::minutes(30);
assert_eq!(format_duration(&duration), "00:30");
let duration = Duration::minutes(59);
assert_eq!(format_duration(&duration), "00:59");
let duration = Duration::minutes(1);
assert_eq!(format_duration(&duration), "00:01");
}
#[serial]
#[test]
fn test_format_duration_hours_only() {
let duration = Duration::hours(1);
assert_eq!(format_duration(&duration), "01:00");
let duration = Duration::hours(8);
assert_eq!(format_duration(&duration), "08:00");
let duration = Duration::hours(12);
assert_eq!(format_duration(&duration), "12:00");
}
#[serial]
#[test]
fn test_format_duration_hours_and_minutes() {
let duration = Duration::hours(1) + Duration::minutes(30);
assert_eq!(format_duration(&duration), "01:30");
let duration = Duration::hours(8) + Duration::minutes(45);
assert_eq!(format_duration(&duration), "08:45");
let duration = Duration::hours(2) + Duration::minutes(5);
assert_eq!(format_duration(&duration), "02:05");
}
#[serial]
#[test]
fn test_format_duration_large_hours() {
let duration = Duration::hours(24);
assert_eq!(format_duration(&duration), "24:00");
let duration = Duration::hours(100);
assert_eq!(format_duration(&duration), "100:00");
let duration = Duration::hours(999);
assert_eq!(format_duration(&duration), "999:00");
}
#[serial]
#[test]
fn test_format_duration_negative_clamped_to_zero() {
let duration = Duration::minutes(-30);
assert_eq!(format_duration(&duration), "00:00");
let duration = Duration::hours(-5);
assert_eq!(format_duration(&duration), "00:00");
let duration = Duration::hours(-1) + Duration::minutes(-30);
assert_eq!(format_duration(&duration), "00:00");
}
#[serial]
#[test]
fn test_format_duration_seconds_rounded() {
let duration = Duration::minutes(30) + Duration::seconds(30);
assert_eq!(format_duration(&duration), "00:30");
let duration = Duration::minutes(30) + Duration::seconds(59);
assert_eq!(format_duration(&duration), "00:30");
let duration = Duration::minutes(30) + Duration::seconds(60);
assert_eq!(format_duration(&duration), "00:31");
}
#[serial]
#[test]
fn test_format_duration_complex_calculations() {
let duration = Duration::hours(2) + Duration::minutes(90); assert_eq!(format_duration(&duration), "03:30");
let duration = Duration::minutes(120) + Duration::minutes(15); assert_eq!(format_duration(&duration), "02:15");
let duration = Duration::seconds(3661); assert_eq!(format_duration(&duration), "01:01");
}
#[serial]
#[test]
fn test_formatted_event_creation() {
let event = FormattedEvent {
id: 1,
start: "09:00".to_string(),
end: "17:00".to_string(),
duration: "08:00".to_string(),
};
assert_eq!(event.id, 1);
assert_eq!(event.start, "09:00");
assert_eq!(event.end, "17:00");
assert_eq!(event.duration, "08:00");
}
#[serial]
#[test]
fn test_formatted_event_serialization() {
let event = FormattedEvent {
id: 2,
start: "14:30".to_string(),
end: "15:45".to_string(),
duration: "01:15".to_string(),
};
let json = serde_json::to_string(&event).unwrap();
assert!(json.contains("\"id\":2"));
assert!(json.contains("\"start\":\"14:30\""));
assert!(json.contains("\"end\":\"15:45\""));
assert!(json.contains("\"duration\":\"01:15\""));
let deserialized: FormattedEvent = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized.id, event.id);
assert_eq!(deserialized.start, event.start);
assert_eq!(deserialized.end, event.end);
assert_eq!(deserialized.duration, event.duration);
}
#[serial]
#[test]
fn test_formatted_event_clone() {
let event = FormattedEvent {
id: 3,
start: "10:00".to_string(),
end: "12:00".to_string(),
duration: "02:00".to_string(),
};
let cloned = event.clone();
assert_eq!(event.id, cloned.id);
assert_eq!(event.start, cloned.start);
assert_eq!(event.end, cloned.end);
assert_eq!(event.duration, cloned.duration);
}
#[serial]
#[test]
fn test_formatted_event_debug() {
let event = FormattedEvent {
id: 4,
start: "08:30".to_string(),
end: "16:30".to_string(),
duration: "08:00".to_string(),
};
let debug_str = format!("{:?}", event);
assert!(debug_str.contains("FormattedEvent"));
assert!(debug_str.contains("id: 4"));
assert!(debug_str.contains("start: \"08:30\""));
assert!(debug_str.contains("end: \"16:30\""));
assert!(debug_str.contains("duration: \"08:00\""));
}
#[serial]
#[test]
fn test_formatted_event_edge_cases() {
let event = FormattedEvent {
id: 0,
start: "".to_string(),
end: "".to_string(),
duration: "".to_string(),
};
assert_eq!(event.id, 0);
assert!(event.start.is_empty());
assert!(event.end.is_empty());
assert!(event.duration.is_empty());
let event = FormattedEvent {
id: -1,
start: "--:--".to_string(),
end: "-".to_string(),
duration: "00:00".to_string(),
};
assert_eq!(event.id, -1);
assert_eq!(event.start, "--:--");
assert_eq!(event.end, "-");
assert_eq!(event.duration, "00:00");
}
#[serial]
#[test]
fn test_formatted_event_typical_work_scenarios() {
let morning = FormattedEvent {
id: 1,
start: "09:00".to_string(),
end: "12:00".to_string(),
duration: "03:00".to_string(),
};
let lunch = FormattedEvent {
id: 2,
start: "12:00".to_string(),
end: "13:00".to_string(),
duration: "01:00".to_string(),
};
let afternoon = FormattedEvent {
id: 3,
start: "13:00".to_string(),
end: "17:30".to_string(),
duration: "04:30".to_string(),
};
assert_eq!(morning.duration, "03:00");
assert_eq!(lunch.duration, "01:00");
assert_eq!(afternoon.duration, "04:30");
}
#[serial]
#[test]
fn test_duration_formatting_consistency() {
let duration1 = Duration::hours(2) + Duration::minutes(30);
let duration2 = Duration::minutes(150);
assert_eq!(format_duration(&duration1), format_duration(&duration2));
assert_eq!(format_duration(&duration1), "02:30");
}
#[serial]
#[test]
fn test_duration_formatting_thread_safety() {
use std::sync::Arc;
use std::thread;
let duration = Arc::new(Duration::hours(1) + Duration::minutes(45));
let expected = "01:45";
let handles: Vec<_> = (0..10)
.map(|_| {
let duration = Arc::clone(&duration);
thread::spawn(move || format_duration(&duration))
})
.collect();
for handle in handles {
let result = handle.join().unwrap();
assert_eq!(result, expected);
}
}
#[serial]
#[test]
fn test_format_duration_boundary_values() {
let max_reasonable = Duration::hours(8760); let result = format_duration(&max_reasonable);
assert_eq!(result, "8760:00");
let almost_hour = Duration::minutes(59);
assert_eq!(format_duration(&almost_hour), "00:59");
let one_hour = Duration::minutes(60);
assert_eq!(format_duration(&one_hour), "01:00");
let hour_plus = Duration::minutes(61);
assert_eq!(format_duration(&hour_plus), "01:01");
}
}