use super::{AssertionFailure, Spec};
use std::borrow::Borrow;
use std::cmp::PartialEq;
use std::fmt::Debug;
pub trait OptionAssertions<'r, T>
where
T: Debug,
{
fn is_some(&mut self) -> Spec<'r, T>;
fn is_none(&mut self);
}
pub trait ContainingOptionAssertions<T>
where
T: Debug + PartialEq,
{
fn contains_value<E: Borrow<T>>(&mut self, expected_value: E);
}
impl<'s, T> ContainingOptionAssertions<T> for Spec<'s, Option<T>>
where
T: Debug + PartialEq,
{
fn contains_value<E: Borrow<T>>(&mut self, expected_value: E) {
let borrowed_expected_value = expected_value.borrow();
match *self.subject {
Some(ref val) => {
if !val.eq(borrowed_expected_value) {
AssertionFailure::from_spec(self)
.with_expected(format!("option to contain <{:?}>", borrowed_expected_value))
.with_actual(format!("<{:?}>", val))
.fail();
}
}
None => {
AssertionFailure::from_spec(self)
.with_expected(format!("option<{:?}>", borrowed_expected_value))
.with_actual("option[none]".to_string())
.fail();
}
};
}
}
impl<'s, T> OptionAssertions<'s, T> for Spec<'s, Option<T>>
where
T: Debug,
{
fn is_some(&mut self) -> Spec<'s, T> {
match *self.subject {
Some(ref val) => Spec {
subject: val,
subject_name: self.subject_name,
location: self.location.clone(),
description: self.description,
},
None => {
AssertionFailure::from_spec(self)
.with_expected("option[some]".to_string())
.with_actual("option[none]".to_string())
.fail();
unreachable!();
}
}
}
fn is_none(&mut self) {
match *self.subject {
None => (),
Some(ref val) => {
AssertionFailure::from_spec(self)
.with_expected("option[none]".to_string())
.with_actual(format!("option<{:?}>", val))
.fail();
}
}
}
}
#[cfg(test)]
mod tests {
use super::super::prelude::*;
#[test]
fn should_not_panic_if_option_is_expected_to_contain_value_and_does() {
let option = Some("Hello");
assert_that(&option).is_some();
}
#[test]
#[should_panic(expected = "\n\texpected: option[some]\n\t but was: option[none]")]
fn should_panic_if_option_is_expected_to_contain_value_and_does_not() {
let option: Option<&str> = None;
assert_that(&option).is_some();
}
#[test]
fn should_be_able_to_unwrap_option_if_some() {
let option = Some("Hello");
assert_that(&option).is_some().is_equal_to(&"Hello");
}
#[test]
fn should_be_able_to_unwrap_referenced_vec() {
assert_that(&Some(&vec![1, 2, 3])).is_some().has_length(3);
}
#[test]
fn contains_value_should_allow_multiple_borrow_types() {
let option = Some("Hello");
assert_that(&option).contains_value("Hello");
assert_that(&option).contains_value(&mut "Hello");
assert_that(&option).contains_value(&"Hello");
}
#[test]
fn should_not_panic_if_option_contains_expected_value() {
let option = Some("Hello");
assert_that(&option).contains_value(&"Hello");
}
#[test]
#[should_panic(expected = "\n\texpected: option to contain <\"Hi\">\n\t but was: <\"Hello\">")]
fn should_panic_if_option_does_not_contain_expected_value() {
let option = Some("Hello");
assert_that(&option).contains_value(&"Hi");
}
#[test]
#[should_panic(expected = "\n\texpected: option<\"Hello\">\n\t but was: option[none]")]
fn should_panic_if_option_is_none_but_expected_value() {
let option: Option<&str> = None;
assert_that(&option).contains_value(&"Hello");
}
#[test]
fn should_not_panic_if_option_is_empty() {
let option: Option<&str> = None;
assert_that(&option).is_none();
}
#[test]
#[should_panic(expected = "\n\texpected: option[none]\n\t but was: option<\"Hello\"")]
fn should_panic_if_option_is_not_empty_but_was_expected_as_empty() {
let option = Some("Hello");
assert_that(&option).is_none();
}
}