From 31afc4b9e5d24341e0bdb39ecfaa4613eb90edf5 Mon Sep 17 00:00:00 2001 From: open-schnick Date: Tue, 21 Nov 2023 17:28:50 +0100 Subject: [PATCH] feat: add option asserting --- README.md | 18 ++++++++++++++- src/lib.rs | 26 +++++++++++++++++++++ src/option.rs | 4 ++++ src/option/is_none.rs | 24 +++++++++++++++++++ src/option/is_some.rs | 54 +++++++++++++++++++++++++++++++++++++++++++ tests/is_none.rs | 20 ++++++++++++++++ tests/is_some.rs | 32 +++++++++++++++++++++++++ 7 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 src/option.rs create mode 100644 src/option/is_none.rs create mode 100644 src/option/is_some.rs create mode 100644 tests/is_none.rs create mode 100644 tests/is_some.rs diff --git a/README.md b/README.md index 2161b09..7a4fc3e 100644 --- a/README.md +++ b/README.md @@ -59,8 +59,24 @@ assert_that(result) .equals("ups!"); ``` +```rust +use smoothy::assert_that; + +let option: Option<()> = None; +assert_that(option).is_none(); +``` + +```rust +use smoothy::assert_that; + +let option: Option = Some(1); +assert_that(option) + .is_some() + .and_value() + .equals(1) +``` + ## TODO: -- option support - vec support (length, contains) - string support (length, contains, starts_with, ends_with) diff --git a/src/lib.rs b/src/lib.rs index e6f6395..954a094 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -117,6 +117,30 @@ //! .equals("Oh no!"); //! ``` //! +//! ## Option +//! +//! Options can be asserted by calling [`is_none`](struct.AssertionBuilder.html#method.is_none) or [`is_some`](struct.AssertionBuilder.html#method.is_some). +//! Instances of [`Some`] can be further asserted with [`and_value`](struct.SomeAsserter.html#method.and_value). +//! +//! ### None +//! +//! ``` +//! # use smoothy::assert_that; +//! let option: Option<()> = None; +//! +//! assert_that(option).is_none(); +//! ``` +//! +//! ### Some +//! +//! ``` +//! # use smoothy::{assert_that, BasicAsserter}; +//! let option: Option = Some(1); +//! let asserter: BasicAsserter = assert_that(option).is_some().and_value(); +//! // further assertions +//! asserter.equals(1); +//! ``` +//! #![cfg_attr(feature = "__private_readme_test", doc = include_str!("../README.md"))] //! @@ -177,10 +201,12 @@ clippy::needless_pass_by_value )] +pub use option::*; pub use result::*; mod equality; mod implementation; +mod option; mod result; /// Main struct with various assertions on `AssertedType` diff --git a/src/option.rs b/src/option.rs new file mode 100644 index 0000000..41452a2 --- /dev/null +++ b/src/option.rs @@ -0,0 +1,4 @@ +mod is_none; +mod is_some; + +pub use is_some::SomeAsserter; diff --git a/src/option/is_none.rs b/src/option/is_none.rs new file mode 100644 index 0000000..7a4c920 --- /dev/null +++ b/src/option/is_none.rs @@ -0,0 +1,24 @@ +use crate::{implementation, BasicAsserter}; +use std::fmt::Debug; + +impl BasicAsserter> +where + SomeValue: Debug, +{ + /// Asserts that the [Option] is [None]. + /// + /// # Examples + /// ``` + /// # use smoothy::assert_that; + /// # + /// let option: Option = None; + /// + /// assert_that(option).is_none(); + /// ``` + /// + /// # Panics + /// When the [Option] is [Some] + pub fn is_none(self) { + implementation::assert(self.value.is_none(), "Option is None", &self.value); + } +} diff --git a/src/option/is_some.rs b/src/option/is_some.rs new file mode 100644 index 0000000..3f9d21f --- /dev/null +++ b/src/option/is_some.rs @@ -0,0 +1,54 @@ +use crate::{implementation, BasicAsserter}; +use std::fmt::Debug; + +impl BasicAsserter> +where + SomeValue: Debug, +{ + /// Asserts that the [Option] is [Some]. + /// + /// Allows the usage of chained assertions on an option-type (see [`SomeAsserter`]). + /// + /// # Examples + /// ``` + /// # use smoothy::assert_that; + /// # + /// let option: Option = Some(String::new()); + /// + /// assert_that(option).is_some(); + /// ``` + /// + /// # Panics + /// When the [Option] is [None] + pub fn is_some(self) -> SomeAsserter { + implementation::assert(self.value.is_some(), "Option is Some", &self.value); + + #[allow(clippy::unwrap_used)] + let value = self.value.unwrap(); + + SomeAsserter { value } + } +} + +/// Enables various assertions on [Some]-values +pub struct SomeAsserter { + value: SomeValue, +} + +impl SomeAsserter { + /// Prepares the [Some] value for further assertions. + /// + /// # Examples + /// ``` + /// # use smoothy::{assert_that, BasicAsserter}; + /// # + /// let option: Option = Some(String::from("Hello World!")); + /// + /// let asserter = assert_that(option).is_some().and_value(); + /// // further assertions + /// asserter.equals("Hello World!"); + /// ``` + pub fn and_value(self) -> BasicAsserter { + BasicAsserter { value: self.value } + } +} diff --git a/tests/is_none.rs b/tests/is_none.rs new file mode 100644 index 0000000..2c0cd28 --- /dev/null +++ b/tests/is_none.rs @@ -0,0 +1,20 @@ +use smoothy::*; + +mod assert_option { + use super::*; + + #[test] + fn succeeds() { + let option: Option<()> = None; + + assert_that(option).is_none(); + } + + #[test] + #[should_panic = "assertion failed: `(Option is None)`"] + fn fails() { + let option: Option<()> = Some(()); + + assert_that(option).is_none(); + } +} diff --git a/tests/is_some.rs b/tests/is_some.rs new file mode 100644 index 0000000..d7b7c75 --- /dev/null +++ b/tests/is_some.rs @@ -0,0 +1,32 @@ +use smoothy::*; + +mod assert_option { + use super::*; + + #[test] + fn succeeds() { + let option: Option = Some(String::new()); + + assert_that(option).is_some(); + } + + #[test] + #[should_panic = "assertion failed: `(Option is Some)`"] + fn fails() { + let option: Option<()> = None; + + assert_that(option).is_some(); + } +} + +mod assert_some { + use super::*; + + #[test] + fn transforms_to_basic_asserter() { + let option: Option = Some(String::new()); + + let asserter: BasicAsserter = assert_that(option).is_some().and_value(); + asserter.equals(""); + } +}