use crate::{CheckResult, ExpectProjection, Expectation, ExpectationBuilder};
use std::fmt::Debug;
pub trait IterableCountExpectations<'e, B>
where
B: ExpectationBuilder<'e>,
{
fn count(self) -> impl ExpectationBuilder<'e, Value = usize>
where
Self: Sized;
fn to_not_be_empty(self) -> Self;
fn to_be_empty(self) -> Self;
}
impl<'e, I, C, B> IterableCountExpectations<'e, B> for B
where
I: Debug + 'e,
for<'a> &'a I: IntoIterator<Item = &'a C>,
C: Debug,
B: ExpectationBuilder<'e, Value = I>,
{
fn count(self) -> impl ExpectationBuilder<'e, Value = usize> {
self.projected_by(|it: &I| Iterator::count(it.into_iter()))
}
fn to_not_be_empty(self) -> Self {
self.to_pass(NotEmptyExpectation {})
}
fn to_be_empty(self) -> Self {
self.to_pass(EmptyExpectation {})
}
}
struct EmptyExpectation;
impl<I, C> Expectation<I> for EmptyExpectation
where
I: Debug,
for<'a> &'a I: IntoIterator<Item = &'a C>,
C: Debug,
{
fn check(&self, value: &I) -> CheckResult {
if value.into_iter().next().is_none() {
CheckResult::Pass
} else {
CheckResult::Fail(
"Expected iterable to be empty, but it had at least one item".to_string(),
)
}
}
}
struct NotEmptyExpectation;
impl<I, C> Expectation<I> for NotEmptyExpectation
where
I: Debug,
for<'a> &'a I: IntoIterator<Item = &'a C>,
C: Debug,
{
fn check(&self, value: &I) -> CheckResult {
if value.into_iter().next().is_some() {
CheckResult::Pass
} else {
CheckResult::Fail("Expected iterable to not be empty, but it was".to_string())
}
}
}
#[cfg(test)]
mod tests {
use super::IterableCountExpectations;
use crate::expect;
use crate::expectations::EqualityExpectations;
use rstest::rstest;
#[test]
pub fn that_to_be_empty_accepts_empty_iterable() {
let value: Vec<u32> = vec![];
expect(value).to_be_empty();
}
#[test]
#[should_panic]
pub fn that_to_be_empty_does_not_accept_non_empty_iterable() {
let value = vec![1];
expect(value).to_be_empty();
}
#[test]
pub fn that_to_not_be_empty_accepts_non_empty_iterable() {
let value = vec![1];
expect(value).to_not_be_empty();
}
#[test]
#[should_panic]
pub fn that_to_not_be_empty_does_not_accept_empty_iterable() {
let value: Vec<u32> = vec![];
expect(value).to_not_be_empty();
}
#[rstest]
#[case(vec![])]
#[case(vec![1])]
#[case(vec![1, 2])]
#[case(vec![1, 2, 3])]
pub fn that_count_projects_correctly(#[case] items: Vec<u32>) {
let expected_count = items.len();
expect(items).count().to_equal(expected_count);
}
}