use crate::core::style::{ALL_OK_HEADER, AT_LESAT_ONE_OK_HEADER};
use crate::core::{style, Format, FormattedOutput, Formatter, MatchFailure, Matcher};
use crate::matchers::combinators::{CombinatorContext, CombinatorMatcher, CombinatorMode};
use super::SomeFailuresFormat;
#[derive(Debug, Default)]
pub struct HeaderFormat<Fmt> {
inner: Fmt,
pos_header: String,
neg_header: String,
}
impl<Fmt> HeaderFormat<Fmt> {
pub fn new(inner: Fmt, pos_header: impl Into<String>, neg_header: impl Into<String>) -> Self {
Self {
inner,
pos_header: pos_header.into(),
neg_header: neg_header.into(),
}
}
}
impl<Fmt> Format for HeaderFormat<Fmt>
where
Fmt: Format,
{
type Value = MatchFailure<Fmt::Value>;
fn fmt(&self, f: &mut Formatter, value: Self::Value) -> crate::Result<()> {
f.set_style(style::important());
if value.is_pos() {
f.write_str(&self.pos_header);
} else {
f.write_str(&self.neg_header)
}
f.reset_style();
f.write_char('\n');
let fail = value.into_inner();
f.write_fmt(FormattedOutput::new(fail, &self.inner)?.indented(style::indent(1)));
Ok(())
}
}
pub fn any<'a, T>(block: impl Fn(&mut CombinatorContext<T>) + 'a) -> Matcher<'a, T, T>
where
T: 'a,
{
Matcher::transform(
CombinatorMatcher::new(CombinatorMode::Any, block),
HeaderFormat::new(
SomeFailuresFormat::new(),
AT_LESAT_ONE_OK_HEADER,
ALL_OK_HEADER,
),
)
}
#[cfg(test)]
mod tests {
use super::any;
use crate::{be_gt, be_lt, expect};
#[test]
fn succeeds_when_any_matchers_succeed() {
expect!(1).to(any(|ctx| ctx.copied().to(be_lt(0)).to(be_gt(0)).done()));
}
#[test]
fn succeeds_when_not_any_matchers_succeed() {
expect!(1).to_not(any(|ctx| ctx.copied().to(be_lt(0)).to(be_gt(2)).done()));
}
#[test]
#[should_panic]
fn fails_when_any_matchers_succeed() {
expect!(1).to_not(any(|ctx| ctx.copied().to(be_lt(0)).to(be_gt(0)).done()));
}
#[test]
#[should_panic]
fn fails_when_not_any_matchers_succeed() {
expect!(1).to(any(|ctx| ctx.copied().to(be_lt(0)).to(be_gt(2)).done()));
}
}