#[cfg(test)]
mod tests {
use kasl::libs::productivity::Productivity;
use kasl::libs::pause::Pause;
use kasl::db::workdays::Workday;
use kasl::db::breaks::Break;
use chrono::{Duration, NaiveDate, NaiveDateTime, NaiveTime};
use tempfile::TempDir;
use test_context::{test_context, TestContext};
struct ProductivityTestContext {
_temp_dir: TempDir,
}
impl TestContext for ProductivityTestContext {
fn setup() -> Self {
let temp_dir = tempfile::tempdir().unwrap();
std::env::set_var("HOME", temp_dir.path());
std::env::set_var("LOCALAPPDATA", temp_dir.path());
ProductivityTestContext { _temp_dir: temp_dir }
}
}
fn create_test_workday() -> Workday {
let date = NaiveDate::from_ymd_opt(2024, 1, 15).unwrap();
let start = NaiveDateTime::new(date, NaiveTime::from_hms_opt(9, 0, 0).unwrap());
let end = NaiveDateTime::new(date, NaiveTime::from_hms_opt(17, 0, 0).unwrap());
Workday {
id: 1,
date,
start,
end: Some(end),
}
}
fn create_test_workday_with_duration(duration: Duration) -> Workday {
let date = NaiveDate::from_ymd_opt(2024, 1, 15).unwrap();
let start = NaiveDateTime::new(date, NaiveTime::from_hms_opt(9, 0, 0).unwrap());
let end = start + duration;
Workday {
id: 1,
date,
start,
end: Some(end),
}
}
#[test_context(ProductivityTestContext)]
#[test]
fn test_productivity_calculation_no_pauses(_ctx: &mut ProductivityTestContext) {
let workday = create_test_workday();
let pauses = vec![];
let breaks = vec![];
let productivity_calc = Productivity::with_test_data(&workday, breaks, vec![], pauses);
let productivity = productivity_calc.calculate_productivity();
assert_eq!(productivity, 100.0);
}
#[test_context(ProductivityTestContext)]
#[test]
fn test_productivity_calculation_with_pauses(_ctx: &mut ProductivityTestContext) {
let workday = create_test_workday();
let pauses = vec![
Pause {
id: 1,
start: NaiveDateTime::new(workday.date, NaiveTime::from_hms_opt(10, 0, 0).unwrap()),
end: Some(NaiveDateTime::new(workday.date, NaiveTime::from_hms_opt(10, 15, 0).unwrap())),
duration: Some(Duration::minutes(15)),
}
];
let breaks = vec![];
let productivity_calc = Productivity::with_test_data(&workday, breaks, pauses, vec![]);
let productivity = productivity_calc.calculate_productivity();
assert!((productivity - 96.875).abs() < 0.001);
}
#[test_context(ProductivityTestContext)]
#[test]
fn test_productivity_calculation_with_breaks(_ctx: &mut ProductivityTestContext) {
let workday = create_test_workday();
let pauses = vec![];
let breaks = vec![
Break {
id: Some(1),
date: workday.date,
start: NaiveDateTime::new(workday.date, NaiveTime::from_hms_opt(12, 0, 0).unwrap()),
end: NaiveDateTime::new(workday.date, NaiveTime::from_hms_opt(13, 0, 0).unwrap()),
duration: Duration::hours(1),
reason: Some("Lunch break".to_string()),
created_at: Some(NaiveDateTime::new(workday.date, NaiveTime::from_hms_opt(12, 0, 0).unwrap())),
}
];
let productivity_calc = Productivity::with_test_data(&workday, breaks, vec![], pauses);
let productivity = productivity_calc.calculate_productivity();
assert_eq!(productivity, 100.0);
}
#[test_context(ProductivityTestContext)]
#[test]
fn test_productivity_calculation_with_pauses_and_breaks(_ctx: &mut ProductivityTestContext) {
let workday = create_test_workday();
let pauses = vec![
Pause {
id: 1,
start: NaiveDateTime::new(workday.date, NaiveTime::from_hms_opt(10, 0, 0).unwrap()),
end: Some(NaiveDateTime::new(workday.date, NaiveTime::from_hms_opt(10, 15, 0).unwrap())),
duration: Some(Duration::minutes(15)),
}
];
let breaks = vec![
Break {
id: Some(1),
date: workday.date,
start: NaiveDateTime::new(workday.date, NaiveTime::from_hms_opt(12, 0, 0).unwrap()),
end: NaiveDateTime::new(workday.date, NaiveTime::from_hms_opt(13, 0, 0).unwrap()),
duration: Duration::hours(1),
reason: Some("Lunch break".to_string()),
created_at: Some(NaiveDateTime::new(workday.date, NaiveTime::from_hms_opt(12, 0, 0).unwrap())),
}
];
let productivity_calc = Productivity::with_test_data(&workday, breaks, pauses, vec![]);
let productivity = productivity_calc.calculate_productivity();
assert_eq!(productivity, 100.0);
}
#[test_context(ProductivityTestContext)]
#[test]
fn test_productivity_for_intervals_no_pauses(_ctx: &mut ProductivityTestContext) {
let work_time = Duration::hours(6);
let workday = create_test_workday_with_duration(work_time);
let pauses = vec![];
let breaks = vec![];
let productivity_calc = Productivity::with_test_data(&workday, breaks, vec![], pauses);
let productivity = productivity_calc.calculate_productivity();
assert_eq!(productivity, 100.0);
}
#[test_context(ProductivityTestContext)]
#[test]
fn test_productivity_for_intervals_with_pauses(_ctx: &mut ProductivityTestContext) {
let work_time = Duration::hours(6);
let workday = create_test_workday_with_duration(work_time);
let pauses = vec![
Pause {
id: 1,
start: NaiveDate::from_ymd_opt(2024, 1, 15).unwrap().and_hms_opt(10, 0, 0).unwrap(),
end: Some(NaiveDate::from_ymd_opt(2024, 1, 15).unwrap().and_hms_opt(10, 15, 0).unwrap()),
duration: Some(Duration::minutes(15)),
}
];
let breaks = vec![];
let productivity_calc = Productivity::with_test_data(&workday, breaks, pauses, vec![]);
let productivity = productivity_calc.calculate_productivity();
assert!((productivity - 95.833333).abs() < 0.001);
}
#[test_context(ProductivityTestContext)]
#[test]
fn test_productivity_edge_cases(_ctx: &mut ProductivityTestContext) {
let zero_work = Duration::zero();
let workday = create_test_workday_with_duration(zero_work);
let productivity_calc = Productivity::with_test_data(&workday, vec![], vec![], vec![]);
let productivity = productivity_calc.calculate_productivity();
assert_eq!(productivity, 0.0);
let work_time = Duration::hours(1);
let workday = create_test_workday_with_duration(work_time);
let negative_pause = vec![
Pause {
id: 1,
start: NaiveDate::from_ymd_opt(2024, 1, 15).unwrap().and_hms_opt(10, 0, 0).unwrap(),
end: Some(NaiveDate::from_ymd_opt(2024, 1, 15).unwrap().and_hms_opt(9, 0, 0).unwrap()), duration: Some(Duration::hours(-2)), }
];
let productivity_calc = Productivity::with_test_data(&workday, vec![], negative_pause, vec![]);
let productivity = productivity_calc.calculate_productivity();
assert!(productivity >= 0.0 && productivity <= 100.0);
}
#[test_context(ProductivityTestContext)]
#[test]
fn test_productivity_boundary_values(_ctx: &mut ProductivityTestContext) {
let workday = create_test_workday();
let massive_pause = vec![
Pause {
id: 1,
start: workday.start,
end: workday.end,
duration: Some(Duration::hours(8)),
}
];
let productivity_calc = Productivity::with_test_data(&workday, vec![], massive_pause, vec![]);
let productivity = productivity_calc.calculate_productivity();
assert_eq!(productivity, 0.0);
let massive_break = vec![
Break {
id: Some(1),
date: workday.date,
start: workday.start,
end: workday.end.unwrap(),
duration: Duration::hours(8),
reason: Some("All day break".to_string()),
created_at: Some(workday.start),
}
];
let productivity_calc = Productivity::with_test_data(&workday, massive_break, vec![], vec![]);
let productivity = productivity_calc.calculate_productivity();
assert_eq!(productivity, 0.0);
}
}