Skip to content

Commit

Permalink
test: implement journey test
Browse files Browse the repository at this point in the history
Signed-off-by: simonsan <14062932+simonsan@users.noreply.github.com>
  • Loading branch information
simonsan committed Mar 23, 2024
1 parent 142dc78 commit cda83b7
Show file tree
Hide file tree
Showing 14 changed files with 245 additions and 24 deletions.
25 changes: 25 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ tracing = "0.1.40"
typed-builder = "0.18.1"
ulid = "1.1.2"
wildmatch = "2.3.3"
simplelog = "0.12.2"

[package]
name = "pace-rs"
Expand Down
1 change: 1 addition & 0 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ insta = { workspace = true, features = ["toml", "redactions"] }
pace_testing = { workspace = true }
rstest = { workspace = true }
similar-asserts = { workspace = true, features = ["serde"] }
simplelog = { workspace = true }

[lints]
workspace = true
4 changes: 2 additions & 2 deletions crates/core/src/commands/reflect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,14 @@ pub struct ReflectCommandOptions {
)]
date_flags: Option<DateFlags>,

/// Time zone to use for the activity, e.g., "Europe/Amsterdam"
/// Time zone to use for displaying the reflections, e.g., "Europe/Amsterdam"
#[cfg_attr(
feature = "clap",
clap(long, value_name = "Time Zone", group = "tz", visible_alias = "tz")
)]
time_zone: Option<Tz>,

