Skip to content

Commit

Permalink
refactor!: use a trait-based approach for defining result assertions
Browse files Browse the repository at this point in the history
BREAKING CHANGE: changing to the new approach means that users need to update their imports to also include the ResultAssertionTrait
  • Loading branch information
open-schnick committed Dec 14, 2024
1 parent d19e553 commit adf5e0f
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 127 deletions.
5 changes: 3 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,13 +257,14 @@ mod string;
pub use connector::AssertionConnector;
pub use equality::EqualityAssertion;
pub use option::{OptionAssertion, SomeAsserter};
pub use result::{ErrAsserter, OkAsserter};
pub use result::{ErrAsserter, OkAsserter, ResultAsserter};
pub use string::StringAssertion;

/// The prelude for smoothy. Contains the most important structs, traits and functions but not all
pub mod prelude {
pub use crate::{
assert_that, BasicAsserter, EqualityAssertion, OptionAssertion, StringAssertion,
assert_that, BasicAsserter, EqualityAssertion, OptionAssertion, ResultAsserter,
StringAssertion,
};
}

Expand Down
120 changes: 116 additions & 4 deletions src/result.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,117 @@
mod is_err;
mod is_ok;
use crate::{implementation, BasicAsserter};

pub use is_err::ErrAsserter;
pub use is_ok::OkAsserter;
/// Specifies various assertions on [`Result`]. Implemented on [`BasicAsserter`]
pub trait ResultAsserter<OkValue, ErrValue> {
/// Asserts that the [Result] is an [Ok].
///
/// Allows the usage of chained assertions on an ok-value (see [`OkAsserter`]).
///
/// # Examples
/// ```
/// # use smoothy::prelude::*;
/// #
/// let result: Result<String, ()> = Ok(String::new());
///
/// assert_that(result).is_ok();
/// ```
///
/// # Panics
/// When the [Result] is an [Err]
#[track_caller]
#[allow(clippy::wrong_self_convention)]
fn is_ok(self) -> OkAsserter<OkValue>;

/// Asserts that the [Result] is an [Err].
///
/// Allows the usage of chained assertions on an error-type (see [`ErrAsserter`]).
///
/// # Examples
/// ```
/// # use smoothy::prelude::*;
/// #
/// let result: Result<(), String> = Err(String::new());
///
/// assert_that(result).is_err();
/// ```
///
/// # Panics
/// When the [Result] is an [Ok]
#[track_caller]
#[allow(clippy::wrong_self_convention)]
fn is_err(self) -> ErrAsserter<ErrValue>;
}

impl<OkValue, ErrValue> ResultAsserter<OkValue, ErrValue>
for BasicAsserter<Result<OkValue, ErrValue>>
where
OkValue: std::fmt::Debug,
ErrValue: std::fmt::Debug,
{
fn is_ok(self) -> OkAsserter<OkValue> {
implementation::assert(self.value.is_ok(), "Result is Ok", &self.value);

#[allow(clippy::unwrap_used)]
let value = self.value.unwrap();

OkAsserter { value }
}

fn is_err(self) -> ErrAsserter<ErrValue> {
implementation::assert(self.value.is_err(), "Result is Err", &self.value);

#[allow(clippy::unwrap_used)]
let value = self.value.err().unwrap();

ErrAsserter { value }
}
}

/// Enables various assertions on [Err]-values
pub struct ErrAsserter<ErrValue> {
value: ErrValue,
}

impl<ErrValue> ErrAsserter<ErrValue> {
/// Prepares the [Err] value for further assertions.
///
/// # Examples
/// ```
/// # use smoothy::prelude::*;
/// #
/// let result: Result<(), String> = Err(String::from("Hello World!"));
///
/// let asserter: BasicAsserter<String> = assert_that(result).is_err().and_error();
/// // further assertions
/// asserter.equals("Hello World!");
/// ```
#[track_caller]
#[must_use = "Transforming the asserted value does not assert anything"]
pub fn and_error(self) -> BasicAsserter<ErrValue> {
BasicAsserter { value: self.value }
}
}

/// Enables various assertions on [Ok]-values
pub struct OkAsserter<OkValue> {
value: OkValue,
}

impl<OkValue> OkAsserter<OkValue> {
/// Prepares the [Ok] value for further assertions.
///
/// # Examples
/// ```
/// # use smoothy::prelude::*;
/// #
/// let result: Result<String, ()> = Ok(String::from("Hello World!"));
///
/// let asserter: BasicAsserter<String> = assert_that(result).is_ok().and_value();
/// // further assertions
/// asserter.equals("Hello World!");
/// ```
#[track_caller]
#[must_use = "Transforming the asserted value does not assert anything"]
pub fn and_value(self) -> BasicAsserter<OkValue> {
BasicAsserter { value: self.value }
}
}
59 changes: 0 additions & 59 deletions src/result/is_err.rs

This file was deleted.

59 changes: 0 additions & 59 deletions src/result/is_ok.rs

This file was deleted.

4 changes: 2 additions & 2 deletions tests/is_err.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use smoothy::{assert_that, EqualityAssertion};
use crate::setup::{ComparableError, ConvertableError};
use smoothy::{assert_that, EqualityAssertion, ResultAsserter};
use std::fmt::Display;

mod assert_result {
Expand All @@ -20,7 +21,6 @@ mod assert_result {

mod assert_error {
use super::*;
use crate::setup::{ComparableError, ConvertableError};

#[test]
fn succeeds() {
Expand Down
2 changes: 1 addition & 1 deletion tests/is_ok.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use smoothy::{assert_that, EqualityAssertion};
use smoothy::{assert_that, EqualityAssertion, ResultAsserter};

mod assert_result {
use super::*;
Expand Down

0 comments on commit adf5e0f

Please sign in to comment.