Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
212 changes: 158 additions & 54 deletions src/assertions.rs

Large diffs are not rendered by default.

9 changes: 4 additions & 5 deletions src/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ use crate::std::error::Error;
use crate::std::format;
use crate::std::string::{String, ToString};

impl<'a, S, R> AssertErrorHasSource<'a, R> for Spec<'a, S, R>
impl<'a, S, R> AssertErrorHasSource for Spec<'a, S, R>
where
S: Error,
R: FailingStrategy,
{
type SourceMessage = Spec<'a, Option<String>, R>;

fn has_no_source(self) -> Self {
self.expecting(not(error_has_source()))
}
Expand All @@ -21,10 +23,7 @@ where
self.expecting(error_has_source())
}

fn has_source_message(
self,
expected_source_message: impl Into<String>,
) -> Spec<'a, Option<String>, R> {
fn has_source_message(self, expected_source_message: impl Into<String>) -> Self::SourceMessage {
let expected_source_message = expected_source_message.into();
self.expecting(error_has_source_message(expected_source_message))
.mapping(|err| err.source().map(ToString::to_string))
Expand Down
56 changes: 34 additions & 22 deletions src/iterator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,21 @@ use crate::std::mem;
use crate::std::{format, string::String, vec, vec::Vec};
use hashbrown::HashSet;

impl<'a, S, T, E, R> AssertIteratorContains<'a, Vec<T>, E, R> for Spec<'a, S, R>
impl<'a, S, T, E, R> AssertIteratorContains<E> for Spec<'a, S, R>
where
S: IntoIterator<Item = T>,
T: PartialEq<E> + Debug,
E: Debug,
R: FailingStrategy,
{
fn contains(self, expected: E) -> Spec<'a, Vec<T>, R> {
type Sequence = Spec<'a, Vec<T>, R>;

fn contains(self, expected: E) -> Self::Sequence {
self.mapping(Vec::from_iter)
.expecting(iterator_contains(expected))
}

fn does_not_contain(self, expected: E) -> Spec<'a, Vec<T>, R> {
fn does_not_contain(self, expected: E) -> Self::Sequence {
self.mapping(Vec::from_iter)
.expecting(not(iterator_contains(expected)))
}
Expand Down Expand Up @@ -97,15 +99,17 @@ where

impl<E> Invertible for IteratorContains<E> {}

impl<'a, S, T, E, R> AssertIteratorContainsInAnyOrder<'a, Vec<T>, E, R> for Spec<'a, S, R>
impl<'a, S, T, E, R> AssertIteratorContainsInAnyOrder<E> for Spec<'a, S, R>
where
S: IntoIterator<Item = T>,
T: PartialEq<<E as IntoIterator>::Item> + Debug,
E: IntoIterator,
<E as IntoIterator>::Item: Debug,
R: FailingStrategy,
{
fn contains_exactly_in_any_order(self, expected: E) -> Spec<'a, Vec<T>, R> {
type Sequence = Spec<'a, Vec<T>, R>;

fn contains_exactly_in_any_order(self, expected: E) -> Self::Sequence {
self.mapping(Vec::from_iter)
.expecting(iterator_contains_exactly_in_any_order(expected))
}
Expand Down Expand Up @@ -414,7 +418,7 @@ where
}
}

impl<'a, S, T, E, R> AssertIteratorContainsInOrder<'a, Vec<T>, E, R> for Spec<'a, S, R>
impl<'a, S, T, E, R> AssertIteratorContainsInOrder<E> for Spec<'a, S, R>
where
S: IntoIterator<Item = T>,
<S as IntoIterator>::IntoIter: DefinedOrderProperty,
Expand All @@ -424,27 +428,29 @@ where
T: PartialEq<<E as IntoIterator>::Item> + Debug,
R: FailingStrategy,
{
fn contains_exactly(self, expected: E) -> Spec<'a, Vec<T>, R> {
type Sequence = Spec<'a, Vec<T>, R>;

fn contains_exactly(self, expected: E) -> Self::Sequence {
self.mapping(Vec::from_iter)
.expecting(iterator_contains_exactly(expected))
}

fn contains_sequence(self, expected: E) -> Spec<'a, Vec<T>, R> {
fn contains_sequence(self, expected: E) -> Self::Sequence {
self.mapping(Vec::from_iter)
.expecting(iterator_contains_sequence(expected))
}

fn contains_all_in_order(self, expected: E) -> Spec<'a, Vec<T>, R> {
fn contains_all_in_order(self, expected: E) -> Self::Sequence {
self.mapping(Vec::from_iter)
.expecting(iterator_contains_all_in_order(expected))
}

fn starts_with(self, expected: E) -> Spec<'a, Vec<T>, R> {
fn starts_with(self, expected: E) -> Self::Sequence {
self.mapping(Vec::from_iter)
.expecting(iterator_starts_with(expected))
}

fn ends_with(self, expected: E) -> Spec<'a, Vec<T>, R> {
fn ends_with(self, expected: E) -> Self::Sequence {
self.mapping(Vec::from_iter)
.expecting(iterator_ends_with(expected))
}
Expand Down Expand Up @@ -777,13 +783,16 @@ where
}
}

impl<'a, S, T, R> AssertElements<'a, T, R> for Spec<'a, S, R>
impl<'a, S, T, R> AssertElements<T> for Spec<'a, S, R>
where
S: IntoIterator<Item = T>,
T: Debug,
R: FailingStrategy,
{
fn single_element(self) -> Spec<'a, T, R> {
type SingleElement = Spec<'a, T, R>;
type MultipleElements = Spec<'a, Vec<T>, R>;

fn single_element(self) -> Self::SingleElement {
let spec = self.mapping(Vec::from_iter).expecting(has_single_element());
if spec.has_failures() {
PanicOnFail.do_fail_with(&spec.failures());
Expand All @@ -796,30 +805,30 @@ where
})
}

fn filtered_on<C>(self, condition: C) -> Spec<'a, Vec<T>, R>
fn filtered_on<C>(self, condition: C) -> Self::MultipleElements
where
C: FnMut(&T) -> bool,
{
self.mapping(|subject| subject.into_iter().filter(condition).collect())
}

fn any_satisfies<P>(self, predicate: P) -> Spec<'a, Vec<T>, R>
fn any_satisfies<P>(self, predicate: P) -> Self::MultipleElements
where
P: FnMut(&T) -> bool,
{
self.mapping(Vec::from_iter)
.expecting(any_satisfies(predicate))
}

fn all_satisfy<P>(self, predicate: P) -> Spec<'a, Vec<T>, R>
fn all_satisfy<P>(self, predicate: P) -> Self::MultipleElements
where
P: FnMut(&T) -> bool,
{
self.mapping(Vec::from_iter)
.expecting(all_satisfy(predicate))
}

fn none_satisfies<P>(self, predicate: P) -> Spec<'a, Vec<T>, R>
fn none_satisfies<P>(self, predicate: P) -> Self::MultipleElements
where
P: FnMut(&T) -> bool,
{
Expand Down Expand Up @@ -946,14 +955,17 @@ where
}
}

impl<'a, S, T, R> AssertOrderedElements<'a, T, R> for Spec<'a, S, R>
impl<'a, S, T, R> AssertOrderedElements for Spec<'a, S, R>
where
S: IntoIterator<Item = T>,
<S as IntoIterator>::IntoIter: DefinedOrderProperty,
T: Debug,
R: FailingStrategy,
{
fn first_element(self) -> Spec<'a, T, R> {
type SingleElement = Spec<'a, T, R>;
type MultipleElements = Spec<'a, Vec<T>, R>;

fn first_element(self) -> Self::SingleElement {
let spec = self
.mapping(Vec::from_iter)
.expecting(has_at_least_number_of_elements(1));
Expand All @@ -964,7 +976,7 @@ where
spec.extracting(|mut collection| collection.remove(0))
}

fn last_element(self) -> Spec<'a, T, R> {
fn last_element(self) -> Self::SingleElement {
let spec = self
.mapping(Vec::from_iter)
.expecting(has_at_least_number_of_elements(1));
Expand All @@ -979,7 +991,7 @@ where
})
}

