mirror of
https://github.com/nikolassv/bartib
synced 2024-11-10 14:14:12 +00:00
feat: add unit tests
This commit is contained in:
parent
a5f06ab7d1
commit
4b8abdb4e1
4 changed files with 227 additions and 12 deletions
|
@ -1,4 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use chrono::Local;
|
||||
|
||||
use crate::data::activity;
|
||||
use crate::data::activity::Activity;
|
||||
|
@ -26,6 +27,8 @@ pub fn show_status(
|
|||
|
||||
filtered_activities.sort_by_key(|activity| activity.start);
|
||||
|
||||
let now = Local::now().naive_local();
|
||||
|
||||
let current: Option<&Activity> = filtered_activities
|
||||
.clone()
|
||||
.into_iter()
|
||||
|
@ -36,20 +39,20 @@ pub fn show_status(
|
|||
let today = filtered_activities
|
||||
.clone()
|
||||
.into_iter()
|
||||
.filter(Filters::today())
|
||||
.filter(Filters::today(now.date()))
|
||||
.map(|f| f.get_duration())
|
||||
.sum();
|
||||
|
||||
let current_week = filtered_activities
|
||||
.clone()
|
||||
.into_iter()
|
||||
.filter(Filters::current_week())
|
||||
.filter(Filters::current_week(now.date()))
|
||||
.map(|f| f.get_duration())
|
||||
.sum();
|
||||
|
||||
let current_month = filtered_activities
|
||||
.into_iter()
|
||||
.filter(Filters::current_month())
|
||||
.filter(Filters::current_month(now.date()))
|
||||
.map(|f| f.get_duration())
|
||||
.sum();
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::data::activity::Activity;
|
||||
|
||||
use chrono::{Datelike, Duration, Local, NaiveDate};
|
||||
use chrono::{Datelike, Duration, NaiveDate};
|
||||
|
||||
pub struct Filters {}
|
||||
|
||||
|
@ -8,20 +8,17 @@ impl Filters {
|
|||
pub fn active(activity: &&Activity) -> bool {
|
||||
!activity.is_stopped()
|
||||
}
|
||||
pub fn today() -> impl Fn(&&Activity) -> bool {
|
||||
let today = Local::now().naive_local().date();
|
||||
pub fn today(today: NaiveDate) -> impl Fn(&&Activity) -> bool {
|
||||
move |activity: &&Activity| activity.start.date() == today
|
||||
}
|
||||
pub fn current_week() -> impl Fn(&&Activity) -> bool {
|
||||
let today = Local::now().naive_local().date();
|
||||
pub fn current_week(today: NaiveDate) -> impl Fn(&&Activity) -> bool {
|
||||
let from_date = today - Duration::days(i64::from(today.weekday().num_days_from_monday()));
|
||||
let to_date = today;
|
||||
move |activity: &&Activity| {
|
||||
activity.start.date() >= from_date && activity.start.date() <= to_date
|
||||
}
|
||||
}
|
||||
pub fn current_month() -> impl Fn(&&Activity) -> bool {
|
||||
let today = Local::now().naive_local().date();
|
||||
pub fn current_month(today: NaiveDate) -> impl Fn(&&Activity) -> bool {
|
||||
let from_date = NaiveDate::from_ymd_opt(today.year(), today.month(), 1).unwrap();
|
||||
let to_date = today;
|
||||
move |activity: &&Activity| {
|
||||
|
@ -29,3 +26,95 @@ impl Filters {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use chrono::NaiveDateTime;
|
||||
|
||||
use crate::data::activity;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn filter_active() {
|
||||
let activities = data();
|
||||
let res: Vec<&Activity> = activities.iter().filter(Filters::active).collect();
|
||||
assert_eq!(res.len(), 1);
|
||||
assert_eq!(res.first().unwrap().description.as_str(), "d4");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn filter_today() {
|
||||
let now = date(2024, 3, 19);
|
||||
let activities = data();
|
||||
let res: Vec<&Activity> = activities
|
||||
.iter()
|
||||
.filter(Filters::today(now.date()))
|
||||
.collect();
|
||||
assert_eq!(res.len(), 2);
|
||||
assert_eq!(res.first().unwrap().description.as_str(), "d3");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn filter_current_week() {
|
||||
let now = date(2024, 3, 19);
|
||||
let activities = data();
|
||||
let res: Vec<&Activity> = activities
|
||||
.iter()
|
||||
.filter(Filters::current_week(now.date()))
|
||||
.collect();
|
||||
assert_eq!(res.len(), 3);
|
||||
assert_eq!(res.first().unwrap().description.as_str(), "d2");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn filter_current_month() {
|
||||
let now = date(2024, 3, 19);
|
||||
let activities = data();
|
||||
let res: Vec<&Activity> = activities
|
||||
.iter()
|
||||
.filter(Filters::current_month(now.date()))
|
||||
.collect();
|
||||
assert_eq!(res.len(), 4);
|
||||
assert_eq!(res.first().unwrap().description.as_str(), "d1");
|
||||
}
|
||||
|
||||
fn data() -> Vec<Activity> {
|
||||
let a0 = activity::Activity {
|
||||
project: "p1".to_string(),
|
||||
description: "d0".to_string(),
|
||||
start: date(2024, 2, 11),
|
||||
end: Some(date(2024, 2, 11) + Duration::hours(2)),
|
||||
};
|
||||
let a1 = activity::Activity {
|
||||
project: "p1".to_string(),
|
||||
description: "d1".to_string(),
|
||||
start: date(2024, 3, 11),
|
||||
end: Some(date(2024, 3, 11) + Duration::hours(2)),
|
||||
};
|
||||
let a2 = activity::Activity {
|
||||
project: "p1".to_string(),
|
||||
description: "d2".to_string(),
|
||||
start: date(2024, 3, 18),
|
||||
end: Some(date(2024, 3, 18) + Duration::hours(2)),
|
||||
};
|
||||
let a3 = activity::Activity {
|
||||
project: "p1".to_string(),
|
||||
description: "d3".to_string(),
|
||||
start: date(2024, 3, 19),
|
||||
end: Some(date(2024, 3, 19) + Duration::hours(2)),
|
||||
};
|
||||
let a4 = activity::Activity {
|
||||
project: "p1".to_string(),
|
||||
description: "d4".to_string(),
|
||||
start: date(2024, 3, 19),
|
||||
end: None,
|
||||
};
|
||||
return vec![a0, a1, a2, a3, a4];
|
||||
}
|
||||
|
||||
fn date(year: i32, month: u32, day: u32) -> NaiveDateTime {
|
||||
let date = NaiveDate::from_ymd_opt(year, month, day).unwrap();
|
||||
return NaiveDateTime::new(date, chrono::NaiveTime::from_hms_opt(10, 0, 0).unwrap());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ pub struct StatusReportData<'a> {
|
|||
pub current_month: Duration,
|
||||
}
|
||||
pub trait StatusReportWriter {
|
||||
fn process<'a>(&self, data: &'a StatusReportData) -> Result<()>;
|
||||
fn process(&self, data: &StatusReportData) -> Result<()>;
|
||||
}
|
||||
|
||||
pub struct RoundProcessor {
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::view::format_util;
|
|||
pub struct StatusReport {}
|
||||
|
||||
impl StatusReportWriter for StatusReport {
|
||||
fn process<'a>(&self, data: &'a StatusReportData) -> anyhow::Result<()> {
|
||||
fn process(&self, data: &StatusReportData) -> anyhow::Result<()> {
|
||||
println!("{data}");
|
||||
Ok(())
|
||||
}
|
||||
|
@ -117,3 +117,126 @@ fn write_period(
|
|||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use chrono::Local;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn report_test() {
|
||||
let data = StatusReportData {
|
||||
activity: None,
|
||||
project: None,
|
||||
current_month: Duration::hours(10),
|
||||
current_week: Duration::hours(5),
|
||||
today: Duration::minutes(30),
|
||||
};
|
||||
let expected = "\u{1b}[2m
|
||||
=======<>[3m Status for <>[1mALL<>[3m projects <>[2m =======
|
||||
<>[2;3m
|
||||
NOW: <>[1m NO Activity
|
||||
|
||||
<>[3m <>[2;3m Today......................... <>[1m30m<>[3m
|
||||
<>[3m <>[2;3m Current week.................. <>[1m5h 00m<>[3m
|
||||
<>[3m <>[2;3m Current month................. <>[1m10h 00m<>[3m
|
||||
\u{1b}[0m";
|
||||
|
||||
let res = data.to_string();
|
||||
|
||||
assert_eq!(clean(res.as_str()), clean(expected));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn report_project_test() {
|
||||
let data = StatusReportData {
|
||||
activity: None,
|
||||
project: Some("project"),
|
||||
current_month: Duration::hours(10),
|
||||
current_week: Duration::hours(5),
|
||||
today: Duration::minutes(30),
|
||||
};
|
||||
let expected = "\u{1b}[2m
|
||||
=======<>[3m Status for project: <>[1mproject<>[2m =======
|
||||
<>[2;3m
|
||||
NOW: <>[1m NO Activity
|
||||
|
||||
<>[3m <>[2;3m Today......................... <>[1m30m<>[3m
|
||||
<>[3m <>[2;3m Current week.................. <>[1m5h 00m<>[3m
|
||||
<>[3m <>[2;3m Current month................. <>[1m10h 00m<>[3m
|
||||
\u{1b}[0m";
|
||||
|
||||
let res = data.to_string();
|
||||
|
||||
assert_eq!(clean(res.as_str()), clean(expected));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn report_active_test() {
|
||||
let now = Local::now().naive_local();
|
||||
let act = activity::Activity {
|
||||
start: now - Duration::minutes(10),
|
||||
end: None,
|
||||
project: "project".to_string(),
|
||||
description: "olia".to_string(),
|
||||
};
|
||||
let data = StatusReportData {
|
||||
activity: Some(&act),
|
||||
project: Some("project"),
|
||||
current_month: Duration::hours(10),
|
||||
current_week: Duration::hours(5),
|
||||
today: Duration::minutes(30),
|
||||
};
|
||||
let expected = "\u{1b}[2m
|
||||
=======<>[3m Status for project: <>[1mproject<>[2m =======
|
||||
<>[2;3m
|
||||
NOW: <>[1;32molia<>[2m ...... <>[1m10m<>[2m
|
||||
|
||||
<>[3m <>[2;3m Today......................... <>[1m30m<>[3m
|
||||
<>[3m <>[2;3m Current week.................. <>[1m5h 00m<>[3m
|
||||
<>[3m <>[2;3m Current month................. <>[1m10h 00m<>[3m
|
||||
\u{1b}[0m";
|
||||
|
||||
let res = data.to_string();
|
||||
|
||||
assert_eq!(clean(res.as_str()), clean(expected));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn report_active_and_project_test() {
|
||||
let now = Local::now().naive_local();
|
||||
let act = activity::Activity {
|
||||
start: now - Duration::minutes(10),
|
||||
end: None,
|
||||
project: "project".to_string(),
|
||||
description: "olia".to_string(),
|
||||
};
|
||||
let data = StatusReportData {
|
||||
activity: Some(&act),
|
||||
project: None,
|
||||
current_month: Duration::hours(10),
|
||||
current_week: Duration::hours(5),
|
||||
today: Duration::minutes(30),
|
||||
};
|
||||
let expected = "\u{1b}[2m
|
||||
=======<>[3m Status for <>[1mALL<>[3m projects <>[2m =======
|
||||
<>[2;3m
|
||||
NOW: <>[1;32molia<>[2;3m on <>[3mproject<>[2m ...... <>[1m10m<>[2m
|
||||
|
||||
<>[3m <>[2;3m Today......................... <>[1m30m<>[3m
|
||||
<>[3m <>[2;3m Current week.................. <>[1m5h 00m<>[3m
|
||||
<>[3m <>[2;3m Current month................. <>[1m10h 00m<>[3m
|
||||
\u{1b}[0m";
|
||||
|
||||
let res = data.to_string();
|
||||
|
||||
assert_eq!(clean(res.as_str()), clean(expected));
|
||||
}
|
||||
|
||||
fn clean(a: &str) -> String {
|
||||
let st_f = "\u{1b}[0m\u{1b}";
|
||||
let clean_res = a.replace(st_f, "<>");
|
||||
clean_res
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue