1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use std::fmt;

use crate::core::style::{ALL_OK_HEADER, AT_LESAT_ONE_OK_HEADER};
use crate::core::Matcher;
use crate::matchers::collections::EveryMatcher;

use super::{HeaderFormat, SomeFailuresFormat};

/// Succeeds when the matcher succeeds for every element of the actual value.
///
/// This accepts a closure which returns a matcher for every element in the collection.
///
/// # Examples
///
/// Expect every element to be `Some(_)`, unwrapping into a vec of strings.
///
/// ```
/// use xpct::{be_some, every, expect};
///
/// let items = vec![Some("foo"), Some("bar")];
///
/// let output: Vec<&str> = expect!(items)
///     .to(every(be_some))
///     .into_inner();
/// ```
///
/// Expect every element to be in the range `20..30`.
///
/// ```
/// use xpct::{be_in, every, expect};
///
/// expect!(vec![20, 25]).to(every(|| be_in(20..30)));
/// ```
pub fn every<'a, PosOut, NegOut, IntoIter>(
    matcher: impl Fn() -> Matcher<'a, IntoIter::Item, PosOut, NegOut> + 'a,
) -> Matcher<'a, IntoIter, Vec<PosOut>, Vec<NegOut>>
where
    IntoIter: fmt::Debug + IntoIterator + 'a,
    PosOut: 'a,
    NegOut: 'a,
{
    Matcher::transform(
        EveryMatcher::new(matcher),
        HeaderFormat::new(
            SomeFailuresFormat::new(),
            ALL_OK_HEADER,
            AT_LESAT_ONE_OK_HEADER,
        ),
    )
}

#[cfg(test)]
mod tests {
    use super::every;
    use crate::{be_some, expect};

    #[test]
    fn succeeds_when_every_element_succeeds() {
        expect!(vec![Some("foo"), Some("bar")]).to(every(be_some));
    }

    #[test]
    fn succeeds_when_not_every_element_succeeds() {
        expect!(vec![Some("foo"), None]).to_not(every(be_some));
    }

    #[test]
    #[should_panic]
    fn fails_when_every_element_succeeds() {
        expect!(vec![Some("foo"), Some("bar")]).to_not(every(be_some));
    }

    #[test]
    #[should_panic]
    fn fails_when_not_every_element_succeeds() {
        expect!(vec![Some("foo"), None]).to(every(be_some));
    }
}