Skip to content

Commit

Permalink
feat: add option asserting
Browse files Browse the repository at this point in the history
  • Loading branch information
open-schnick committed Nov 27, 2023
1 parent 2f6a711 commit 31afc4b
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 1 deletion.
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<u8> = 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)
26 changes: 26 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<u8> = Some(1);
//! let asserter: BasicAsserter<u8> = assert_that(option).is_some().and_value();
//! // further assertions
//! asserter.equals(1);
//! ```
//!
#![cfg_attr(feature = "__private_readme_test", doc = include_str!("../README.md"))]
//!
Expand Down Expand Up @@ -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`
Expand Down
4 changes: 4 additions & 0 deletions src/option.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
mod is_none;
mod is_some;

pub use is_some::SomeAsserter;
24 changes: 24 additions & 0 deletions src/option/is_none.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::{implementation, BasicAsserter};
use std::fmt::Debug;

impl<SomeValue> BasicAsserter<Option<SomeValue>>
where
SomeValue: Debug,
{
/// Asserts that the [Option] is [None].
///
/// # Examples
/// ```
/// # use smoothy::assert_that;
/// #
/// let option: Option<String> = 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);
}
}
54 changes: 54 additions & 0 deletions src/option/is_some.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use crate::{implementation, BasicAsserter};
use std::fmt::Debug;

impl<SomeValue> BasicAsserter<Option<SomeValue>>
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<String> = Some(String::new());
///
/// assert_that(option).is_some();
/// ```
///
/// # Panics
/// When the [Option] is [None]
pub fn is_some(self) -> SomeAsserter<SomeValue> {
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<SomeValue> {
value: SomeValue,
}

impl<SomeValue> SomeAsserter<SomeValue> {
/// Prepares the [Some] value for further assertions.
///
/// # Examples
/// ```
/// # use smoothy::{assert_that, BasicAsserter};
/// #
/// let option: Option<String> = 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<SomeValue> {
BasicAsserter { value: self.value }
}
}
20 changes: 20 additions & 0 deletions tests/is_none.rs
Original file line number Diff line number Diff line change
@@ -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();
}
}
32 changes: 32 additions & 0 deletions tests/is_some.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use smoothy::*;

mod assert_option {
use super::*;

#[test]
fn succeeds() {
let option: Option<String> = 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<String> = Some(String::new());

let asserter: BasicAsserter<String> = assert_that(option).is_some().and_value();
asserter.equals("");
}
}

0 comments on commit 31afc4b

Please sign in to comment.