mod fixture;
use asserting::prelude::*;
use asserting::spec::{FailingStrategy, Spec};
use std::borrow::Borrow;
#[derive(Debug, Clone, Copy, PartialEq)]
struct Coord {
x: i32,
y: i32,
}
struct Snake {
length: usize,
head: Coord,
body: Vec<Coord>,
}
trait AssertSnake {
#[track_caller]
fn has_body(self, expected_body: &[Coord]) -> Self;
}
impl<S, R> AssertSnake for Spec<'_, S, R>
where
S: Borrow<Snake>,
R: FailingStrategy,
{
fn has_body(mut self, expected_body: &[Coord]) -> Self {
let actual_body = self.subject().borrow();
let mut failures;
failures = verify_that(actual_body)
.with_configured_diff_format()
.extracting(|s| s.length)
.named("snake.length")
.is_equal_to(expected_body.len())
.display_failures();
failures.extend(
verify_that(actual_body)
.with_configured_diff_format()
.extracting(|s| &s.body)
.named("snake.body")
.contains_exactly(expected_body)
.display_failures(),
);
failures.extend(
verify_that(actual_body)
.with_configured_diff_format()
.extracting(|s| s.head)
.named("snake.head")
.is_equal_to(expected_body[0])
.display_failures(),
);
if !failures.is_empty() {
self.do_fail_with_message(format!(
"assertion of snake body failed: \n\n{}",
failures.join("\n")
));
}
self
}
}
fn test() {
let snake = Snake {
length: 2,
head: Coord { x: 3, y: 1 },
body: vec![
Coord { x: 2, y: 1 },
Coord { x: 1, y: 2 },
Coord { x: -1, y: 1 },
],
};
assert_that!(snake).has_body(&[
Coord { x: 2, y: 1 },
Coord { x: 1, y: 1 },
Coord { x: 1, y: 2 },
]);
}
fn main() {
test();
}