diff --git a/README.md b/README.md index d354943..2cddfbd 100644 --- a/README.md +++ b/README.md @@ -135,16 +135,24 @@ The documentation of the assertion traits contains examples on how to use each a ### Equality -for all types that implement `PartialEq` with `E` being the type of the expected value. +for all types that implement `PartialEq` with `E` being the type of the expected value: | assertion | description | |-----------------|----------------------------------------------------------| | is_equal_to | verify that the subject is equal to an expected value | -| is_not_equal_to | verify that the subject is not equal to a specific value | +| is_not_equal_to | verify that the subject is not equal to a specific value | + +for all types that implement `PartialEq` and the subject is of the same type as the expected +value: + +| assertion | description | +|----------------|-----------------------------------------------------------------------------------------------| +| is_same_as | verify that the subject is of the same type and has the same value than the expected value | +| is_not_same_as | verify that the subject is of the same type and has a different value than the expected value | ### Order -for all types that implement `PartialOrd` with `E` being the type of the expected value. +for all types that implement `PartialOrd` with `E` being the type of the expected value: | assertion | description | |-----------------|----------------------------------------------------------------------------------------| @@ -159,7 +167,7 @@ for all types that implement `PartialOrd` with `E` being the type of the expe ### Range for all types `T` that implement `PartialOrd` and `E` implementing `PartialOrd` with `E` -being the type of the expected value. +being the type of the expected value: | assertion | description | |-----------------|-------------------------------------------------------| diff --git a/src/assertions.rs b/src/assertions.rs index b494250..ff61235 100644 --- a/src/assertions.rs +++ b/src/assertions.rs @@ -50,7 +50,7 @@ pub trait AssertEquality { #[track_caller] fn is_equal_to(self, expected: E) -> Self; - /// Verifies that subject is not equal to some other value. + /// Verifies that the subject is not equal to some other value. /// /// # Examples /// @@ -66,6 +66,56 @@ pub trait AssertEquality { fn is_not_equal_to(self, expected: E) -> Self; } +/// Assert whether two values are of the same type and have the same value. +/// +/// These assertions are implemented for all types that implement `PartialEq`. +/// +/// # Examples +/// +/// ``` +/// use asserting::prelude::*; +/// +/// let subject = String::from("adipiscing liber esse anim"); +/// assert_that!(subject).is_same_as("adipiscing liber esse anim".to_string()); +/// +/// let subject = "ea eu exercitation eu"; +/// assert_that!(subject).is_not_same_as("Ea eu exercitation"); +/// +/// assert_that!(42).is_same_as(42); +/// assert_that!(41).is_not_same_as(42); +/// ``` +pub trait AssertSameAs { + /// Verifies that the subject is of the same type and has the same value as + /// some other value. + /// + /// # Examples + /// + /// ``` + /// use asserting::prelude::*; + /// + /// let subject = String::from("adipiscing liber esse anim"); + /// assert_that!(subject).is_same_as("adipiscing liber esse anim".to_string()); + /// + /// assert_that!(42).is_same_as(42); + /// ``` + fn is_same_as(self, expected: E) -> Self; + + /// Verifies that the subject is of the same type but has a different value + /// as some other value. + /// + /// # Examples + /// + /// ``` + /// use asserting::prelude::*; + /// + /// let subject = "ea eu exercitation eu"; + /// assert_that!(subject).is_not_same_as("Ea eu exercitation"); + /// + /// assert_that!(41).is_not_same_as(42); + /// ``` + fn is_not_same_as(self, expected: E) -> Self; +} + /// Assert approximate equality for floating point numbers. /// /// # Examples diff --git a/src/equality.rs b/src/equality.rs index 04f398f..c89678b 100644 --- a/src/equality.rs +++ b/src/equality.rs @@ -1,10 +1,12 @@ //! Implementation of the equality assertions. -use crate::assertions::{AssertEquality, AssertHasDebugMessage, AssertHasDisplayMessage}; +use crate::assertions::{ + AssertEquality, AssertHasDebugMessage, AssertHasDisplayMessage, AssertSameAs, +}; use crate::colored::{mark_diff, mark_diff_str}; use crate::expectations::{ - has_debug_message, has_display_message, is_equal_to, not, HasDebugMessage, HasDisplayMessage, - IsEqualTo, + has_debug_message, has_display_message, is_equal_to, is_same_as, not, HasDebugMessage, + HasDisplayMessage, IsEqualTo, IsSameAs, }; use crate::spec::{DiffFormat, Expectation, Expression, FailingStrategy, Invertible, Spec}; use crate::std::fmt::{Debug, Display}; @@ -53,6 +55,46 @@ where impl Invertible for IsEqualTo {} +impl AssertSameAs for Spec<'_, S, R> +where + S: PartialEq + Debug, + R: FailingStrategy, +{ + fn is_same_as(self, expected: S) -> Self { + self.expecting(is_same_as(expected)) + } + + fn is_not_same_as(self, expected: S) -> Self { + self.expecting(not(is_same_as(expected))) + } +} + +impl Expectation for IsSameAs +where + S: PartialEq + Debug, +{ + fn test(&mut self, subject: &S) -> bool { + subject == &self.expected + } + + fn message( + &self, + expression: &Expression<'_>, + actual: &S, + inverted: bool, + format: &DiffFormat, + ) -> String { + let not = if inverted { "not " } else { "" }; + let expected = &self.expected; + let (marked_actual, marked_expected) = mark_diff(actual, expected, format); + format!( + "expected {expression} to be {not}the same as {expected:?}\n but was: {marked_actual}\n expected: {not}{marked_expected}", + ) + } +} + +impl Invertible for IsSameAs {} + impl AssertHasDebugMessage for Spec<'_, S, R> where S: Debug, diff --git a/src/expectations.rs b/src/expectations.rs index 01d7ae8..95b97a4 100644 --- a/src/expectations.rs +++ b/src/expectations.rs @@ -250,6 +250,15 @@ pub struct IsEqualTo { pub expected: E, } +/// Creates an [`IsSameAs`] expectation. +pub fn is_same_as(expected: E) -> IsSameAs { + IsSameAs { expected } +} + +pub struct IsSameAs { + pub expected: E, +} + /// Creates an [`IsCloseTo`] expectation. /// /// The margin is set to a default value. To define a custom margin, use the diff --git a/src/lib.rs b/src/lib.rs index 727a763..6094171 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -85,6 +85,12 @@ //! assert_that!('M').is_in_range('A'..='Z'); //! assert_that!('M').is_not_in_range('a'..='z'); //! +//! let subject = "at invidunt quis placerat".to_string(); +//! assert_that!(subject).is_equal_to("at invidunt quis placerat"); +//! +//! let subject = "justo clita in stet".to_string(); +//! assert_that!(subject).is_same_as("justo clita in stet".to_string()); +//! //! let subject = "anim proident eiusmod sint".to_string(); //! assert_that!(subject).contains("eiusmod"); //! diff --git a/src/string/tests.rs b/src/string/tests.rs index e69e602..4c57fc9 100644 --- a/src/string/tests.rs +++ b/src/string/tests.rs @@ -91,6 +91,84 @@ fn verify_string_is_equal_to_str_fails() { ); } +#[test] +fn string_is_same_as_string() { + let subject: String = "aliqua esse consectetur ullamcorper".to_string(); + + assert_that(subject).is_same_as("aliqua esse consectetur ullamcorper".to_string()); +} + +#[test] +fn string_ref_is_same_as_string_ref() { + let subject: &String = &"adipiscing liber esse anim".to_string(); + + assert_that(subject).is_same_as(&"adipiscing liber esse anim".to_string()); +} + +#[test] +fn str_is_same_as_str() { + let subject: &str = "diam accusam tation luptatum"; + + assert_that(subject).is_same_as("diam accusam tation luptatum"); +} + +#[test] +fn verify_string_is_same_as_string_fails() { + let failures = verify_that("diam accusam tation luptatum".to_string()) + .named("my_text") + .is_same_as("diam accusam Tation luptatum".to_string()) + .display_failures(); + + assert_eq!( + failures, + &[ + r#"expected my_text to be the same as "diam accusam Tation luptatum" + but was: "diam accusam tation luptatum" + expected: "diam accusam Tation luptatum" +"# + ] + ); +} + +#[test] +fn string_is_not_same_as_string() { + let subject: String = "aliqua esse consectetur ullamcorper".to_string(); + + assert_that(subject).is_not_same_as("Aliqua esse consectetur ullamcorper".to_string()); +} + +#[test] +fn string_ref_is_not_same_as_string_ref() { + let subject: &String = &"adipiscing liber esse anim".to_string(); + + assert_that(subject).is_not_same_as(&"adipiscing liber rese anim".to_string()); +} + +#[test] +fn str_is_not_same_as_str() { + let subject: &str = "Diam accusam tation luptatum"; + + assert_that(subject).is_not_same_as("diam accusam tation luptatum"); +} + +#[test] +fn verify_str_is_not_same_as_str_fails() { + let failures = verify_that("diam accusam tation luptatum") + .named("my_text") + .is_not_same_as("diam accusam tation luptatum") + .display_failures(); + + assert_eq!( + failures, + &[ + r#"expected my_text to be not the same as "diam accusam tation luptatum" + but was: "diam accusam tation luptatum" + expected: not "diam accusam tation luptatum" +"# + ] + ); +} + #[test] fn string_is_empty() { let subject: String = String::new(); @@ -1417,6 +1495,42 @@ mod colored { ); } + #[test] + fn highlight_diffs_is_same_as_for_strings() { + let failures = verify_that("no fugiat pariatur placerat") + .with_diff_format(DIFF_FORMAT_RED_BLUE) + .is_same_as("no Fugiat Pariatur placerat") + .display_failures(); + + assert_eq!( + failures, + &[ + "expected subject to be the same as \"no Fugiat Pariatur placerat\"\n \ + but was: \"no \u{1b}[31mf\u{1b}[0mugiat \u{1b}[31mp\u{1b}[0mariatur placerat\"\n \ + expected: \"no \u{1b}[34mF\u{1b}[0mugiat \u{1b}[34mP\u{1b}[0mariatur placerat\"\n\ + " + ] + ); + } + + #[test] + fn highlight_diffs_is_not_same_as_for_strings() { + let failures = verify_that("justo clita in stet") + .with_diff_format(DIFF_FORMAT_RED_BLUE) + .is_not_same_as("justo clita in stet") + .display_failures(); + + assert_eq!( + failures, + &[ + "expected subject to be not the same as \"justo clita in stet\"\n \ + but was: \"justo clita in stet\"\n \ + expected: not \"justo clita in stet\"\n\ + " + ] + ); + } + #[test] fn highlight_diffs_string_is_empty() { let subject = "voluptua quod quis dignissim";