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
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#![feature(core_intrinsics)]
#![doc(html_root_url="https://samfoo.github.io/oxidize/")]
#![cfg_attr(test, deny(warnings))]

//! # Oxidize
//!
//! Oxidize lets you set expected outcomes on objects in unit tests (or
//! anywhere). This allows for more fluid expression than with assertions alone
//! and yields more readable error messages.
//!
//! For example:
//!
//!     use oxidize::dsl::*;
//!
//!     expect("optimus prime").to(contain("prime"));
//!
//! Any expectation can also be negated:
//!
//!     use oxidize::dsl::*;
//!
//!     expect("megatron").to_not(contain("prime"));
//!
//! ## Built-in Matchers
//!
//! Oxidize has of built-in [matchers](matchers/index.html) that you can
//! use for all kinds of data.
//!
//! ### Equality
//!
//!     use oxidize::dsl::*;
//!
//!     expect(1).to(equal(1));
//!     expect(6).is(greater_than(0));
//!     expect(-120).is(less_than(5));
//!
//! ### Truthiness
//!
//!     use oxidize::dsl::*;
//!
//!     struct Transformer { is_prime: bool };
//!     let optimus = Transformer { is_prime: true };
//!
//!     expect(optimus.is_prime).to(be_true());
//!
//!     struct Paradox;
//!     impl Paradox {
//!         fn can_fly(&self) -> bool {
//!             false
//!         }
//!     }
//!     let pigs = Paradox;
//!
//!     expect(pigs.can_fly()).to(be_false());
//!
//! ### Substrings / Containers
//!
//!     use oxidize::dsl::*;
//!
//!     expect(vec![1, 2, 3]).to(contain(2));
//!     expect("Energon Cube").to(contain("Cube"));
//!
//! ### Length
//!
//!     use oxidize::dsl::*;
//!
//!     expect(vec![1, 2, 3, 4]).is_not(empty());
//!
//! ### Options / Existence
//!
//!     use oxidize::dsl::*;
//!
//!     let mut big: Vec<u64> = vec![1337u64];
//!
//!     expect(big.pop()).is(some());
//!     expect(big.pop()).is(none());
//!
//! ### Regex
//!
//!     use oxidize::dsl::*;
//!
//!     expect("sam").to(match_regex("..."));
//!
//! ## Inspiration
//!
//! These projects were inspirational in oxidize's design (maybe they'll inspire
//! you, too!):
//!
//! * [rspec-expectations](https://github.com/rspec/rspec-expectations/)
//! * [hamcrest](http://hamcrest.org/)
//! * [assertj](https://joel-costigliola.github.io/assertj/)

extern crate regex;

use matchers::Matcher;

/// Contains all built in matchers.
pub mod matchers;

/// Contains functions wrapping creating matchers in a more pleasant syntax.
pub mod dsl;

use std::fmt::Debug;

/// Holds an expectation's left hand side (LHS). This LHS can then be matched by
/// any `Matcher`.
pub struct Expectation<Lhs: Debug>(Lhs);

impl<Lhs: Debug> Expectation<Lhs> {
    pub fn is<T>(&self, matcher: Box<T>) where T: Matcher<Lhs> {
        self.to(matcher)
    }

    pub fn is_not<T>(&self, matcher: Box<T>) where T: Matcher<Lhs> {
        self.to_not(matcher)
    }

    pub fn to<T>(&self, matcher: Box<T>) where T: Matcher<Lhs> {
        if !matcher.matches(&self.0) {
            panic!(matcher.fail_msg(&self.0))
        }
    }

    pub fn to_not<T>(&self, matcher: Box<T>) where T: Matcher<Lhs> {
        if matcher.matches(&self.0) {
            panic!(matcher.negated_fail_msg(&self.0))
        }
    }
}