/// Time zone offset to use for the activity, e.g., "+0200" or "-0500". Format: ±HHMM
/// Time zone offset to use to display the reflections, e.g., "+0200" or "-0500". Format: ±HHMM
#[cfg_attr(
feature = "clap",
clap(
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/domain/activity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ impl Activity {
begin: PaceDateTime,
end: PaceDateTime,
) -> PaceResult<()> {
let end_opts = ActivityEndOptions::new(end, calculate_duration(&begin, end)?);
let end_opts = ActivityEndOptions::new(end, calculate_duration(&begin, &end)?);

debug!(
"Ending activity {} with duration calculations end_opts: {:?}",
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/storage/in_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ impl ActivityStateManagement for InMemoryActivityStorage {

let end_opts = ActivityEndOptions::new(
*end_opts.end_time(),
calculate_duration(&begin_time, *end_opts.end_time())?,
calculate_duration(&begin_time, end_opts.end_time())?,
);

debug!("End options: {:?}", end_opts);
Expand Down
7 changes: 0 additions & 7 deletions crates/core/tests/journey/hold_resume.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@ use pace_core::prelude::{
Activity, ActivityQuerying, ActivityReadOps, ActivityStateManagement, HoldOptions,
InMemoryActivityStorage, ResumeOptions, TestResult,
};
use pace_time::date_time::PaceDateTime;

#[test]
#[allow(clippy::too_many_lines)]
fn test_hold_resume_journey_for_activities_passes() -> TestResult<()> {
let storage = InMemoryActivityStorage::new();
let _now = PaceDateTime::now();

let first_og_activity = Activity::builder().description("Test activity").build();

Expand Down Expand Up @@ -196,8 +194,3 @@ fn test_hold_resume_journey_for_activities_passes() -> TestResult<()> {

Ok(())
}

// #[test]
// fn test_begin_and_end_activity_in_different_time_zones_passes() -> TestResult<()> {
// todo!("Implement this test.")
// }
9 changes: 9 additions & 0 deletions crates/core/tests/journey/main.rs
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
mod hold_resume;
mod start_finish_different_time_zone;

// DEBUGGING: To make life easier, you can import SimpleLogger from simplelog crate
//
// `use simplelog::{Config, SimpleLogger};`
//
// and use it like this to initialize the logger in your tests:
//
// `SimpleLogger::init(tracing::log::LevelFilter::Debug, Config::default())?;`
105 changes: 105 additions & 0 deletions crates/core/tests/journey/start_finish_different_time_zone.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use chrono::FixedOffset;
use eyre::OptionExt;
use pace_core::prelude::{
Activity, ActivityReadOps, ActivityStateManagement, EndOptions, InMemoryActivityStorage,
TestResult,
};
use pace_time::{date_time::PaceDateTime, duration::PaceDuration};

#[test]
#[allow(clippy::too_many_lines)]
fn test_begin_and_end_activity_in_different_time_zones_passes() -> TestResult<()> {
let storage = InMemoryActivityStorage::new();

// We start an activity in our time zone
let now = PaceDateTime::now();

let first_og_activity = Activity::builder()
.description("Our time zone")
.begin(now)
.build();

let first_begin_activity = storage.begin_activity(first_og_activity.clone())?;

let first_stored_activity = storage.read_activity(*first_begin_activity.guid())?;

assert_eq!(
first_og_activity.begin(),
first_stored_activity.activity().begin(),
"Stored activity has not the same begin time as the original activity."
);

assert_eq!(
first_og_activity.description(),
first_stored_activity.activity().description(),
"Stored activity has not the same description as the original activity."
);

assert_eq!(
first_og_activity.kind(),
first_stored_activity.activity().kind(),
"Stored activity has not the same kind as the original activity."
);

assert_ne!(
first_og_activity.status(),
first_stored_activity.activity().status(),
"Stored activity has the same status as the original activity. Which can't be, because it should be active."
);

assert!(
first_stored_activity.activity().status().is_active(),
"Stored activity is not active."
);

assert!(
first_og_activity.status().is_inactive(),
"Original activity is not inactive."
);

// use 3 hours as duration
let artificial_duration = 3 * 60 * 60;

// Now we end the activity in a different time zone
let end = PaceDateTime::now_with_offset("-0200".parse::<FixedOffset>()?)
.add_duration(PaceDuration::new(artificial_duration))?;

let ended_activity = storage
.end_last_unfinished_activity(EndOptions::builder().end_time(end).build())?
.ok_or_eyre("Activity was not ended.")?;

assert_eq!(
first_og_activity.begin(),
ended_activity.activity().begin(),
"Ended activity has not the same begin time as the original activity."
);

assert_eq!(
first_og_activity.description(),
ended_activity.activity().description(),
"Ended activity has not the same description as the original activity."
);

assert_eq!(
first_og_activity.kind(),
ended_activity.activity().kind(),
"Ended activity has not the same kind as the original activity."
);

assert!(
ended_activity.activity().status().is_ended(),
"Activity is not ended."
);

let read_ended_activity = storage.read_activity(*ended_activity.guid())?;

dbg!(&read_ended_activity);

// check activity lasted 3 hours
assert_eq!(
read_ended_activity.activity().duration()?,
PaceDuration::new(artificial_duration)
);

Ok(())
}
3 changes: 2 additions & 1 deletion crates/time/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ humantime = { workspace = true }
serde = { workspace = true }
serde_derive = { workspace = true }
thiserror = { workspace = true }
tracing = { workspace = true }
tracing = { workspace = true, features = ["log"] }
typed-builder = { workspace = true }

[dev-dependencies]
eyre = { workspace = true }
rstest = { workspace = true }

[lints]
workspace = true
51 changes: 49 additions & 2 deletions crates/time/src/date_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ use std::{
};

use chrono::{
DateTime, FixedOffset, Local, LocalResult, NaiveDate, NaiveDateTime, NaiveTime, SubsecRound,
TimeZone,
DateTime, Duration, FixedOffset, Local, LocalResult, NaiveDate, NaiveDateTime, NaiveTime,
SubsecRound, TimeZone,
};

use serde_derive::{Deserialize, Serialize};
use tracing::debug;

use crate::{
date::PaceDate,
duration::PaceDuration,
error::{PaceTimeErrorKind, PaceTimeResult},
time::PaceTime,
time_zone::PaceTimeZoneKind,
Expand Down Expand Up @@ -132,6 +133,38 @@ impl PaceDateTime {
pace_date_time_from_date_and_time_and_tz(date, time, time_zone)
}

/// Add a [`TimeDelta`] to the [`PaceDateTime`] and return a new [`PaceDateTime`]
///
/// # Arguments
///
/// * `rhs` - The [`TimeDelta`] to add
///
/// # Errors
///
/// Returns an error if the addition fails
///
/// # Returns
///
/// Returns the new [`PaceDateTime`] with the added [`TimeDelta`]
pub fn add_duration(self, rhs: PaceDuration) -> PaceTimeResult<Self> {
Ok(Self(
self.0
.checked_add_signed(
Duration::new(
i64::try_from(rhs.inner())
.map_err(PaceTimeErrorKind::FailedToConvertDurationToI64)?,
0,
)
.ok_or_else(|| {
PaceTimeErrorKind::ConversionToDurationFailed(format!("{rhs:?}"))
})?,
)
.ok_or_else(|| {
PaceTimeErrorKind::AddingTimeDeltaFailed(format!("{self} + {rhs:?}"))
})?,
))
}

// TODO! Implement this
// pub fn with_date_and_time(
// year: i32,
Expand Down Expand Up @@ -239,6 +272,20 @@ impl PaceDateTime {
pub fn now() -> Self {
Self(Local::now().round_subsecs(0).fixed_offset())
}

/// Create a new `PaceDateTime` with a [`FixedOffset`]
///
/// # Arguments
///
/// * `offset` - The [`FixedOffset`] to use
///
/// # Returns
///
/// Returns the new `PaceDateTime` with the given offset
#[must_use]
pub fn now_with_offset(offset: FixedOffset) -> Self {
Self(Local::now().round_subsecs(0).with_timezone(&offset))
}
}

impl Validate for PaceDateTime {
Expand Down
Loading

0 comments on commit cda83b7

Please sign in to comment.