Skip to content

Commit

Permalink
Merge pull request #75 from lipanski/all_of_matcher
Browse files Browse the repository at this point in the history
Matcher::AllOf
  • Loading branch information
lipanski authored Jul 11, 2019
2 parents 1d82aa6 + 68d4862 commit 80ea470
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 3 deletions.
38 changes: 37 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,27 @@
//! .create();
//!```
//!
//! # The `AllOf` matcher
//!
//! The `Matcher::AllOf` construct takes a vector of matchers as arguments and will be enabled
//! if all of the provided matchers match the request.
//!
//! ## Example
//!
//! ```
//! use mockito::{mock, Matcher};
//!
//! // Will match requests to POST / whenever the request body contains both `hello` and `world`
//! let _m = mock("POST", "/")
//! .match_body(
//! Matcher::AllOf(vec![
//! Matcher::Regex("hello".to_string()),
//! Matcher::Regex("world".to_string()),
//! ])
//! )
//! .create();
//!```
//!
//! # Non-matching calls
//!
//! Any calls to the Mockito server that are not matched will return *501 Mock Not Found*.
Expand Down Expand Up @@ -504,8 +525,10 @@ pub enum Matcher {
Json(serde_json::Value),
/// Matches a specified JSON body from a `String`
JsonString(String),
/// At least one must match
/// At least one matcher must match
AnyOf(Vec<Matcher>),
/// All matchers must match
AllOf(Vec<Matcher>),
/// Matches any path or any header value.
Any,
/// Checks that a header is not present in the request.
Expand All @@ -529,6 +552,9 @@ impl Matcher {
Matcher::AnyOf(ref matchers) if header_values.is_empty() => {
matchers.iter().any(|m| m.matches_values(header_values))
},
Matcher::AllOf(ref matchers) if header_values.is_empty() => {
matchers.iter().all(|m| m.matches_values(header_values))
},
_ => !header_values.is_empty() && header_values.iter().all(|val| self.matches_value(val)),
}
}
Expand All @@ -551,6 +577,9 @@ impl Matcher {
Matcher::AnyOf(ref matchers) => {
matchers.iter().any(|m| m.matches_value(other))
},
Matcher::AllOf(ref matchers) => {
matchers.iter().all(|m| m.matches_value(other))
},
Matcher::Missing => false,
}
}
Expand Down Expand Up @@ -831,6 +860,7 @@ impl fmt::Display for Mock {
},
Matcher::Any => formatted.push_str("(any)\r\n"),
Matcher::AnyOf(..) => formatted.push_str("(any of)\r\n"),
Matcher::AllOf(..) => formatted.push_str("(all of)\r\n"),
Matcher::Missing => formatted.push_str("(missing)\r\n"),
}

Expand Down Expand Up @@ -874,6 +904,11 @@ impl fmt::Display for Mock {
formatted.push_str(": ");
formatted.push_str("(any of)");
},
Matcher::AllOf(..) => {
formatted.push_str(key);
formatted.push_str(": ");
formatted.push_str("(all of)");
},
}

formatted.push_str("\r\n");
Expand All @@ -890,6 +925,7 @@ impl fmt::Display for Mock {
},
Matcher::Missing => formatted.push_str("(missing)\r\n"),
Matcher::AnyOf(..) => formatted.push_str("(any of)\r\n"),
Matcher::AllOf(..) => formatted.push_str("(all of)\r\n"),
Matcher::Any => {}
}

Expand Down
98 changes: 96 additions & 2 deletions tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ fn test_regex_match_header() {
}