fn nth_element(self, n: usize) -> Spec<'a, T, R> {
fn nth_element(self, n: usize) -> Self::SingleElement {
let min_len = n + 1;
let spec = self
.mapping(Vec::from_iter)
Expand All @@ -991,7 +1003,7 @@ where
spec.extracting(|mut collection| collection.remove(n))
}

fn elements_at(self, indices: impl IntoIterator<Item = usize>) -> Spec<'a, Vec<T>, R> {
fn elements_at(self, indices: impl IntoIterator<Item = usize>) -> Self::MultipleElements {
let indices = HashSet::<_>::from_iter(indices);
self.mapping(|subject| {
subject
Expand Down
12 changes: 8 additions & 4 deletions src/mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,28 @@ use crate::std::fmt::{Debug, Display};
use crate::std::format;
use crate::std::string::{String, ToString};

impl<'a, S, R> AssertDebugString<'a, R> for Spec<'a, S, R>
impl<'a, S, R> AssertDebugString for Spec<'a, S, R>
where
S: Debug,
R: FailingStrategy,
{
fn debug_string(self) -> Spec<'a, String, R> {
type DebugString = Spec<'a, String, R>;

fn debug_string(self) -> Self::DebugString {
let expression_debug_string = format!("{}'s debug string", self.expression());
self.mapping(|subject| format!("{subject:?}"))
.named(expression_debug_string)
}
}

impl<'a, S, R> AssertDisplayString<'a, R> for Spec<'a, S, R>
impl<'a, S, R> AssertDisplayString for Spec<'a, S, R>
where
S: Display,
R: FailingStrategy,
{
fn display_string(self) -> Spec<'a, String, R> {
type DisplayString = Spec<'a, String, R>;

fn display_string(self) -> Self::DisplayString {
let expression_display_string = format!("{}'s display string", self.expression());
self.mapping(|subject| subject.to_string())
.named(expression_display_string)
Expand Down
12 changes: 8 additions & 4 deletions src/option/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@ where
}
}

impl<'a, T, R> AssertOptionValue<'a, T, R> for Spec<'a, Option<T>, R>
impl<'a, T, R> AssertOptionValue for Spec<'a, Option<T>, R>
where
R: FailingStrategy,
{
fn some(self) -> Spec<'a, T, R> {
type Some = Spec<'a, T, R>;

fn some(self) -> Self::Some {
self.mapping(|subject| match subject {
None => {
panic!("expected the subject to be `Some(_)`, but was `None`")
Expand All @@ -53,11 +55,13 @@ where
}
}

impl<'a, T, R> AssertBorrowedOptionValue<'a, T, R> for Spec<'a, &'a Option<T>, R>
impl<'a, T, R> AssertBorrowedOptionValue for Spec<'a, &'a Option<T>, R>
where
R: FailingStrategy,
{
fn some(self) -> Spec<'a, &'a T, R> {
type Some = Spec<'a, &'a T, R>;

fn some(self) -> Self::Some {
self.mapping(|subject| match subject {
None => {
panic!("expected the subject to be `Some(_)`, but was `None`")
Expand Down
10 changes: 6 additions & 4 deletions src/panic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,22 @@ use crate::std::panic;
const ONLY_ONE_EXPECTATION: &str = "only one expectation allowed when asserting closures!";
const UNKNOWN_PANIC_MESSAGE: &str = "<unknown panic message>";

impl<'a, S, R> AssertCodePanics<'a, R> for Spec<'a, Code<S>, R>
impl<'a, S, R> AssertCodePanics for Spec<'a, Code<S>, R>
where
S: FnOnce(),
R: FailingStrategy,
{
fn does_not_panic(self) -> Spec<'a, (), R> {
type Mapped = Spec<'a, (), R>;

fn does_not_panic(self) -> Self::Mapped {
self.expecting(does_not_panic()).mapping(|_| ())
}

fn panics(self) -> Spec<'a, (), R> {
fn panics(self) -> Self::Mapped {
self.expecting(does_panic()).mapping(|_| ())
}

fn panics_with_message(self, message: impl Into<String>) -> Spec<'a, (), R> {
fn panics_with_message(self, message: impl Into<String>) -> Self::Mapped {
self.expecting(does_panic().with_message(message))
.mapping(|_| ())
}
Expand Down
Loading
Loading