changes
All checks were successful
CI / ci (push) Successful in 19m38s

This commit is contained in:
2026-08-26 20:55:30 +02:00
parent a557c183e9
commit 23d052278a
523 changed files with 24448 additions and 2005 deletions

View File

@@ -0,0 +1,12 @@
use domain::metric::AlcoholicDrinks;
#[test]
fn a_count_of_drinks_no_one_survives_is_rejected() {
assert!(AlcoholicDrinks::new(61).is_err());
}
#[test]
fn the_boundaries_of_a_days_drinking_are_valid() {
assert_eq!(AlcoholicDrinks::new(0).unwrap().value(), 0);
assert_eq!(AlcoholicDrinks::new(60).unwrap().value(), 60);
}

View File

@@ -0,0 +1,12 @@
use domain::metric::AwakeMinutes;
#[test]
fn more_awake_minutes_than_a_day_holds_are_rejected() {
assert!(AwakeMinutes::new(1_441).is_err());
}
#[test]
fn the_boundaries_of_time_spent_awake_are_valid() {
assert_eq!(AwakeMinutes::new(0).unwrap().value(), 0);
assert_eq!(AwakeMinutes::new(1_440).unwrap().value(), 1_440);
}

View File

@@ -0,0 +1,53 @@
use domain::entry::Date;
use domain::metric::{DailyMetric, MetricValue, Source, Steps};
use domain::provider::ProviderName;
use domain::user::UserId;
fn a_date() -> Date {
Date::from_persistence("2026-08-26".parse().unwrap())
}
fn steps(count: u32, source: Source) -> DailyMetric {
DailyMetric::new(
UserId::generate(),
a_date(),
MetricValue::Steps(Steps::new(count).unwrap()),
source,
)
}
fn a_provider() -> Source {
Source::Provider(ProviderName::new("healthkit").unwrap())
}
#[test]
fn a_manual_count_supersedes_one_a_provider_reported() {
let manual = steps(8_412, Source::Manual);
let imported = steps(8_000, a_provider());
assert!(manual.supersedes(&imported));
}
#[test]
fn a_provider_does_not_overwrite_a_count_the_user_stated() {
let manual = steps(8_412, Source::Manual);
let imported = steps(8_000, a_provider());
assert!(!imported.supersedes(&manual));
}
#[test]
fn a_later_import_replaces_an_earlier_one() {
let earlier = steps(8_000, a_provider());
let later = steps(8_412, a_provider());
assert!(later.supersedes(&earlier));
}
#[test]
fn a_correction_replaces_the_count_the_user_stated_before() {
let stated = steps(8_000, Source::Manual);
let corrected = steps(8_412, Source::Manual);
assert!(corrected.supersedes(&stated));
}

View File

@@ -0,0 +1,12 @@
use domain::metric::ExerciseMinutes;
#[test]
fn more_exercise_than_a_day_holds_is_rejected() {
assert!(ExerciseMinutes::new(1_441).is_err());
}
#[test]
fn the_boundaries_of_a_days_exercise_are_valid() {
assert_eq!(ExerciseMinutes::new(0).unwrap().value(), 0);
assert_eq!(ExerciseMinutes::new(1_440).unwrap().value(), 1_440);
}

View File

@@ -0,0 +1,17 @@
use domain::metric::Hrv;
#[test]
fn a_variability_of_zero_is_rejected() {
assert!(Hrv::new(0).is_err());
}
#[test]
fn a_variability_beyond_any_recorded_reading_is_rejected() {
assert!(Hrv::new(301).is_err());
}
#[test]
fn the_boundaries_of_variability_are_valid() {
assert_eq!(Hrv::new(1).unwrap().value(), 1);
assert_eq!(Hrv::new(300).unwrap().value(), 300);
}

View File

@@ -0,0 +1,45 @@
use domain::metric::MetricKind;
const EVERY_KIND: [MetricKind; 8] = [
MetricKind::Steps,
MetricKind::SleepMinutes,
MetricKind::AwakeMinutes,
MetricKind::RestingHeartRate,
MetricKind::Hrv,
MetricKind::ExerciseMinutes,
MetricKind::ScreenTimeMinutes,
MetricKind::AlcoholicDrinks,
];
fn wire_name(kind: MetricKind) -> &'static str {
match kind {
MetricKind::Steps => "steps",
MetricKind::SleepMinutes => "sleepMinutes",
MetricKind::AwakeMinutes => "awakeMinutes",
MetricKind::RestingHeartRate => "restingHeartRate",
MetricKind::Hrv => "hrv",
MetricKind::ExerciseMinutes => "exerciseMinutes",
MetricKind::ScreenTimeMinutes => "screenTimeMinutes",
MetricKind::AlcoholicDrinks => "alcoholicDrinks",
}
}
#[test]
fn every_kind_keeps_the_name_clients_and_rows_already_use() {
for kind in EVERY_KIND {
assert_eq!(kind.name(), wire_name(kind));
}
}
#[test]
fn every_name_resolves_back_to_its_kind() {
for kind in EVERY_KIND {
assert_eq!(MetricKind::from_name(kind.name()), Some(kind));
}
}
#[test]
fn a_name_this_build_does_not_know_resolves_to_nothing() {
assert_eq!(MetricKind::from_name("telepathy"), None);
assert_eq!(MetricKind::from_name("caffeine"), None);
}

View File

@@ -0,0 +1,8 @@
use domain::metric::{MetricKind, MetricValue, Steps};
#[test]
fn a_values_kind_is_derived_from_the_value_itself() {
let value = MetricValue::Steps(Steps::new(8_412).unwrap());
assert_eq!(value.kind(), MetricKind::Steps);
}

View File

@@ -0,0 +1,13 @@
use domain::metric::RestingHeartRate;
#[test]
fn a_resting_rate_no_living_person_has_is_rejected() {
assert!(RestingHeartRate::new(24).is_err());
assert!(RestingHeartRate::new(121).is_err());
}
#[test]
fn the_range_covers_athletes_and_the_unwell() {
assert_eq!(RestingHeartRate::new(25).unwrap().value(), 25);
assert_eq!(RestingHeartRate::new(120).unwrap().value(), 120);
}

View File

@@ -0,0 +1,12 @@
use domain::metric::ScreenTimeMinutes;
#[test]
fn more_screen_time_than_a_day_holds_is_rejected() {
assert!(ScreenTimeMinutes::new(1_441).is_err());
}
#[test]
fn the_boundaries_of_a_days_screen_time_are_valid() {
assert_eq!(ScreenTimeMinutes::new(0).unwrap().value(), 0);
assert_eq!(ScreenTimeMinutes::new(1_440).unwrap().value(), 1_440);
}

View File

@@ -0,0 +1,12 @@
use domain::metric::SleepMinutes;
#[test]
fn a_night_longer_than_a_day_is_rejected() {
assert!(SleepMinutes::new(1_441).is_err());
}
#[test]
fn the_boundaries_of_a_nights_sleep_are_valid() {
assert_eq!(SleepMinutes::new(0).unwrap().value(), 0);
assert_eq!(SleepMinutes::new(1_440).unwrap().value(), 1_440);
}

View File

@@ -0,0 +1,12 @@
use domain::metric::Steps;
#[test]
fn a_step_count_beyond_a_days_maximum_is_rejected() {
assert!(Steps::new(200_001).is_err());
}
#[test]
fn the_boundaries_of_a_days_step_count_are_valid() {
assert_eq!(Steps::new(0).unwrap().value(), 0);
assert_eq!(Steps::new(200_000).unwrap().value(), 200_000);
}