From d2e35d8ba12520f99426d86507741a25674e1ca8 Mon Sep 17 00:00:00 2001 From: Abraham Toriz Date: Mon, 29 Aug 2022 19:04:15 -0400 Subject: [PATCH] most tests of the chart formatter passing --- src/formatters/chart.rs | 145 ++++++++++++++++++++++++++++++---------- 1 file changed, 109 insertions(+), 36 deletions(-) diff --git a/src/formatters/chart.rs b/src/formatters/chart.rs index 51d3e30..9d9bb9f 100644 --- a/src/formatters/chart.rs +++ b/src/formatters/chart.rs @@ -47,8 +47,25 @@ fn hour_blocks(hours: f64, block_minutes: usize) -> usize { (hours * 60.0) as usize / block_minutes } +fn week_total(week_accumulated: f64, weekly_goal_hours: f64) -> String { + let formatted_hours = if weekly_goal_hours == 0.0 { + format!("{week_accumulated:.1}") + } else if week_accumulated >= weekly_goal_hours { + Green.paint(format!("{week_accumulated:.1}")).to_string() + } else { + Red.paint(format!("{week_accumulated:.1}")).to_string() + }; + + formatted_hours + &if weekly_goal_hours == 0.0 { + String::from("") + } else { + format!("/{weekly_goal_hours:.1}") + } +} + pub fn print_formatted(entries: Vec, out: &mut W, facts: &Facts) -> Result<()> { if entries.is_empty() { + writeln!(out, "No entries to display")?; return Ok(()); } @@ -99,24 +116,21 @@ pub fn print_formatted(entries: Vec, out: &mut W, facts: &Facts for (i, date) in dates.enumerate() { let hours = *entries_by_date.get(&date).unwrap_or(&0.0); let current_day = WeekDay::from(date.weekday()); - week_accumulated += hours; if current_day == start_of_week && i != 0 { tabs.separator(' '); tabs.feed(vec![ String::from(""), String::from("Week"), - if week_accumulated >= weekly_goal_hours { - Green.paint(format!("{week_accumulated:.1}")).to_string() - } else { - Red.paint(format!("{week_accumulated:.1}")).to_string() - }, + week_total(week_accumulated, weekly_goal_hours), ]); tabs.separator(' '); week_accumulated = 0.0; } + week_accumulated += hours; + let daily_goal_blocks = hour_blocks(daily_goal_hours as f64, block_size_minutes); let chart_print = { // first print at most `daily_goal_blocks` characters in green @@ -155,11 +169,7 @@ pub fn print_formatted(entries: Vec, out: &mut W, facts: &Facts tabs.feed(vec![ String::from(""), String::from("Week"), - if week_accumulated >= weekly_goal_hours { - Green.paint(format!("{week_accumulated:.1}")).to_string() - } else { - Red.paint(format!("{week_accumulated:.1}")).to_string() - }, + week_total(week_accumulated, weekly_goal_hours), ]); out.write_all(tabs.print(facts.env.stdout_is_tty).as_bytes())?; @@ -172,6 +182,8 @@ mod tests { use pretty_assertions::assert_str_eq; use chrono::{Utc, TimeZone, Duration}; + use crate::config::{Config, FormattersSettings, ChartFormatterSettings}; + use super::*; #[test] @@ -190,50 +202,57 @@ mod tests { Entry::new_sample(4, day4, Some(day4 + Duration::hours(2))), ]; let mut out = Vec::new(); - let facts = Facts::new(); + let config = Config { + formatters: FormattersSettings { + chart: ChartFormatterSettings { + daily_goal_hours: 4, + weekly_goal_hours: 20, + ..Default::default() + }, + }, + ..Default::default() + }; + let facts = Facts::new().with_config(config); print_formatted(entries, &mut out, &facts).unwrap(); - assert_str_eq!(String::from_utf8_lossy(&out), " Date Day Chart Hours + assert_str_eq!(String::from_utf8_lossy(&out), " Date Day Chart Hours -Aug 15 Mon 5 - 16 Tue 3.5 - 17 Wed 4 - 18 Thu 2 +Aug 15 Mon \u{1b}[42m \u{1b}[0m\u{1b}[48;5;10m \u{1b}[0m 5.0 + 16 Tue \u{1b}[42m \u{1b}[0m\u{1b}[47m \u{1b}[0m 3.5 + 17 Wed \u{1b}[42m \u{1b}[0m 4.0 + 18 Thu \u{1b}[42m \u{1b}[0m\u{1b}[47m \u{1b}[0m 2.0 - Week 20h + Week \u{1b}[31m14.5\u{1b}[0m/20.0 "); } + /// If entries span more than one week, both are shown with a weekly result #[test] fn partitioned_week() { + std::env::set_var("TZ", "CST+6"); + + let day1 = Utc.ymd(2022, 8, 28).and_hms(12, 0, 0); + let day2 = Utc.ymd(2022, 8, 29).and_hms(12, 0, 0); + let entries = vec![ + Entry::new_sample(1, day1, Some(day1 + Duration::hours(5))), + Entry::new_sample(2, day2, Some(day2 + Duration::hours(3))), ]; let mut out = Vec::new(); let facts = Facts::new(); print_formatted(entries, &mut out, &facts).unwrap(); - assert_str_eq!(String::from_utf8_lossy(&out), "\ -Date Day Chart Hours + assert_str_eq!(String::from_utf8_lossy(&out), " Date Day Chart Hours -Aug 25 Mon 3 - 26 Tue 4 - 27 Wed 2 - 28 Thu 2.5 - 29 Fri 4.5 - 30 Sat 1 - 31 Sun 1.2 +Aug 28 Sun \u{1b}[48;5;10m \u{1b}[0m 5.0 - Week 19h + Week 5.0 -Sep 1 Mon 3 - 2 Tue 4 - 3 Wed 2 - 4 Thu 2.5 - 5 Fri 4.5 +Aug 29 Mon \u{1b}[48;5;10m \u{1b}[0m 3.0 - Week 20h + Week 3.0 "); } @@ -245,7 +264,7 @@ Sep 1 Mon 3 print_formatted(entries, &mut out, &facts).unwrap(); - assert_str_eq!(String::from_utf8_lossy(&out), "No entries\n"); + assert_str_eq!(String::from_utf8_lossy(&out), "No entries to display\n"); } #[test] @@ -255,6 +274,60 @@ Sep 1 Mon 3 #[test] fn days_without_hours_appear() { - assert!(false, "for completeness, if a date between the first shown date and the last one doesnt have any hours registered it should show as 0"); + std::env::set_var("TZ", "CST+6"); + + let day1 = Utc.ymd(2022, 8, 15).and_hms(12, 0, 0); + let day3 = Utc.ymd(2022, 8, 17).and_hms(12, 0, 0); + + let entries = vec![ + Entry::new_sample(1, day1, Some(day1 + Duration::hours(5))), + Entry::new_sample(3, day3, Some(day3 + Duration::hours(4))), + ]; + let mut out = Vec::new(); + let facts = Facts::new(); + + print_formatted(entries, &mut out, &facts).unwrap(); + + dbg!(String::from_utf8_lossy(&out)); + + assert_str_eq!(String::from_utf8_lossy(&out), " Date Day Chart Hours + +Aug 15 Mon \u{1b}[48;5;10m \u{1b}[0m 5.0 + 16 Tue 0.0 + 17 Wed \u{1b}[48;5;10m \u{1b}[0m 4.0 + + Week 9.0 +"); + } + + #[test] + fn display_without_goals_set() { + std::env::set_var("TZ", "CST+6"); + + let day1 = Utc.ymd(2022, 8, 15).and_hms(12, 0, 0); + let day2 = Utc.ymd(2022, 8, 16).and_hms(12, 0, 0); + let day3 = Utc.ymd(2022, 8, 17).and_hms(12, 0, 0); + let day4 = Utc.ymd(2022, 8, 18).and_hms(12, 0, 0); + + let entries = vec![ + Entry::new_sample(1, day1, Some(day1 + Duration::hours(5))), + Entry::new_sample(2, day2, Some(day2 + Duration::minutes(60 * 3 + 30))), + Entry::new_sample(3, day3, Some(day3 + Duration::hours(4))), + Entry::new_sample(4, day4, Some(day4 + Duration::hours(2))), + ]; + let mut out = Vec::new(); + let facts = Facts::new(); + + print_formatted(entries, &mut out, &facts).unwrap(); + + assert_str_eq!(String::from_utf8_lossy(&out), " Date Day Chart Hours + +Aug 15 Mon \u{1b}[48;5;10m \u{1b}[0m 5.0 + 16 Tue \u{1b}[48;5;10m \u{1b}[0m 3.5 + 17 Wed \u{1b}[48;5;10m \u{1b}[0m 4.0 + 18 Thu \u{1b}[48;5;10m \u{1b}[0m 2.0 + + Week 14.5 +"); } }