#[allow(unused_imports)]
use test_log::test;
#[allow(unused_imports)]
use pact_models::PactSpecification;
#[allow(unused_imports)]
use serde_json;
#[allow(unused_imports)]
use expectest::prelude::*;
#[allow(unused_imports)]
#[cfg(feature = "plugins")] use pact_plugin_driver::catalogue_manager::register_core_entries;
#[allow(unused_imports)]
use pact_models::interaction::{Interaction, http_interaction_from_json};
#[allow(unused_imports)]
use pact_matching::{match_interaction_request, match_interaction_response};
#[allow(unused_imports)]
use pact_models::prelude::{Pact, RequestResponsePact};
#[tokio::test]
async fn null_found_at_key_where_not_null_expected() {
println!("FILE: tests/spec_testcases/v3/response/body/null found at key where not null expected.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Name should not be null",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"name": "Mary"
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"name": null
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/null found at key where not null expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/null found at key where not null expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn objects_in_array_no_matches() {
println!("FILE: tests/spec_testcases/v3/response/body/objects in array no matches.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Array of objects, properties match on incorrect objects",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": [
{"favouriteColor": "red"},
{"favouriteNumber": 2}
]
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": [
{"favouriteColor": "blue",
"favouriteNumber": 4},
{"favouriteColor": "red",
"favouriteNumber": 2}
]
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array no matches.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array no matches.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn missing_body_found_when_empty_expected() {
println!("FILE: tests/spec_testcases/v3/response/body/missing body found when empty expected.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Missing body found, when an empty body was expected",
"expected" : {
"body": null
},
"actual": {
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/missing body found when empty expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/missing body found when empty expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn matches_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/matches xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Responses match",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": "redblue"
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": "redblue"
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/matches xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/matches xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn array_at_top_level_with_matchers_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/array at top level with matchers xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "XML top level array matches",
"expected": {
"headers": {"Content-Type": "application/xml"},
"body" : "",
"matchingRules" : {
"body": {
"$.people.*['@id']": {
"matchers": [
{
"match": "type"
}
]
},
"$.people.*['@name']": {
"matchers": [
{
"match": "type"
}
]
},
"$.people.*['@dob']": {
"matchers": [
{
"match": "regex",
"regex": "\\d{2}/\\d{2}/\\d{4}"
}
]
},
"$.people.*['@timestamp']": {
"matchers": [
{
"match": "regex",
"regex": "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}"
}
]
}
}
}
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/array at top level with matchers xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/array at top level with matchers xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn array_with_type_matcher_mismatch_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/array with type matcher mismatch xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "XML array with type matcher mismatch",
"expected": {
"headers": {},
"body" : "Fred",
"matchingRules" : {
"body": {
"$.people": {
"matchers": [
{
"match": "type"
}
]
}
}
}
},
"actual": {
"headers": {},
"body": "FredFredFred"
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/array with type matcher mismatch xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/array with type matcher mismatch xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn no_body_no_content_type() {
println!("FILE: tests/spec_testcases/v3/response/body/no body no content type.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "No body, no content-type",
"expected" : {
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"feet": 4,
"name": "Mary",
"favouriteColours": ["red","blue"]
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/no body no content type.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/no body no content type.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn keys_out_of_order_match_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/keys out of order match xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "XML Favourite number and favourite colours out of order",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": ""
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/keys out of order match xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/keys out of order match xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn array_at_top_level_with_matchers() {
println!("FILE: tests/spec_testcases/v3/response/body/array at top level with matchers.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "top level array matches",
"expected": {
"headers": {"Content-Type": "application/json"},
"body" : [ {
"dob" : "06/11/2015",
"name" : "Rogger the Dogger",
"id" : 3380634027,
"timestamp" : "2015-06-11T13:17:29"
}, {
"dob" : "06/11/2015",
"name" : "Cat in the Hat",
"id" : 1284270029,
"timestamp" : "2015-06-11T13:17:29"
} ],
"matchingRules" : {
"body": {
"$[0].id": {
"matchers": [
{
"match": "type"
}
]
},
"$[1].id": {
"matchers": [
{
"match": "type"
}
]
},
"$[0].name": {
"matchers": [
{
"match": "type"
}
]
},
"$[1].name": {
"matchers": [
{
"match": "type"
}
]
},
"$[1].dob": {
"matchers": [
{
"match": "regex",
"regex": "\\d{2}/\\d{2}/\\d{4}"
}
]
},
"$[1].timestamp": {
"matchers": [
{
"match": "regex",
"regex": "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}"
}
]
},
"$[0].timestamp": {
"matchers": [
{
"match": "regex",
"regex": "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}"
}
]
},
"$[0].dob": {
"matchers": [
{
"match": "regex",
"regex": "\\d{2}/\\d{2}/\\d{4}"
}
]
}
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": [
{
"dob": "11/06/2015",
"name": "Bob The Builder",
"id": 1234567890,
"timestamp": "2000-06-10T20:41:37"
},
{
"dob": "12/10/2000",
"name": "Slinky Malinky",
"id": 6677889900,
"timestamp": "2015-06-10T22:98:78"
}
]
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/array at top level with matchers.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/array at top level with matchers.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn array_at_top_level() {
println!("FILE: tests/spec_testcases/v3/response/body/array at top level.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "top level array matches",
"expected": {
"headers": {"Content-Type": "application/json"},
"body": [
{
"dob": "06/10/2015",
"name": "Rogger the Dogger",
"id": 1014753708,
"timestamp": "2015-06-10T20:41:37"
},
{
"dob": "06/10/2015",
"name": "Cat in the Hat",
"id": 8858030303,
"timestamp": "2015-06-10T20:41:37"
}
]
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": [
{
"dob": "06/10/2015",
"name": "Rogger the Dogger",
"id": 1014753708,
"timestamp": "2015-06-10T20:41:37"
},
{
"dob": "06/10/2015",
"name": "Cat in the Hat",
"id": 8858030303,
"timestamp": "2015-06-10T20:41:37"
}
]
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/array at top level.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/array at top level.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn missing_key() {
println!("FILE: tests/spec_testcases/v3/response/body/missing key.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Missing key alligator name",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"name": "Mary",
"age": 3
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator": {
"age": 3
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/missing key.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/missing key.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn plain_text_missing_body() {
println!("FILE: tests/spec_testcases/v3/response/body/plain text missing body.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Plain text that matches",
"expected" : {
"headers": { "Content-Type": "text/plain" }
},
"actual": {
"headers": { "Content-Type": "text/plain" }
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/plain text missing body.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/plain text missing body.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn unexpected_index_with_null_value() {
println!("FILE: tests/spec_testcases/v3/response/body/unexpected index with null value.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Unexpected favourite colour with null value",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"favouriteColours": ["red","blue"]
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"favouriteColours": ["red","blue", null]
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/unexpected index with null value.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/unexpected index with null value.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn non_empty_body_found_when_empty_expected() {
println!("FILE: tests/spec_testcases/v3/response/body/non empty body found when empty expected.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Non empty body found, when an empty body was expected",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": null
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"feet": 4,
"name": "Mary",
"favouriteColours": ["red","blue"]
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/non empty body found when empty expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/non empty body found when empty expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn null_found_in_array_when_not_null_expected() {
println!("FILE: tests/spec_testcases/v3/response/body/null found in array when not null expected.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Favourite numbers expected to be strings found a null",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"favouriteNumbers": ["1","2","3"]
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"favouriteNumbers": ["1",null,"3"]
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/null found in array when not null expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/null found in array when not null expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn deeply_nested_objects_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/deeply nested objects xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "XML Comparisons should work even on nested objects",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": "FredJohn"
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": "FredJohn"
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/deeply nested objects xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/deeply nested objects xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn plain_text_empty_body() {
println!("FILE: tests/spec_testcases/v3/response/body/plain text empty body.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Plain text that matches",
"expected" : {
"headers": { "Content-Type": "text/plain" },
"body": ""
},
"actual": {
"headers": { "Content-Type": "text/plain" },
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/plain text empty body.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/plain text empty body.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn empty_body_no_content_type() {
println!("FILE: tests/spec_testcases/v3/response/body/empty body no content type.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Empty body, no content-type",
"expected" : {
"body": ""
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/empty body no content type.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/empty body no content type.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn value_found_in_array_when_empty_expected_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/value found in array when empty expected xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "XML Favourite numbers expected to contain empty, but non-empty found",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": "13"
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": "123"
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/value found in array when empty expected xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/value found in array when empty expected xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn additional_property_with_type_matcher_that_does_not_match() {
println!("FILE: tests/spec_testcases/v3/response/body/additional property with type matcher that does not match.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "additional property with type matcher wildcards that don't match",
"expected": {
"headers": {},
"body" : {
"myPerson": {
"name": "Any name"
}
},
"matchingRules" : {
"body": {
"$.myPerson.*": {
"matchers": [
{
"match": "type"
}
]
}
}
}
},
"actual": {
"headers": {},
"body": {
"myPerson": {
"name": 39,
"age": 39,
"nationality": "Australian"
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/additional property with type matcher that does not match.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/additional property with type matcher that does not match.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn objects_in_array_type_matching() {
println!("FILE: tests/spec_testcases/v3/response/body/objects in array type matching.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "objects in array type matching",
"expected": {
"headers": {},
"body": [{
"name": "John Smith",
"age": 50
}],
"matchingRules": {
"body": {
"$": {
"matchers": [
{
"match": "type"
}
]
},
"$[*]": {
"matchers": [
{
"match": "type"
}
]
}
}
}
},
"actual": {
"headers": {},
"body": [{
"name": "Peter Peterson",
"age": 22,
"gender": "Male"
}, {
"name": "John Johnston",
"age": 64
}]
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array type matching.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array type matching.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn objects_in_array_second_matches() {
println!("FILE: tests/spec_testcases/v3/response/body/objects in array second matches.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Property of second object matches, but unexpected element recieved",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": [
{"favouriteColor": "red"}
]
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": [
{"favouriteColor": "blue",
"favouriteNumber": 4},
{"favouriteColor": "red",
"favouriteNumber": 2}
]
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array second matches.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array second matches.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn objects_in_array_no_matches_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/objects in array no matches xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "XML Array of objects, properties match on incorrect objects",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": ""
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array no matches xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array no matches xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn different_xml_namespaces() {
println!("FILE: tests/spec_testcases/v3/response/body/different xml namespaces.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "XML namespaces do not match",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": ""
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/different xml namespaces.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/different xml namespaces.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn array_with_type_matcher_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/array with type matcher xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "array with type matcher",
"expected": {
"headers": {},
"body" : "Fred",
"matchingRules" : {
"body": {
"$.people": {
"matchers": [
{
"match": "type"
}
]
},
"$.people[*]": {
"matchers": [
{
"match": "type"
}
]
}
}
}
},
"actual": {
"headers": {},
"body": "FredGeorgeCat"
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/array with type matcher xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/array with type matcher xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn array_in_different_order_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/array in different order xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "XML Favourite colours in wrong order",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": ""
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/array in different order xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/array in different order xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn missing_body() {
println!("FILE: tests/spec_testcases/v3/response/body/missing body.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Missing body",
"expected" : {
"headers": {"Content-Type": "application/json"}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"feet": 4,
"name": "Mary",
"favouriteColours": ["red","blue"]
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/missing body.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/missing body.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn null_body_no_content_type() {
println!("FILE: tests/spec_testcases/v3/response/body/null body no content type.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "NULL body, no content-type",
"expected" : {
"body": null
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": null
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/null body no content type.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/null body no content type.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn not_null_found_in_array_when_null_expected() {
println!("FILE: tests/spec_testcases/v3/response/body/not null found in array when null expected.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Favourite numbers expected to contain null, but not null found",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"favouriteNumbers": ["1",null,"3"]
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"favouriteNumbers": ["1","2","3"]
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/not null found in array when null expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/not null found in array when null expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn unexpected_index_with_non_empty_value_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/unexpected index with non-empty value xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "XML Unexpected favourite colour",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": "redblue"
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": "redbluetaupe"
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/unexpected index with non-empty value xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/unexpected index with non-empty value xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn different_value_found_at_index_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/different value found at index xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "XML Incorrect favourite colour",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": "redblue"
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": "redpurple"
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/different value found at index xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/different value found at index xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn matches_with_floats() {
println!("FILE: tests/spec_testcases/v3/response/body/matches with floats.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Response match with floats",
"expected": {
"headers": {"Content-Type": "application/json"},
"matchingRules": {
"body": {
"$.product.price": {
"matchers": [
{
"match": "regex",
"regex": "\\d(\\.\\d{1,2})"
}
]
}
}
},
"body": [
{
"product": {
"id": 123,
"description": "Television",
"price": 500.55
}
}
]
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": [
{
"product": {
"id": 123,
"description": "Television",
"price": 500.55
}
}
]
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/matches with floats.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/matches with floats.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn matches_with_regex_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/matches with regex xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "XML Requests match with regex",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"matchingRules": {
"body": {
"$.alligator['@name']": {
"matchers": [
{
"match": "regex",
"regex": "\\w+"
}
]
}
}
},
"body": ""
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/matches with regex xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/matches with regex xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn plain_text_that_does_not_match() {
println!("FILE: tests/spec_testcases/v3/response/body/plain text that does not match.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Plain text that does not match",
"expected" : {
"headers": { "Content-Type": "text/plain" },
"body": "alligator named mary"
},
"actual": {
"headers": { "Content-Type": "text/plain" },
"body": "alligator named fred"
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/plain text that does not match.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/plain text that does not match.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn array_in_different_order() {
println!("FILE: tests/spec_testcases/v3/response/body/array in different order.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Favourite colours in wrong order",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"favouriteColours": ["red","blue"]
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"favouriteColours": ["blue", "red"]
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/array in different order.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/array in different order.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn property_name_is_different_case() {
println!("FILE: tests/spec_testcases/v3/response/body/property name is different case.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Property names on objects are case sensitive",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"FavouriteColour": "red"
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"favouritecolour": "red"
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/property name is different case.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/property name is different case.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn matches_with_regex() {
println!("FILE: tests/spec_testcases/v3/response/body/matches with regex.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Requests match with regex",
"expected" : {
"headers": {"Content-Type": "application/json"},
"matchingRules": {
"body": {
"$.alligator.name": {
"matchers": [
{
"match": "regex",
"regex": "\\w+"
}
]
}
}
},
"body": {
"alligator":{
"name": "Mary",
"feet": 4,
"favouriteColours": ["red","blue"]
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"feet": 4,
"name": "Harry",
"favouriteColours": ["red","blue"]
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/matches with regex.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/matches with regex.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn array_with_type_matcher() {
println!("FILE: tests/spec_testcases/v3/response/body/array with type matcher.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "array with type matcher",
"expected": {
"headers": {},
"body" : {
"myDates": [
10
]
},
"matchingRules" : {
"body": {
"$.myDates": {
"matchers": [
{
"match": "type"
}
]
},
"$.myDates[*]": {
"matchers": [
{
"match": "type"
}
]
}
}
}
},
"actual": {
"headers": {},
"body": {
"myDates": [
20,
5,
1910
]
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/array with type matcher.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/array with type matcher.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn unexpected_index_with_missing_value_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/unexpected index with missing value xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "XML Unexpected favourite colour with missing value",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": "redblue"
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": "redblue"
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/unexpected index with missing value xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/unexpected index with missing value xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn array_at_top_level_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/array at top level xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "XML top level array matches",
"expected": {
"headers": {"Content-Type": "application/xml"},
"body": ""
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/array at top level xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/array at top level xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn no_body_no_content_type_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/no body no content type xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "XML No body, no content-type",
"expected" : {
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/no body no content type xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/no body no content type xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn array_with_regex_matcher_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/array with regex matcher xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "XML array with regex matcher",
"expected": {
"headers": {},
"body" : "29/10/2015",
"matchingRules" : {
"body": {
"$.myDates": {
"matchers": [
{
"match": "type"
}
]
},
"$.myDates[*].date['#text']": {
"matchers": [
{
"match": "regex",
"regex": "\\d{2}/\\d{2}/\\d{4}"
}
]
}
}
}
},
"actual": {
"headers": {},
"body": "01/11/201015/12/201430/06/2015"
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/array with regex matcher xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/array with regex matcher xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn plain_text_that_matches() {
println!("FILE: tests/spec_testcases/v3/response/body/plain text that matches.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Plain text that matches",
"expected" : {
"headers": { "Content-Type": "text/plain" },
"body": "alligator named mary"
},
"actual": {
"headers": { "Content-Type": "text/plain" },
"body": "alligator named mary"
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/plain text that matches.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/plain text that matches.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn unexpected_key_with_empty_value_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/unexpected key with empty value xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "XML Unexpected phone number with empty value",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": ""
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/unexpected key with empty value xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/unexpected key with empty value xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn missing_index() {
println!("FILE: tests/spec_testcases/v3/response/body/missing index.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Missing favorite colour",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"favouriteColours": ["red","blue"]
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator": {
"favouriteColours": ["red"]
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/missing index.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/missing index.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn different_value_found_at_index() {
println!("FILE: tests/spec_testcases/v3/response/body/different value found at index.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Incorrect favourite colour",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"favouriteColours": ["red","blue"]
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"favouriteColours": ["red","taupe"]
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/different value found at index.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/different value found at index.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn missing_body_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/missing body xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "XML Missing body",
"expected" : {
"headers": {"Content-Type": "application/xml"}
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/missing body xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/missing body xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn missing_body_no_content_type() {
println!("FILE: tests/spec_testcases/v3/response/body/missing body no content type.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Missing body, no content-type",
"expected" : {
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"feet": 4,
"name": "Mary",
"favouriteColours": ["red","blue"]
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/missing body no content type.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/missing body no content type.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn matches() {
println!("FILE: tests/spec_testcases/v3/response/body/matches.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Responses match",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"name": "Mary",
"feet": 4,
"favouriteColours": ["red","blue"]
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"feet": 4,
"name": "Mary",
"favouriteColours": ["red","blue"]
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/matches.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/matches.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn number_found_in_array_when_string_expected() {
println!("FILE: tests/spec_testcases/v3/response/body/number found in array when string expected.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Favourite numbers expected to be strings found a number",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"favouriteNumbers": ["1","2","3"]
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"favouriteNumbers": ["1",2,"3"]
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/number found in array when string expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/number found in array when string expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn empty_body() {
println!("FILE: tests/spec_testcases/v3/response/body/empty body.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Empty body",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": ""
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/empty body.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/empty body.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn different_xml_namespace_prefixes() {
println!("FILE: tests/spec_testcases/v3/response/body/different xml namespace prefixes.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "different XML namespace declarations/prefixes",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": "1"
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": "1"
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/different xml namespace prefixes.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/different xml namespace prefixes.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn plain_text_regex_matching() {
println!("FILE: tests/spec_testcases/v3/response/body/plain text regex matching.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Plain text that matches",
"expected" : {
"headers": { "Content-Type": "text/plain" },
"body": "alligator named mary",
"matchingRules": {
"body": {
"$": {
"matchers": [
{
"match": "regex",
"regex": "alligator.*"
}
]
}
}
}
},
"actual": {
"headers": { "Content-Type": "text/plain" },
"body": "alligator named brent"
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/plain text regex matching.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/plain text regex matching.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn unexpected_xml_namespace() {
println!("FILE: tests/spec_testcases/v3/response/body/unexpected xml namespace.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "XML namespaces not expected",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": ""
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/unexpected xml namespace.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/unexpected xml namespace.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn deeply_nested_objects() {
println!("FILE: tests/spec_testcases/v3/response/body/deeply nested objects.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Comparisons should work even on nested objects",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"object1": {
"object2": {
"object4": {
"object5": {
"name": "Mary",
"friends": ["Fred", "John"]
},
"object6": {
"phoneNumber": 1234567890
}
}
}
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"object1":{
"object2": {
"object4":{
"object5": {
"name": "Mary",
"friends": ["Fred", "John"],
"gender": "F"
},
"object6": {
"phoneNumber": 1234567890
}
}
},
"color": "red"
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/deeply nested objects.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/deeply nested objects.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn unexpected_key_with_non_empty_value_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/unexpected key with non-empty value xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "XML Unexpected phone number",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": ""
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/unexpected key with non-empty value xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/unexpected key with non-empty value xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn missing_key_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/missing key xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "XML Missing key alligator name",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": ""
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/missing key xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/missing key xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn string_found_in_array_when_number_expected() {
println!("FILE: tests/spec_testcases/v3/response/body/string found in array when number expected.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Favourite Numbers expected to be numbers, but 2 is a string",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"favouriteNumbers": [1,2,3]
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"favouriteNumbers": [1,"2",3]
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/string found in array when number expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/string found in array when number expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn array_with_type_matcher_mismatch() {
println!("FILE: tests/spec_testcases/v3/response/body/array with type matcher mismatch.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "array with type matcher mismatch",
"expected": {
"headers": {},
"body" : {
"myDates": [
10
]
},
"matchingRules" : {
"body": {
"$.myDates[*]": {
"matchers": [
{
"match": "type"
}
]
}
}
}
},
"actual": {
"headers": {},
"body": {
"myDates": [
20,
5,
"100299"
]
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/array with type matcher mismatch.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/array with type matcher mismatch.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn unexpected_index_with_not_null_value() {
println!("FILE: tests/spec_testcases/v3/response/body/unexpected index with not null value.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Unexpected favourite colour",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"favouriteColours": ["red","blue"]
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"favouriteColours": ["red","blue","taupe"]
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/unexpected index with not null value.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/unexpected index with not null value.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn number_found_at_key_when_string_expected() {
println!("FILE: tests/spec_testcases/v3/response/body/number found at key when string expected.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Number of feet expected to be string but was number",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"feet": "4"
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"feet": 4
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/number found at key when string expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/number found at key when string expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn keys_out_of_order_match() {
println!("FILE: tests/spec_testcases/v3/response/body/keys out of order match.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Favourite number and favourite colours out of order",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"favouriteNumber": 7,
"favouriteColours": ["red","blue"]
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"favouriteColours": ["red","blue"],
"favouriteNumber": 7
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/keys out of order match.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/keys out of order match.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn matches_with_integers() {
println!("FILE: tests/spec_testcases/v3/response/body/matches with integers.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Response match with integers",
"expected" : {
"method": "POST",
"path": "/",
"query": {},
"headers": {"Content-Type": "application/json"},
"matchingRules": {
"body": {
"$.alligator.feet": {
"matchers": [
{
"match": "regex",
"regex": "[0-9]"
}
]
}
}
},
"body": {
"alligator":{
"name": "Mary",
"feet": 4,
"favouriteColours": ["red","blue"]
}
}
},
"actual": {
"method": "POST",
"path": "/",
"query": {},
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"feet": 4,
"name": "Mary",
"favouriteColours": ["red","blue"]
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/matches with integers.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/matches with integers.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn not_null_found_at_key_when_null_expected() {
println!("FILE: tests/spec_testcases/v3/response/body/not null found at key when null expected.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Name should be null",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"name": null
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"name": "Fred"
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/not null found at key when null expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/not null found at key when null expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn null_body() {
println!("FILE: tests/spec_testcases/v3/response/body/null body.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "NULL body",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": null
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": null
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/null body.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/null body.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn different_value_found_at_key_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/different value found at key xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "XML Incorrect value at alligator name",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": ""
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/different value found at key xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/different value found at key xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn plain_text_regex_matching_missing_body() {
println!("FILE: tests/spec_testcases/v3/response/body/plain text regex matching missing body.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Plain text that matches",
"expected" : {
"headers": { "Content-Type": "text/plain" },
"body": "alligator named mary",
"matchingRules": {
"body": {
"$": {
"matchers": [
{
"match": "regex",
"regex": "alligator named .{4}"
}
]
}
}
}
},
"actual": {
"headers": { "Content-Type": "text/plain" }
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/plain text regex matching missing body.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/plain text regex matching missing body.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn array_with_regex_matcher() {
println!("FILE: tests/spec_testcases/v3/response/body/array with regex matcher.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "array with regex matcher",
"expected": {
"headers": {},
"body" : {
"myDates": [
"29/10/2015"
]
},
"matchingRules" : {
"body": {
"$.myDates": {
"matchers": [
{
"match": "type"
}
]
},
"$.myDates[*]": {
"matchers": [
{
"match": "regex",
"regex": "\\d{2}/\\d{2}/\\d{4}"
}
]
}
}
}
},
"actual": {
"headers": {},
"body": {
"myDates": [
"01/11/2010",
"15/12/2014",
"30/06/2015"
]
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/array with regex matcher.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/array with regex matcher.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn different_value_found_at_key() {
println!("FILE: tests/spec_testcases/v3/response/body/different value found at key.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Incorrect value at alligator name",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"name": "Mary"
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"name": "Fred"
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/different value found at key.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/different value found at key.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn unexpected_key_with_null_value() {
println!("FILE: tests/spec_testcases/v3/response/body/unexpected key with null value.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Unexpected phone number with null value",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"name": "Mary"
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"name": "Mary",
"phoneNumber": null
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/unexpected key with null value.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/unexpected key with null value.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn string_found_at_key_when_number_expected() {
println!("FILE: tests/spec_testcases/v3/response/body/string found at key when number expected.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Number of feet expected to be number but was string",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"feet": 4
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"feet": "4"
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/string found at key when number expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/string found at key when number expected.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn objects_in_array_second_matches_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/objects in array second matches xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "XML Property of second object matches, but unexpected element received",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": ""
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array second matches xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array second matches xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn missing_index_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/missing index xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Missing favorite colour",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": "redblue"
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": "red"
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/missing index xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/missing index xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn objects_in_array_first_matches_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/objects in array first matches xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "XML Properties match but unexpected element received",
"expected": {
"headers": {"Content-Type": "application/xml"},
"body": ""
},
"actual": {
"headers": {"Content-Type": "application/xml"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array first matches xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array first matches xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn unexpected_key_with_not_null_value() {
println!("FILE: tests/spec_testcases/v3/response/body/unexpected key with not null value.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Unexpected phone number",
"expected" : {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"name": "Mary"
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"name": "Mary",
"phoneNumber": "12345678"
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/unexpected key with not null value.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/unexpected key with not null value.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn additional_property_with_type_matcher() {
println!("FILE: tests/spec_testcases/v3/response/body/additional property with type matcher.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "additional property with type matcher wildcards",
"expected": {
"headers": {},
"body" : {
"myPerson": {
"name": "Any name"
}
},
"matchingRules" : {
"body": {
"$.myPerson.*": {
"matchers": [
{
"match": "type"
}
]
}
}
}
},
"actual": {
"headers": {},
"body": {
"myPerson": {
"name": "Jon Peterson",
"age": "39",
"nationality": "Australian"
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/additional property with type matcher.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/additional property with type matcher.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn objects_in_array_type_matching_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/objects in array type matching xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "XML objects in array type matching",
"expected": {
"headers": {},
"body": "",
"matchingRules": {
"body": {
"$": {
"matchers": [
{
"match": "type"
}
]
},
"$[*]": {
"matchers": [
{
"match": "type"
}
]
},
"$[*].*": {
"matchers": [
{
"match": "type"
}
]
}
}
}
},
"actual": {
"headers": {},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array type matching xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array type matching xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn objects_in_array_with_type_mismatching() {
println!("FILE: tests/spec_testcases/v3/response/body/objects in array with type mismatching.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "objects in array with type mismatching",
"expected": {
"headers": {},
"body": [{
"Name": "John Smith",
"Age": 50
}],
"matchingRules": {
"body": {
"$[*]": {
"matchers": [
{
"match": "type"
}
]
},
"$[*].*": {
"matchers": [
{
"match": "type"
}
]
}
}
}
},
"actual": {
"headers": {},
"body": [{
"name": "Peter Peterson",
"age": 22,
"gender": "Male"
}, {}]
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array with type mismatching.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array with type mismatching.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn plain_text_regex_matching_that_does_not_match() {
println!("FILE: tests/spec_testcases/v3/response/body/plain text regex matching that does not match.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Plain text that matches",
"expected" : {
"headers": { "Content-Type": "text/plain" },
"body": "alligator named mary",
"matchingRules": {
"body": {
"$": {
"matchers": [
{
"match": "regex",
"regex": "alligator named .{4}"
}
]
}
}
}
},
"actual": {
"headers": { "Content-Type": "text/plain" },
"body": "alligator named brent"
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/plain text regex matching that does not match.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/plain text regex matching that does not match.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn objects_in_array_with_type_mismatching_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/objects in array with type mismatching xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "XML objects in array with type mismatching",
"expected": {
"headers": {},
"body": "",
"matchingRules": {
"body": {
"$[*]": {
"matchers": [
{
"match": "type"
}
]
},
"$[*].*": {
"matchers": [
{
"match": "type"
}
]
}
}
}
},
"actual": {
"headers": {},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array with type mismatching xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array with type mismatching xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
#[cfg(feature = "xml")]
async fn property_name_is_different_case_xml() {
println!("FILE: tests/spec_testcases/v3/response/body/property name is different case xml.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "XML Property names on objects are case sensitive",
"expected" : {
"headers": {"Content-Type": "application/xml"},
"body": ""
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": ""
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/property name is different case xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/property name is different case xml.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn matches_with_type() {
println!("FILE: tests/spec_testcases/v3/response/body/matches with type.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": true,
"comment": "Response match with same type",
"expected" : {
"headers": {"Content-Type": "application/json"},
"matchingRules": {
"body": {
"$.alligator.name": {
"matchers": [
{
"match": "type"
}
]
},
"$.alligator.feet": {
"matchers": [
{
"match": "type"
}
]
}
}
},
"body": {
"alligator":{
"name": "Mary",
"feet": 4,
"favouriteColours": ["red","blue"]
}
}
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": {
"alligator":{
"feet": 5,
"name": "Harry the very hungry alligator with an extra foot",
"favouriteColours": ["red","blue"]
}
}
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/matches with type.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/matches with type.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}
#[tokio::test]
async fn objects_in_array_first_matches() {
println!("FILE: tests/spec_testcases/v3/response/body/objects in array first matches.json");
#[allow(unused_mut)]
let mut pact: serde_json::Value = serde_json::from_str(r#"
{
"match": false,
"comment": "Properties match but unexpected element received",
"expected": {
"headers": {"Content-Type": "application/json"},
"body": [
{
"favouriteColor": "red"
}
]
},
"actual": {
"headers": {"Content-Type": "application/json"},
"body": [
{
"favouriteColor": "red",
"favouriteNumber": 2
},
{
"favouriteColor": "blue",
"favouriteNumber": 2
}
]
}
}
"#).unwrap();
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("expected").unwrap()});
let expected = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array first matches.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("EXPECTED: {:?}", expected);
println!("BODY: {}", expected.as_request_response().unwrap().response.body.display_string());
let interaction_json = serde_json::json!({"type": "Synchronous/HTTP", "response": pact.get("actual").unwrap()});
let actual = http_interaction_from_json("tests/spec_testcases/v3/response/body/objects in array first matches.json", &interaction_json, &PactSpecification::V3).unwrap();
println!("ACTUAL: {:?}", actual);
println!("BODY: {}", actual.as_request_response().unwrap().response.body.display_string());
let pact_match = pact.get("match").unwrap();
#[cfg(feature = "plugins")] pact_matching::matchers::configure_core_catalogue();
let pact = RequestResponsePact { interactions: vec![ expected.as_request_response().unwrap_or_default() ], .. RequestResponsePact::default() }.boxed();
let result = match_interaction_response(expected, actual, pact, &PactSpecification::V3).await.unwrap();
println!("RESULT: {:?}", result);
if pact_match.as_bool().unwrap() {
expect!(result.iter()).to(be_empty());
} else {
expect!(result.iter()).to_not(be_empty());
}
}