#[test]
fn test_or_match_header() {
fn test_any_of_match_header() {
let _m = mock("GET", "/")
.match_header("Via", Matcher::AnyOf(vec![
Matcher::Exact("one".into()),
Expand All @@ -484,7 +484,28 @@ fn test_or_match_header() {
}

#[test]
fn test_or_miss_match_header() {
fn test_any_of_match_body() {
let _m = mock("GET", "/")
.match_body(Matcher::AnyOf(vec![
Matcher::Regex("one".to_string()),
Matcher::Regex("two".to_string())]))
.create();

let (status_line, _, _) = request_with_body("GET /", "", "one");
assert!(status_line.starts_with("HTTP/1.1 200 "));

let (status_line, _, _) = request_with_body("GET /", "", "two");
assert!(status_line.starts_with("HTTP/1.1 200 "));

let (status_line, _, _) = request_with_body("GET /", "", "one two");
assert!(status_line.starts_with("HTTP/1.1 200 "));

let (status_line, _, _) = request_with_body("GET /", "", "three");
assert!(status_line.starts_with("HTTP/1.1 501 "));
}

#[test]
fn test_any_of_missing_match_header() {
let _m = mock("GET", "/")
.match_header("Via", Matcher::AnyOf(vec![
Matcher::Exact("one".into()),
Expand All @@ -511,6 +532,79 @@ fn test_or_miss_match_header() {
assert!(status_line.starts_with("HTTP/1.1 501 "));
}

#[test]
fn test_all_of_match_header() {
let _m = mock("GET", "/")
.match_header("Via", Matcher::AllOf(vec![
Matcher::Regex("one".into()),
Matcher::Regex("two".into())]))
.with_body("{}")
.create();

let (status_line, _, _) = request("GET /", "Via: one\r\n");
assert!(status_line.starts_with("HTTP/1.1 501 "));

let (status_line, _, _) = request("GET /", "Via: two\r\n");
assert!(status_line.starts_with("HTTP/1.1 501 "));

let (status_line, _, _) = request("GET /", "Via: one two\r\nVia: one two three\r\n");
assert!(status_line.starts_with("HTTP/1.1 200 "));

let (status_line, _, _) = request("GET /", "Via: one\r\nVia: two\r\nVia: wrong\r\n");
assert!(status_line.starts_with("HTTP/1.1 501 "));

let (status_line, _, _) = request("GET /", "Via: wrong\r\n");
assert!(status_line.starts_with("HTTP/1.1 501 "));
}

#[test]
fn test_all_of_match_body() {
let _m = mock("GET", "/")
.match_body(Matcher::AllOf(vec![
Matcher::Regex("one".to_string()),
Matcher::Regex("two".to_string())]))
.create();

let (status_line, _, _) = request_with_body("GET /", "", "one");
assert!(status_line.starts_with("HTTP/1.1 501 "));

let (status_line, _, _) = request_with_body("GET /", "", "two");
assert!(status_line.starts_with("HTTP/1.1 501 "));

let (status_line, _, _) = request_with_body("GET /", "", "one two");
assert!(status_line.starts_with("HTTP/1.1 200 "));

let (status_line, _, _) = request_with_body("GET /", "", "three");
assert!(status_line.starts_with("HTTP/1.1 501 "));
}

#[test]
fn test_all_of_missing_match_header() {
let _m = mock("GET", "/")
.match_header("Via", Matcher::AllOf(vec![
Matcher::Missing]))
.with_body("{}")
.create();

let (status_line, _, _) = request("GET /", "Via: one\r\n");
assert!(status_line.starts_with("HTTP/1.1 501 "));

let (status_line, _, _) = request("GET /", "Via: one\r\nVia: one\r\nVia: one\r\n");
assert!(status_line.starts_with("HTTP/1.1 501 "));

let (status_line, _, _) = request("GET /", "NotVia: one\r\n");
assert!(status_line.starts_with("HTTP/1.1 200 "));

let (status_line, _, _) = request("GET /", "Via: wrong\r\n");
assert!(status_line.starts_with("HTTP/1.1 501 "));

let (status_line, _, _) = request("GET /", "Via: wrong\r\nVia: one\r\n");
assert!(status_line.starts_with("HTTP/1.1 501 "));

let (status_line, _, _) = request("GET /", "Via: one\r\nVia: wrong\r\n");
assert!(status_line.starts_with("HTTP/1.1 501 "));
}

#[test]
fn test_large_utf8_body() {
let mock_body: String = rand::thread_rng()
Expand Down

0 comments on commit 80ea470

Please sign in to comment.