assertr 0.5.6

Fluent assertions for the Rust programming language.
Documentation
use crate::AssertThat;
use crate::mode::Mode;
use crate::tracking::AssertionTracking;
use indoc::writedoc;
use jiff::SignedDuration;
use std::fmt::Write;

#[allow(clippy::return_self_not_must_use)]
#[cfg_attr(feature = "fluent", assertr_derive::fluent_aliases)]
pub trait SignedDurationAssertions {
    fn is_zero(self) -> Self;

    fn is_negative(self) -> Self;

    fn is_positive(self) -> Self;

    fn is_close_to(self, expected: SignedDuration, allowed_deviation: SignedDuration) -> Self;
}

impl<M: Mode> SignedDurationAssertions for AssertThat<'_, SignedDuration, M> {
    #[track_caller]
    fn is_zero(self) -> Self {
        self.track_assertion();

        if !self.actual().is_zero() {
            self.add_detail_message("Actual was not zero.");

            let expected = SignedDuration::ZERO;
            self.fail(|w: &mut String| {
                writedoc! {w, r"
                    Expected: {expected:#?}

                      Actual: {actual:#?}
                ", actual = self.actual()}
            });
        }

        self
    }

    #[track_caller]
    fn is_negative(self) -> Self {
        self.track_assertion();

        if !self.actual().is_negative() {
            self.fail(|w: &mut String| {
                writedoc! {w, r"
                    Expected: {actual:#?} to be negative,

                      Actual: {actual:#?},
                ", actual = self.actual()}
            });
        }

        self
    }

    #[track_caller]
    fn is_positive(self) -> Self {
        self.track_assertion();

        if !self.actual().is_positive() {
            self.fail(|w: &mut String| {
                writedoc! {w, r"
                    Expected: {actual:#?} to be positive,

                      Actual: {actual:#?},
                ", actual = self.actual()}
            });
        }

        self
    }

    #[track_caller]
    fn is_close_to(self, expected: SignedDuration, allowed_deviation: SignedDuration) -> Self {
        self.track_assertion();

        let actual = *self.actual();
        let min = expected - allowed_deviation;
        let max = expected + allowed_deviation;
        if !(actual >= min && actual <= max) {
            self.fail(|w: &mut String| {
                writedoc! {w, r"
                    Expected value to be close to: {expected:?},
                     with allowed deviation being: {allowed_deviation:?},
                      but value was outside range: [{min:?}, {max:?}]

                      Actual: {actual:?}
                ", actual = self.actual()}
            });
        }

        self
    }
}

#[cfg(test)]
mod tests {
    mod is_zero {
        use crate::prelude::*;
        use indoc::formatdoc;
        use jiff::SignedDuration;

        #[test]
        fn succeeds_when_zero() {
            assert_that!(SignedDuration::ZERO).is_zero();
        }

        #[test]
        fn panics_when_not_zero() {
            let duration: SignedDuration = "2h 30m".parse().unwrap();

            assert_that_panic_by(|| {
                assert_that!(duration).with_location(false).is_zero();
            })
            .has_type::<String>()
            .is_equal_to(formatdoc! {r#"
                    -------- assertr --------
                    Expected: 0s

                      Actual: 9000s

                    Details: [
                        Actual was not zero.,
                    ]
                    -------- assertr --------
                "#});
        }
    }

    mod is_negative {
        use crate::prelude::*;
        use indoc::formatdoc;
        use jiff::SignedDuration;

        #[test]
        fn succeeds_when_negative() {
            assert_that!(SignedDuration::from_secs(-5)).is_negative();
        }

        #[test]
        fn panics_when_zero() {
            assert_that_panic_by(|| {
                assert_that!(SignedDuration::ZERO)
                    .with_location(false)
                    .is_negative();
            })
            .has_type::<String>()
            .is_equal_to(formatdoc! {r#"
                    -------- assertr --------
                    Expected: 0s to be negative,

                      Actual: 0s,
                    -------- assertr --------
                "#});
        }

        #[test]
        fn panics_when_positive() {
            assert_that_panic_by(|| {
                assert_that!(SignedDuration::from_secs(5))
                    .with_location(false)
                    .is_negative();
            })
            .has_type::<String>()
            .is_equal_to(formatdoc! {r#"
                    -------- assertr --------
                    Expected: 5s to be negative,

                      Actual: 5s,
                    -------- assertr --------
                "#});
        }
    }

    mod is_positive {
        use crate::prelude::*;
        use indoc::formatdoc;
        use jiff::SignedDuration;

        #[test]
        fn succeeds_when_positive() {
            assert_that!(SignedDuration::from_secs(5)).is_positive();
        }

        #[test]
        fn panics_when_zero() {
            assert_that_panic_by(|| {
                assert_that!(SignedDuration::ZERO)
                    .with_location(false)
                    .is_positive();
            })
            .has_type::<String>()
            .is_equal_to(formatdoc! {r#"
                    -------- assertr --------
                    Expected: 0s to be positive,

                      Actual: 0s,
                    -------- assertr --------
                "#});
        }

        #[test]
        fn panics_when_negative() {
            assert_that_panic_by(|| {
                assert_that!(SignedDuration::from_secs(-5))
                    .with_location(false)
                    .is_positive();
            })
            .has_type::<String>()
            .is_equal_to(formatdoc! {r#"
                    -------- assertr --------
                    Expected: -5s to be positive,

                      Actual: -5s,
                    -------- assertr --------
                "#});
        }
    }

    mod is_close_to {
        use crate::prelude::*;
        use indoc::formatdoc;
        use jiff::SignedDuration;

        #[test]
        fn panics_when_below_allowed_range() {
            assert_that_panic_by(|| {
                assert_that!(SignedDuration::from_secs_f32(0.3319))
                    .with_location(false)
                    .is_close_to(
                        SignedDuration::from_secs_f32(0.333),
                        SignedDuration::from_secs_f32(0.001),
                    );
            })
            .has_type::<String>()
            .is_equal_to(formatdoc! {r#"
                    -------- assertr --------
                    Expected value to be close to: 333ms,
                     with allowed deviation being: 1ms,
                      but value was outside range: [332ms, 334ms]

                      Actual: 331ms 900µs
                    -------- assertr --------
                "#});
        }

        #[test]
        fn succeeds_when_actual_is_in_allowed_range() {
            assert_that!(SignedDuration::from_secs_f32(0.332)).is_close_to(
                SignedDuration::from_secs_f32(0.333),
                SignedDuration::from_secs_f32(0.001),
            );
            assert_that!(SignedDuration::from_secs_f32(0.333)).is_close_to(
                SignedDuration::from_secs_f32(0.333),
                SignedDuration::from_secs_f32(0.001),
            );
            assert_that!(SignedDuration::from_secs_f32(0.334)).is_close_to(
                SignedDuration::from_secs_f32(0.333),
                SignedDuration::from_secs_f32(0.001),
            );
        }

        #[test]
        fn panics_when_above_allowed_range() {
            assert_that_panic_by(|| {
                assert_that!(SignedDuration::from_secs_f32(0.3341))
                    .with_location(false)
                    .is_close_to(
                        SignedDuration::from_secs_f32(0.333),
                        SignedDuration::from_secs_f32(0.001),
                    );
            })
            .has_type::<String>()
            .is_equal_to(formatdoc! {r#"
                    -------- assertr --------
                    Expected value to be close to: 333ms,
                     with allowed deviation being: 1ms,
                      but value was outside range: [332ms, 334ms]

                      Actual: 334ms 100µs
                    -------- assertr --------
                "#});
        }
    }
}