use std::io::Cursor;
use actix_web::HttpResponse;
use serde::{Deserialize, Serialize};
use serde_json::json;
use rocket_test::Resp;
#[path = "rocket_test.rs"]
mod rocket_test;
#[path = "reqwest_test.rs"]
mod reqwest_test;
#[path = "surf_test.rs"]
mod surf_test;
#[path = "ureq_test.rs"]
mod ureq_test;
#[path = "hyper_test.rs"]
mod hyper_test;
#[path = "axum_test.rs"]
mod axum_test;
#[path = "awc_test.rs"]
mod awc_test;
#[path = "isahc_test.rs"]
mod isahc_test;
#[path = "actix_test.rs"]
mod actix_test;
pub enum Stub {
Full,
StatusAccepted,
StatusBadRequest,
StatusConflict,
StatusCreated,
StatusForbidden,
StatusGone,
StatusMovedPermanently,
StatusNoContent,
StatusNotFound,
StatusOk,
StatusPartialContent,
StatusInternalServerError,
StatusUnauthorized,
HeaderJson,
HeaderMany,
HeaderMulti,
HeaderCacheControl,
HeaderOne,
HeaderText,
HeaderXml,
BodyJson,
BodyJsonAbsent,
BodyBytes,
BodyBytesAbsent,
BodyText,
BodyTextAbsent,
}
impl Stub {
fn responses(&self) -> Responses {
use axum::response::IntoResponse as _;
let mut axum_response = axum::response::Response::builder()
.status(axum::http::StatusCode::OK)
.body(json!({"a": "b"}).to_string())
.unwrap();
axum_response
.headers_mut()
.insert("content-type", "application/json".parse().unwrap());
match self {
Stub::Full => Responses(
HttpResponse::Ok()
.append_header(("content-type", "application/json"))
.body(json!({"a": "b"}).to_string()),
Resp(
rocket::Response::build()
.status(rocket::http::Status::Ok)
.raw_header("content-type", "application/json")
.streamed_body(Cursor::new(json!({"a": "b"}).to_string()))
.finalize(),
),
axum_response.into_response(),
),
Stub::StatusAccepted => Responses(
HttpResponse::Accepted().finish(),
rocket::http::Status::Accepted.into(),
axum::http::StatusCode::ACCEPTED.into_response(),
),
Stub::StatusBadRequest => Responses(
HttpResponse::BadRequest().finish(),
rocket::http::Status::BadRequest.into(),
axum::http::StatusCode::BAD_REQUEST.into_response(),
),
Stub::StatusConflict => Responses(
HttpResponse::Conflict().finish(),
rocket::http::Status::Conflict.into(),
axum::http::StatusCode::CONFLICT.into_response(),
),
Stub::StatusCreated => Responses(
HttpResponse::Created().finish(),
rocket::http::Status::Created.into(),
axum::http::StatusCode::CREATED.into_response(),
),
Stub::StatusForbidden => Responses(
HttpResponse::Forbidden().finish(),
rocket::http::Status::Forbidden.into(),
axum::http::StatusCode::FORBIDDEN.into_response(),
),
Stub::StatusGone => Responses(
HttpResponse::Gone().finish(),
rocket::http::Status::Gone.into(),
axum::http::StatusCode::GONE.into_response(),
),
Stub::StatusMovedPermanently => Responses(
HttpResponse::MovedPermanently().finish(),
rocket::http::Status::MovedPermanently.into(),
axum::http::StatusCode::MOVED_PERMANENTLY.into_response(),
),
Stub::StatusNoContent => Responses(
HttpResponse::NoContent().finish(),
rocket::http::Status::NoContent.into(),
axum::http::StatusCode::NO_CONTENT.into_response(),
),
Stub::StatusNotFound => Responses(
HttpResponse::NotFound().finish(),
rocket::http::Status::NotFound.into(),
axum::http::StatusCode::NOT_FOUND.into_response(),
),
Stub::StatusOk => Responses(
HttpResponse::Ok().finish(),
rocket::http::Status::Ok.into(),
axum::http::StatusCode::OK.into_response(),
),
Stub::StatusPartialContent => Responses(
HttpResponse::PartialContent().finish(),
rocket::http::Status::PartialContent.into(),
axum::http::StatusCode::PARTIAL_CONTENT.into_response(),
),
Stub::StatusInternalServerError => Responses(
HttpResponse::InternalServerError().finish(),
rocket::http::Status::InternalServerError.into(),
axum::http::StatusCode::INTERNAL_SERVER_ERROR.into_response(),
),
Stub::StatusUnauthorized => Responses(
HttpResponse::Unauthorized().finish(),
rocket::http::Status::Unauthorized.into(),
axum::http::StatusCode::UNAUTHORIZED.into_response(),
),
Stub::HeaderJson => Responses(
HttpResponse::Ok().append_header(("content-type", "application/json")).finish(),
vec![("content-type", "application/json")].into(),
[("content-type", "application/json")].into_response(),
),
Stub::HeaderMany => Responses(
HttpResponse::Ok()
.append_header(("x-a", "a"))
.append_header(("x-b", "b"))
.finish(),
vec![("x-a", "a"), ("x-b", "b")].into(),
[("x-a", "a"), ("x-b", "b")].into_response(),
),
Stub::HeaderMulti => Responses(
HttpResponse::Ok().append_header(("x-m", "a, b")).finish(),
vec![("x-m", vec!["a", "b"])].into(),
[("x-m", "a, b")].into_response(),
),
Stub::HeaderCacheControl => Responses(
HttpResponse::Ok()
.append_header(("cache-control", "no-cache, no-store"))
.finish(),
vec![("cache-control", vec!["no-cache", "no-store"])].into(),
[("cache-control", "no-cache, no-store")].into_response(),
),
Stub::HeaderOne => Responses(
HttpResponse::Ok().append_header(("x-a", "a")).finish(),
vec![("x-a", "a")].into(),
[("x-a", "a")].into_response(),
),
Stub::HeaderText => Responses(
HttpResponse::Ok().append_header(("content-type", "text/plain")).finish(),
vec![("content-type", "text/plain")].into(),
[("content-type", "text/plain")].into_response(),
),
Stub::HeaderXml => Responses(
HttpResponse::Ok().append_header(("content-type", "application/xml")).finish(),
vec![("content-type", "application/xml")].into(),
[("content-type", "application/xml")].into_response(),
),
Stub::BodyJson => Responses(
HttpResponse::Ok().body(json!({"a": "b"}).to_string()),
json!({"a": "b"}).into(),
axum::Json(json!({"a": "b"})).into_response(),
),
Stub::BodyJsonAbsent => Responses(
HttpResponse::Ok().finish(),
rocket::http::Status::Ok.into(),
axum::http::StatusCode::OK.into_response(),
),
Stub::BodyBytes => Responses(HttpResponse::Ok().body("abcd"), "abcd".into(), b"abcd".into_response()),
Stub::BodyBytesAbsent => Responses(
HttpResponse::Ok().finish(),
rocket::http::Status::Ok.into(),
axum::http::StatusCode::OK.into_response(),
),
Stub::BodyText => Responses(HttpResponse::Ok().body("abcd"), "abcd".into(), "abcd".into_response()),
Stub::BodyTextAbsent => Responses(
HttpResponse::Ok().finish(),
rocket::http::Status::Ok.into(),
axum::http::StatusCode::OK.into_response(),
),
}
}
}
pub struct Responses(pub HttpResponse, pub Resp, pub axum::response::Response);
#[derive(Deserialize, Serialize, Debug, Eq, PartialEq)]
pub struct TestBody {
pub a: String,
}
#[macro_export]
macro_rules! asserhttp_test {
($fn_name:ident, $stub:literal, $resp:expr, $($(.$meth:ident($( $arg:expr ),*))+),+) => {
$($crate::reqwest_test!($fn_name, $stub, $( .$meth($($arg),*) )* );)+
$($crate::surf_test!($fn_name, $stub, $( .$meth($($arg),*) )* );)+
$($crate::ureq_test!($fn_name, $stub, $( .$meth($($arg),*) )* );)+
$($crate::hyper_test!($fn_name, $stub, $( .$meth($($arg),*) )* );)+
$($crate::awc_test!($fn_name, $stub, $( .$meth($($arg),*) )* );)+
$($crate::isahc_test!($fn_name, $stub, $( .$meth($($arg),*) )* );)+
$($crate::actix_test!($fn_name, $resp.0, $( .$meth($($arg),*) )* );)+
$($crate::rocket_test!($fn_name, $resp.1, $( .$meth($($arg),*) )* );)+
$($crate::axum_test!($fn_name, $resp.2, $( .$meth($($arg),*) )* );)+
};
($fn_name:ident, $stub:literal, $resp:expr, $panic_msg:literal, $($(.$meth:ident($( $arg:expr ),*))+),+) => {
$($crate::reqwest_test!($fn_name, $stub, $panic_msg, $( .$meth($($arg),*) )* );)+
$($crate::surf_test!($fn_name, $stub, $panic_msg, $( .$meth($($arg),*) )* );)+
$($crate::ureq_test!($fn_name, $stub, $panic_msg, $( .$meth($($arg),*) )* );)+
$($crate::hyper_test!($fn_name, $stub, $panic_msg, $( .$meth($($arg),*) )* );)+
$($crate::awc_test!($fn_name, $stub, $panic_msg, $( .$meth($($arg),*) )* );)+
$($crate::isahc_test!($fn_name, $stub, $panic_msg, $( .$meth($($arg),*) )* );)+
$($crate::actix_test!($fn_name, $resp.0, $panic_msg, $( .$meth($($arg),*) )* );)+
$($crate::rocket_test!($fn_name, $resp.1, $panic_msg, $( .$meth($($arg),*) )* );)+
$($crate::axum_test!($fn_name, $resp.2, $panic_msg, $( .$meth($($arg),*) )* );)+
};
($fn_name:ident, $stub:literal, $resp:expr, $error:expr, $($(.$meth:ident($( $arg:expr ),*))+),+) => {
$($crate::reqwest_test!($fn_name, $stub, $error, $( .$meth($($arg),*) )*);)+
$($crate::surf_test!($fn_name, $stub, $error, $( .$meth($($arg),*) )* );)+
$($crate::ureq_test!($fn_name, $stub, $error, $( .$meth($($arg),*) )* );)+
$($crate::hyper_test!($fn_name, $stub, $error, $( .$meth($($arg),*) )* );)+
$($crate::awc_test!($fn_name, $stub, $error, $( .$meth($($arg),*) )* );)+
$($crate::isahc_test!($fn_name, $stub, $error, $( .$meth($($arg),*) )* );)+
$($crate::actix_test!($fn_name, $resp.0, $error, $( .$meth($($arg),*) )* );)+
$($crate::rocket_test!($fn_name, $resp.1, $error, $( .$meth($($arg),*) )* );)+
$($crate::axum_test!($fn_name, $resp.2, $error, $( .$meth($($arg),*) )* );)+
};
}
mod status {
use super::Stub::*;
asserhttp_test!(status_should_succeed, "status/ok.json", StatusOk.responses(), .expect_status(200));
asserhttp_test!(status_enum_should_succeed, "status/ok.json", StatusOk.responses(), .expect_status(Status::Ok));
asserhttp_test!(status_should_fail, "status/ok.json", StatusOk.responses(), "expected status to be '100' but was '200'", .expect_status(100));
asserhttp_test!(status_closure_should_succeed, "status/ok.json", StatusOk.responses(), .expect_status(|s| assert_eq!(s, 200)));
asserhttp_test!(status_closure_should_fail, "status/ok.json", StatusOk.responses(), "", .expect_status(|s| assert_eq!(s, 400)));
asserhttp_test!(fallible_status_should_succeed, "status/ok.json", StatusOk.responses(), .try_expect_status(200).unwrap());
asserhttp_test!(fallible_status_enum_should_succeed, "status/ok.json", StatusOk.responses(), .try_expect_status(Status::Ok).unwrap());
asserhttp_test!(fallible_status_should_fail, "status/ok.json", StatusOk.responses(), AsserhttpError::StatusMismatch { expected: 100, actual: 200 }, .try_expect_status(100));
asserhttp_test!(fallible_status_closure_should_succeed, "status/ok.json", StatusOk.responses(), .try_expect_status(|actual| if actual != 200 { Err(AsserhttpError::StatusMismatch { expected: 200, actual }) } else { Ok(()) }).unwrap());
asserhttp_test!(fallible_status_closure_should_fail, "status/ok.json", StatusOk.responses(), AsserhttpError::StatusMismatch { expected: 400, actual: 200 }, .try_expect_status(|actual| if actual != 400 { Err(AsserhttpError::StatusMismatch { expected: 400, actual }) } else { Ok(()) }));
asserhttp_test!(status_ok_should_succeed, "status/ok.json", StatusOk.responses(), .expect_status_ok());
asserhttp_test!(status_ok_should_fail, "status/created.json", StatusCreated.responses(), "expected status to be '200' but was '201'", .expect_status_ok());
asserhttp_test!(status_created_should_succeed, "status/created.json", StatusCreated.responses(), .expect_status_created());
asserhttp_test!(status_created_should_fail, "status/ok.json", StatusOk.responses(), "expected status to be '201' but was '200'", .expect_status_created());
asserhttp_test!(status_accepted_should_succeed, "status/accepted.json", StatusAccepted.responses(), .expect_status_accepted());
asserhttp_test!(status_accepted_should_fail, "status/ok.json", StatusOk.responses(), "expected status to be '202' but was '200'", .expect_status_accepted());
asserhttp_test!(status_no_content_should_succeed, "status/no-content.json", StatusNoContent.responses(), .expect_status_no_content());
asserhttp_test!(status_no_content_should_fail, "status/ok.json", StatusOk.responses(), "expected status to be '204' but was '200'", .expect_status_no_content());
asserhttp_test!(status_partial_content_should_succeed, "status/partial-content.json", StatusPartialContent.responses(), .expect_status_partial_content());
asserhttp_test!(status_partial_content_should_fail, "status/ok.json", StatusOk.responses(), "expected status to be '206' but was '200'", .expect_status_partial_content());
asserhttp_test!(status_bad_request_should_succeed, "status/bad-request.json", StatusBadRequest.responses(), .expect_status_bad_request());
asserhttp_test!(status_bad_request_should_fail, "status/ok.json", StatusOk.responses(), "expected status to be '400' but was '200'", .expect_status_bad_request());
asserhttp_test!(status_unauthorized_should_succeed, "status/unauthorized.json", StatusUnauthorized.responses(), .expect_status_unauthorized());
asserhttp_test!(status_unauthorized_should_fail, "status/ok.json", StatusOk.responses(), "expected status to be '401' but was '200'", .expect_status_unauthorized());
asserhttp_test!(status_forbidden_should_succeed, "status/forbidden.json", StatusForbidden.responses(), .expect_status_forbidden());
asserhttp_test!(status_forbidden_should_fail, "status/ok.json", StatusOk.responses(), "expected status to be '403' but was '200'", .expect_status_forbidden());
asserhttp_test!(status_not_found_should_succeed, "status/not-found.json", StatusNotFound.responses(), .expect_status_not_found());
asserhttp_test!(status_not_found_should_fail, "status/ok.json", StatusOk.responses(), "expected status to be '404' but was '200'", .expect_status_not_found());
asserhttp_test!(status_conflict_should_succeed, "status/conflict.json", StatusConflict.responses(), .expect_status_conflict());
asserhttp_test!(status_conflict_should_fail, "status/ok.json", StatusOk.responses(), "expected status to be '409' but was '200'", .expect_status_conflict());
asserhttp_test!(status_gone_should_succeed, "status/gone.json", StatusGone.responses(), .expect_status_gone());
asserhttp_test!(status_gone_should_fail, "status/ok.json", StatusOk.responses(), "expected status to be '410' but was '200'", .expect_status_gone());
asserhttp_test!(status_internal_server_error_should_succeed, "status/server-error.json", StatusInternalServerError.responses(), .expect_status_internal_server_error());
asserhttp_test!(status_internal_server_error_should_fail, "status/ok.json", StatusOk.responses(), "expected status to be '500' but was '200'", .expect_status_internal_server_error());
asserhttp_test!(status_range_should_succeed, "status/created.json", StatusCreated.responses(), .expect_status_in_range(200, 300));
asserhttp_test!(status_range_should_fail_when_higher, "status/server-error.json", StatusInternalServerError.responses(), "expected status to be in [300;400[ but was '500'", .expect_status_in_range(300, 400));
asserhttp_test!(status_range_should_fail_when_lower, "status/ok.json", StatusOk.responses(), "expected status to be in [300;400[ but was '200'", .expect_status_in_range(300, 400));
asserhttp_test!(status_range_should_succeed_in_inclusive_lower_range, "status/ok.json", StatusOk.responses(), .expect_status_in_range(200, 202));
asserhttp_test!(status_range_should_fail_when_in_exclusive_upper_range, "status/accepted.json", StatusAccepted.responses(), "expected status to be in [200;202[ but was '202'", .expect_status_in_range(200, 202));
asserhttp_test!(status_success_should_succeed, "status/ok.json", StatusOk.responses(), .expect_status_success());
asserhttp_test!(status_success_should_fail, "status/bad-request.json", StatusBadRequest.responses(), "expected status to be in [200;300[ but was '400'", .expect_status_success());
asserhttp_test!(status_redirection_should_succeed, "status/moved-permanently.json", StatusMovedPermanently.responses(), .expect_status_redirection());
asserhttp_test!(status_redirection_should_fail, "status/server-error.json", StatusInternalServerError.responses(), "expected status to be in [300;400[ but was '500'", .expect_status_redirection());
asserhttp_test!(status_client_error_should_succeed, "status/bad-request.json", StatusBadRequest.responses(), .expect_status_client_error());
asserhttp_test!(status_client_error_should_fail, "status/ok.json", StatusOk.responses(), "expected status to be in [400;500[ but was '200'", .expect_status_client_error());
asserhttp_test!(status_server_error_should_succeed, "status/server-error.json", StatusInternalServerError.responses(), .expect_status_server_error());
asserhttp_test!(status_server_error_should_fail, "status/ok.json", StatusOk.responses(), "expected status to be in [500;600[ but was '200'", .expect_status_server_error());
}
mod header {
use super::Stub::*;
use serde_json::json;
asserhttp_test!(header_should_succeed, "header/one.json", HeaderOne.responses(), .expect_header("x-a", "a"));
asserhttp_test!(header_const_should_succeed, "header/json.json", HeaderJson.responses(), .expect_header(headers::CONTENT_TYPE, "application/json"));
asserhttp_test!(header_should_match_key_ignoring_case, "header/one.json", HeaderOne.responses(), .expect_header("X-A", "a"));
asserhttp_test!(header_should_fail_because_key_case_sensitive, "header/one.json", HeaderOne.responses(), "expected header 'x-a' to be equal to 'A' but was 'a'", .expect_header("x-a", "A"));
asserhttp_test!(header_should_fail_when_wrong_key, "header/one.json", HeaderOne.responses(), "expected one header named 'x-b' but none found", .expect_header("x-b", "a"));
asserhttp_test!(header_const_should_fail_when_wrong_key, "header/json.json", HeaderJson.responses(), "expected one header named 'accept' but none found", .expect_header(headers::ACCEPT, "application/json"));
asserhttp_test!(header_should_fail_when_wrong_value, "header/one.json", HeaderOne.responses(), "expected header 'x-a' to be equal to 'b' but was 'a'", .expect_header("x-a", "b"));
asserhttp_test!(header_many_should_succeed, "header/many.json", HeaderMany.responses(), .expect_header("x-a", "a").expect_header("x-b", "b"));
asserhttp_test!(header_should_fail_when_multivalued, "header/multi.json", HeaderMulti.responses(), "expected header 'x-m' to be single valued. Had '2' values '[\"a\", \"b\"]'. Use 'expect_headers' instead", .expect_header("x-m", "a"));
asserhttp_test!(fallible_header_should_succeed, "header/one.json", HeaderOne.responses(), .try_expect_header("x-a", "a").unwrap());
asserhttp_test!(fallible_header_const_should_succeed, "header/json.json", HeaderJson.responses(), .try_expect_header(headers::CONTENT_TYPE, "application/json").unwrap());
asserhttp_test!(fallible_header_should_match_key_ignoring_case, "header/one.json", HeaderOne.responses(), .try_expect_header("X-A", "a").unwrap());
asserhttp_test!(fallible_header_should_fail_because_key_case_sensitive, "header/one.json", HeaderOne.responses(), AsserhttpError::HeaderValueMismatch { key: HeaderKey::from("x-a"), actual: HeaderValue::from("a"), expected: HeaderValue::from("A") }, .try_expect_header("x-a", "A"));
asserhttp_test!(fallible_header_should_fail_when_wrong_key, "header/one.json", HeaderOne.responses(), AsserhttpError::HeaderAbsent { key: HeaderKey::from("x-b") }, .try_expect_header("x-b", "a"));
asserhttp_test!(fallible_header_const_should_fail_when_wrong_key, "header/json.json", HeaderJson.responses(), AsserhttpError::HeaderAbsent { key: HeaderKey::from("accept") }, .try_expect_header(headers::ACCEPT, "application/json"));
asserhttp_test!(fallible_header_should_fail_when_wrong_value, "header/one.json", HeaderOne.responses(), AsserhttpError::HeaderValueMismatch { key: HeaderKey::from("x-a"), actual: HeaderValue::from("a"), expected: HeaderValue::from("b") }, .try_expect_header("x-a", "b"));
asserhttp_test!(fallible_header_many_should_succeed, "header/many.json", HeaderMany.responses(), .try_expect_header("x-a", "a").unwrap().try_expect_header("x-b", "b").unwrap());
asserhttp_test!(fallible_header_should_fail_when_multivalued, "header/multi.json", HeaderMulti.responses(), AsserhttpError::MultivaluedHeader { key: HeaderKey::from("x-m"), values_count: 2, actual_values: HeaderValues::from(["a", "b"]) }, .try_expect_header("x-m", "a"));
asserhttp_test!(header_closure_should_succeed, "header/one.json", HeaderOne.responses(), .expect_header("x-a", |h| assert_eq!(h, "a")));
asserhttp_test!(header_closure_should_fail, "header/one.json", HeaderOne.responses(), "", .expect_header("x-a", |h| assert_eq!(h, "b")));
asserhttp_test!(header_closure_should_fail_when_wrong_key, "header/one.json", HeaderOne.responses(), "", .expect_header("x-w", |h| assert_eq!(h, "a")));
asserhttp_test!(fallible_header_closure_should_succeed, "header/one.json", HeaderOne.responses(), .try_expect_header("x-a", |h| { assert_eq!(h, "a"); Ok(()) }).unwrap());
asserhttp_test!(fallible_header_closure_should_fail_when_wrong_key, "header/one.json", HeaderOne.responses(), "", .try_expect_header("x-w", |h| { assert_eq!(h, "a"); Ok(()) }).unwrap());
asserhttp_test!(header_multi_should_succeed, "header/multi.json", HeaderMulti.responses(), .expect_headers("x-m", ["a", "b"]));
asserhttp_test!(header_multi_const_should_succeed, "header/cache-control.json", HeaderCacheControl.responses(), .expect_headers(headers::CACHE_CONTROL, ["no-cache", "no-store"]));
asserhttp_test!(header_multi_should_match_key_ignoring_case, "header/multi.json", HeaderMulti.responses(), .expect_headers("X-M", ["a", "b"]));
asserhttp_test!(header_multi_should_fail_when_key_missing, "header/multi.json", HeaderMulti.responses(), "expected one header named 'x-b' but none found", .expect_headers("x-b", ["a", "b"]));
asserhttp_test!(header_multi_const_should_fail_when_key_missing, "header/multi.json", HeaderMulti.responses(), "expected one header named 'cache-control' but none found", .expect_headers(headers::CACHE_CONTROL, ["a", "b"]));
asserhttp_test!(header_multi_should_fail_when_one_value_missing, "header/multi.json", HeaderMulti.responses(), "expected header 'x-m' to contain values '[\"a\"]' but contained '[\"a\", \"b\"]'", .expect_headers("x-m", ["a"]));
asserhttp_test!(header_multi_should_fail_when_one_value_not_eq, "header/multi.json", HeaderMulti.responses(), "expected header 'x-m' to contain values '[\"a\", \"c\"]' but contained '[\"a\", \"b\"]'", .expect_headers("x-m", ["a", "c"]));
asserhttp_test!(header_multi_should_fail_because_value_case_sensitive, "header/multi.json", HeaderMulti.responses(), "expected header 'x-m' to contain values '[\"a\", \"B\"]' but contained '[\"a\", \"b\"]'", .expect_headers("x-m", ["a", "B"]));
asserhttp_test!(header_multi_should_fail_when_one_expected_value_missing, "header/multi.json", HeaderMulti.responses(), "expected header 'x-m' to contain values '[\"a\", \"b\", \"c\"]' but contained '[\"a\", \"b\"]'", .expect_headers("x-m", ["a", "b", "c"]));
asserhttp_test!(fallible_header_multi_should_succeed, "header/multi.json", HeaderMulti.responses(), .try_expect_headers("x-m", ["a", "b"]).unwrap());
asserhttp_test!(fallible_header_multi_const_should_succeed, "header/cache-control.json", HeaderCacheControl.responses(), .try_expect_headers(headers::CACHE_CONTROL, ["no-cache", "no-store"]).unwrap());
asserhttp_test!(fallible_header_multi_should_match_key_ignoring_case, "header/multi.json", HeaderMulti.responses(), .try_expect_headers("X-M", ["a", "b"]).unwrap());
asserhttp_test!(fallible_header_multi_should_fail_when_key_missing, "header/multi.json", HeaderMulti.responses(), AsserhttpError::HeaderAbsent { key: HeaderKey::from("x-b") }, .try_expect_headers("x-b", ["a", "b"]));
asserhttp_test!(fallible_header_multi_const_should_fail_when_key_missing, "header/multi.json", HeaderMulti.responses(), AsserhttpError::HeaderAbsent { key: HeaderKey::from("cache-control") }, .try_expect_headers(headers::CACHE_CONTROL, ["a", "b"]));
asserhttp_test!(fallible_header_multi_should_fail_when_one_value_missing, "header/multi.json", HeaderMulti.responses(), AsserhttpError::HeaderValuesMismatch { key: HeaderKey::from("x-m"), actual_values: HeaderValues::from(["a", "b"]), expected: HeaderValues::from(["a"]) }, .try_expect_headers("x-m", ["a"]));
asserhttp_test!(fallible_header_multi_should_fail_when_one_value_not_eq, "header/multi.json", HeaderMulti.responses(), AsserhttpError::HeaderValuesMismatch { key: HeaderKey::from("x-m"), actual_values: HeaderValues::from(["a", "b"]), expected: HeaderValues::from(["a", "c"]) }, .try_expect_headers("x-m", ["a", "c"]));
asserhttp_test!(fallible_header_multi_should_fail_because_value_case_sensitive, "header/multi.json", HeaderMulti.responses(), AsserhttpError::HeaderValuesMismatch { key: HeaderKey::from("x-m"), actual_values: HeaderValues::from(["a", "b"]), expected: HeaderValues::from(["a", "B"]) }, .try_expect_headers("x-m", ["a", "B"]));
asserhttp_test!(fallible_header_multi_should_fail_when_one_expected_value_missing, "header/multi.json", HeaderMulti.responses(), AsserhttpError::HeaderValuesMismatch { key: HeaderKey::from("x-m"), actual_values: HeaderValues::from(["a", "b"]), expected: HeaderValues::from(["a", "b", "c"]) }, .try_expect_headers("x-m", ["a", "b", "c"]));
asserhttp_test!(header_multi_closure_should_succeed, "header/multi.json", HeaderMulti.responses(), .expect_headers("x-m", |h: Vec<&str>| assert!(h.contains(&"a") && h.contains(&"b"))));
asserhttp_test!(header_multi_closure_should_fail, "header/multi.json", HeaderMulti.responses(), "", .expect_headers("x-m", |h: Vec<&str>| assert!(h.contains(&"c"))));
asserhttp_test!(header_multi_closure_should_fail_when_wrong_key, "header/multi.json", HeaderMulti.responses(), "", .expect_headers("x-w", |h: Vec<&str>| assert!(h.contains(&"a") && h.contains(&"b"))));
asserhttp_test!(fallible_header_multi_closure_should_succeed, "header/multi.json", HeaderMulti.responses(), .try_expect_headers("x-m", |h: Vec<&str>| { assert!(h.contains(&"a") && h.contains(&"b")); Ok(()) }).unwrap());
asserhttp_test!(fallible_header_multi_closure_should_fail_when_wrong_key, "header/multi.json", HeaderMulti.responses(), "", .try_expect_headers("x-w", |h: Vec<&str>| { assert!(h.contains(&"a") && h.contains(&"b")); Ok(()) }).unwrap());
asserhttp_test!(header_present_should_succeed, "header/one.json", HeaderOne.responses(), .expect_header_present("x-a"));
asserhttp_test!(header_present_const_should_succeed, "header/json.json", HeaderJson.responses(), .expect_header_present(headers::CONTENT_TYPE));
asserhttp_test!(header_present_should_succeed_ignoring_case, "header/one.json", HeaderOne.responses(), .expect_header_present("X-A"));
asserhttp_test!(header_present_should_fail_when_absent, "header/one.json", HeaderOne.responses(), "expected one header named 'x-b' but none found", .expect_header_present("x-b"));
asserhttp_test!(header_present_const_should_fail_when_absent, "header/json.json", HeaderJson.responses(), "expected one header named 'accept' but none found", .expect_header_present(headers::ACCEPT));
asserhttp_test!(fallible_header_present_should_succeed, "header/one.json", HeaderOne.responses(), .try_expect_header_present("x-a").unwrap());
asserhttp_test!(fallible_header_present_const_should_succeed, "header/json.json", HeaderJson.responses(), .try_expect_header_present(headers::CONTENT_TYPE).unwrap());
asserhttp_test!(fallible_header_present_should_succeed_ignoring_case, "header/one.json", HeaderOne.responses(), .try_expect_header_present("X-A").unwrap());
asserhttp_test!(fallible_header_present_should_fail_when_absent, "header/one.json", HeaderOne.responses(), AsserhttpError::HeaderAbsent { key: HeaderKey::from("x-b") }, .try_expect_header_present("x-b"));
asserhttp_test!(fallible_header_present_const_should_fail_when_absent, "header/json.json", HeaderJson.responses(), AsserhttpError::HeaderAbsent { key: HeaderKey::from("accept") }, .try_expect_header_present(headers::ACCEPT));
asserhttp_test!(header_absent_should_succeed, "header/one.json", HeaderOne.responses(), .expect_header_absent("x-b"));
asserhttp_test!(header_absent_const_should_succeed, "header/one.json", HeaderOne.responses(), .expect_header_absent(headers::ACCEPT));
asserhttp_test!(header_absent_should_fail_when_present, "header/one.json", HeaderOne.responses(), "expected no header named 'x-a' but one found", .expect_header_absent("x-a"));
asserhttp_test!(header_absent_should_fail_when_present_ignoring_case, "header/one.json", HeaderOne.responses(), "expected no header named 'X-A' but one found", .expect_header_absent("X-A"));
asserhttp_test!(header_absent_const_should_fail_when_present, "header/json.json", HeaderJson.responses(), "expected no header named 'content-type' but one found", .expect_header_absent(headers::CONTENT_TYPE));
asserhttp_test!(fallible_header_absent_should_succeed, "header/one.json", HeaderOne.responses(), .try_expect_header_absent("x-b").unwrap());
asserhttp_test!(fallible_header_absent_const_should_succeed, "header/one.json", HeaderOne.responses(), .try_expect_header_absent(headers::ACCEPT).unwrap());
asserhttp_test!(fallible_header_absent_should_fail_when_present, "header/one.json", HeaderOne.responses(), AsserhttpError::HeaderPresent { key: HeaderKey::from("x-a") }, .try_expect_header_absent("x-a"));
asserhttp_test!(fallible_header_absent_should_fail_when_present_ignoring_case, "header/one.json", HeaderOne.responses(), AsserhttpError::HeaderPresent { key: HeaderKey::from("X-A") }, .try_expect_header_absent("X-A"));
asserhttp_test!(fallible_header_absent_const_should_fail_when_present, "header/json.json", HeaderJson.responses(), AsserhttpError::HeaderPresent { key: HeaderKey::from("content-type") }, .try_expect_header_absent(headers::CONTENT_TYPE));
asserhttp_test!(header_content_type_json_should_succeed, "header/json.json", HeaderJson.responses(), .expect_content_type_json());
asserhttp_test!(header_content_type_json_should_fail, "header/xml.json", HeaderXml.responses(), "expected header 'content-type' to be equal to 'application/json' but was 'application/xml'", .expect_content_type_json());
asserhttp_test!(header_content_type_text_should_succeed, "header/text.json", HeaderText.responses(), .expect_content_type_text());
asserhttp_test!(header_content_type_text_should_fail, "header/xml.json", HeaderXml.responses(), "expected header 'content-type' to be equal to 'text/plain' but was 'application/xml'", .expect_content_type_text());
asserhttp_test!(expect_header_first_should_not_be_destructive, "full.json", Full.responses(), .expect_content_type_json().expect_status_ok().expect_body_json_eq(json!({"a": "b"})));
mod relax_type {
use asserhttp::*;
#[test]
#[stubr::mock("header/one.json")]
fn header_accepts_any_str_key() {
isahc::get(stubr.uri()).expect_header("x-a", "a");
isahc::get(stubr.uri()).expect_header("x-a".to_string(), "a");
let key: String = "x-a".to_string();
isahc::get(stubr.uri()).expect_header(key.as_str(), "a");
isahc::get(stubr.uri()).expect_header(&"x-a".to_string(), "a");
}
#[test]
#[stubr::mock("header/one.json")]
fn header_accepts_any_str_value() {
isahc::get(stubr.uri()).expect_header("x-a", "a");
isahc::get(stubr.uri()).expect_header("x-a", "a".to_string());
let value: String = "a".to_string();
isahc::get(stubr.uri()).expect_header("x-a", value.as_str());
isahc::get(stubr.uri()).expect_header("x-a", &"a".to_string());
}
#[test]
#[stubr::mock("header/multi.json")]
fn header_accepts_any_str_values() {
isahc::get(stubr.uri()).expect_headers("x-m", ["a", "b"]);
isahc::get(stubr.uri()).expect_headers("x-m", ["a", "b"]);
isahc::get(stubr.uri()).expect_headers("x-m", ["a".to_string(), "b".to_string()]);
isahc::get(stubr.uri()).expect_headers("x-m", &["a".to_string(), "b".to_string()]);
isahc::get(stubr.uri()).expect_headers("x-m", [&"a".to_string(), &"b".to_string()]);
isahc::get(stubr.uri()).expect_headers("x-m", [&"a".to_string(), &"b".to_string()]);
let (a, b) = ("a".to_string(), "b".to_string());
isahc::get(stubr.uri()).expect_headers("x-m", [a.as_str(), b.as_str()]);
isahc::get(stubr.uri()).expect_headers("x-m", [a.as_str(), b.as_str()]);
isahc::get(stubr.uri()).expect_headers("x-m", vec!["a", "b"]);
isahc::get(stubr.uri()).expect_headers("x-m", vec!["a".to_string(), "b".to_string()]);
isahc::get(stubr.uri()).expect_headers("x-m", vec![&"a".to_string(), &"b".to_string()]);
let (a, b) = ("a".to_string(), "b".to_string());
isahc::get(stubr.uri()).expect_headers("x-m", vec![a.as_str(), b.as_str()]);
}
}
}
mod body {
use serde_json::{json, Value};
use super::{Stub::*, *};
asserhttp_test!(body_json_should_succeed, "body/json/value.json", BodyJson.responses(), .expect_body_json(|b: Value| assert_eq!(b, json!({"a": "b"}))));
asserhttp_test!(body_json_struct_should_succeed, "body/json/value.json", BodyJson.responses(), .expect_body_json(|b: TestBody| assert_eq!(b, TestBody { a: String::from("b") })));
asserhttp_test!(body_json_should_fail_when_closure_fails, "body/json/value.json", BodyJson.responses(), "", .expect_body_json(|b: Value| assert_eq!(b, json!({"a": "c"}))));
asserhttp_test!(fallible_body_json_should_succeed, "body/json/value.json", BodyJson.responses(), .try_expect_body_json(|b: Value| { assert_eq!(b, json!({"a": "b"})); Ok(()) }).unwrap());
asserhttp_test!(fallible_body_json_struct_should_succeed, "body/json/value.json", BodyJson.responses(), .try_expect_body_json(|b: TestBody| { assert_eq!(b, TestBody { a: String::from("b") }); Ok(()) }).unwrap());
asserhttp_test!(fallible_body_json_should_fail_when_closure_fails, "body/json/value.json", BodyJson.responses(), "", .try_expect_body_json(|b: Value| { assert_eq!(b, json!({"a": "c"})); Ok(()) }).unwrap());
asserhttp_test!(body_json_eq_should_succeed, "body/json/value.json", BodyJson.responses(), .expect_body_json_eq(json!({"a": "b"})));
asserhttp_test!(body_json_struct_eq_should_succeed, "body/json/value.json", BodyJson.responses(), .expect_body_json_eq(TestBody { a: String::from("b") }));
asserhttp_test!(body_json_eq_should_fail_when_not_eq, "body/json/value.json", BodyJson.responses(), "json atoms at path \".a\" are not equal:\n lhs:\n \"b\"\n rhs:\n \"c\"", .expect_body_json_eq(json!({"a": "c"})));
asserhttp_test!(body_json_eq_should_fail_when_absent, "body/json/absent.json", BodyJsonAbsent.responses(), "expected a response body but none was present", .expect_body_json_eq(json!({"a": "b"})));
asserhttp_test!(fallible_body_json_eq_should_succeed, "body/json/value.json", BodyJson.responses(), .try_expect_body_json_eq(json!({"a": "b"})).unwrap());
asserhttp_test!(fallible_body_json_struct_eq_should_succeed, "body/json/value.json", BodyJson.responses(), .try_expect_body_json_eq(TestBody { a: String::from("b") }).unwrap());
asserhttp_test!(fallible_body_json_eq_should_fail_when_not_eq, "body/json/value.json", BodyJson.responses(), AsserhttpError::JsonBodyMismatch("json atoms at path \".a\" are not equal:\n lhs:\n \"b\"\n rhs:\n \"c\"".to_string()), .try_expect_body_json_eq(json!({"a": "c"})));
asserhttp_test!(fallible_body_json_eq_should_fail_when_absent, "body/json/absent.json", BodyJsonAbsent.responses(), AsserhttpError::BodyAbsent, .try_expect_body_json_eq(json!({"a": "b"})));
asserhttp_test!(body_text_should_succeed, "body/text/value.json", BodyText.responses(), .expect_body_text(|b| assert_eq!(b, String::from("abcd"))));
asserhttp_test!(body_text_should_fail_when_closure_fails, "body/text/value.json", BodyText.responses(), "", .expect_body_text(|b| assert_eq!(b, String::from("dcba"))));
asserhttp_test!(fallible_body_text_should_succeed, "body/text/value.json", BodyText.responses(), .try_expect_body_text(|b| { assert_eq!(b, String::from("abcd")); Ok(()) }).unwrap());
asserhttp_test!(fallible_body_text_should_fail_when_closure_fails, "body/text/value.json", BodyText.responses(), "", .try_expect_body_text(|b| { assert_eq!(b, String::from("dcba")); Ok(()) }).unwrap());
asserhttp_test!(body_text_eq_should_succeed, "body/text/value.json", BodyText.responses(), .expect_body_text_eq("abcd"));
asserhttp_test!(body_text_eq_should_fail_when_not_eq, "body/text/value.json", BodyText.responses(), "expected body to be 'dcba' but was 'abcd'", .expect_body_text_eq("dcba"));
asserhttp_test!(body_text_eq_should_fail_when_absent, "body/text/absent.json", BodyTextAbsent.responses(), "expected a response body but none was present", .expect_body_text_eq("abcd"));
asserhttp_test!(fallible_body_text_eq_should_succeed, "body/text/value.json", BodyText.responses(), .try_expect_body_text_eq("abcd").unwrap());
asserhttp_test!(fallible_body_text_eq_should_fail_when_not_eq, "body/text/value.json", BodyText.responses(), AsserhttpError::TextBodyMismatch { actual: "abcd".to_string(), expected: "dcba".to_string() }, .try_expect_body_text_eq("dcba"));
asserhttp_test!(fallible_body_text_eq_should_fail_when_absent, "body/text/absent.json", BodyTextAbsent.responses(), AsserhttpError::BodyAbsent, .try_expect_body_text_eq("abcd"));
asserhttp_test!(body_text_regex_should_succeed, "body/text/value.json", BodyText.responses(), .expect_body_text_matches("[a-d]+"));
asserhttp_test!(body_text_regex_should_fail_when_does_not_match, "body/text/value.json", BodyText.responses(), "expected body to match regex '[e-h]+' but was 'abcd'", .expect_body_text_matches("[e-h]+"));
asserhttp_test!(body_text_regex_should_fail_when_absent, "body/text/absent.json", BodyTextAbsent.responses(), "expected a response body but none was present", .expect_body_text_matches("[a-d]+"));
asserhttp_test!(fallible_body_text_regex_should_succeed, "body/text/value.json", BodyText.responses(), .try_expect_body_text_matches("[a-d]+").unwrap());
asserhttp_test!(fallible_body_text_regex_should_fail_when_does_not_match, "body/text/value.json", BodyText.responses(), AsserhttpError::RegexBodyMismatch { actual: "abcd".to_string(), regex: "[e-h]+".to_string() }, .try_expect_body_text_matches("[e-h]+"));
asserhttp_test!(fallible_body_text_regex_should_fail_when_absent, "body/text/absent.json", BodyTextAbsent.responses(), AsserhttpError::BodyAbsent, .try_expect_body_text_matches("[a-d]+"));
asserhttp_test!(body_bytes_should_succeed, "body/bytes/value.json", BodyBytes.responses(), .expect_body_bytes(|b| assert_eq!(b, b"abcd")));
asserhttp_test!(body_bytes_should_fail_when_closure_fails, "body/bytes/value.json", BodyBytes.responses(), "", .expect_body_bytes(|b| assert_eq!(b, b"dcba")));
asserhttp_test!(fallible_body_bytes_should_succeed, "body/bytes/value.json", BodyBytes.responses(), .try_expect_body_bytes(|b| { assert_eq!(b, b"abcd"); Ok(()) }).unwrap());
asserhttp_test!(fallible_body_bytes_should_fail_when_closure_fails, "body/bytes/value.json", BodyBytes.responses(), "", .try_expect_body_bytes(|b| { assert_eq!(b, b"dcba"); Ok(()) } ).unwrap());
asserhttp_test!(body_bytes_eq_should_succeed, "body/bytes/value.json", BodyBytes.responses(), .expect_body_bytes_eq(b"abcd"));
asserhttp_test!(body_bytes_eq_should_fail_when_not_eq, "body/bytes/value.json", BodyBytes.responses(), "expected body to be '[100, 99, 98, 97]' but was '[97, 98, 99, 100]'", .expect_body_bytes_eq(b"dcba"));
asserhttp_test!(body_bytes_eq_should_fail_when_absent, "body/bytes/absent.json", BodyBytesAbsent.responses(), "expected a response body but none was present", .expect_body_bytes_eq(b"abcd"));
asserhttp_test!(fallible_body_bytes_eq_should_succeed, "body/bytes/value.json", BodyBytes.responses(), .try_expect_body_bytes_eq(b"abcd").unwrap());
asserhttp_test!(fallible_body_bytes_eq_should_fail_when_not_eq, "body/bytes/value.json", BodyBytes.responses(), AsserhttpError::BytesBodyMismatch{actual: vec![97, 98, 99, 100], expected: vec![100, 99, 98, 97]}, .try_expect_body_bytes_eq(b"dcba"));
asserhttp_test!(fallible_body_bytes_eq_should_fail_when_absent, "body/bytes/absent.json", BodyBytesAbsent.responses(), AsserhttpError::BodyAbsent, .try_expect_body_bytes_eq(b"abcd"));
asserhttp_test!(body_present_should_succeed, "body/bytes/value.json", BodyBytes.responses(), .expect_body_present());
asserhttp_test!(body_present_should_fail_when_absent, "body/bytes/absent.json", BodyBytesAbsent.responses(), "expected a response body but none was present", .expect_body_present());
asserhttp_test!(fallible_body_present_should_succeed, "body/bytes/value.json", BodyBytes.responses(), .try_expect_body_present().unwrap());
asserhttp_test!(fallible_body_present_should_fail_when_absent, "body/bytes/absent.json", BodyBytesAbsent.responses(), AsserhttpError::BodyAbsent, .try_expect_body_present());
asserhttp_test!(body_absent_should_succeed, "body/bytes/absent.json", BodyBytesAbsent.responses(), .expect_body_absent());
asserhttp_test!(body_absent_should_fail_when_present, "body/bytes/value.json", BodyBytes.responses(), "expected no response body but one was present", .expect_body_absent());
asserhttp_test!(fallible_body_absent_should_succeed, "body/bytes/absent.json", BodyBytesAbsent.responses(), .try_expect_body_absent().unwrap());
asserhttp_test!(fallible_body_absent_should_fail_when_present, "body/bytes/value.json", BodyBytes.responses(), AsserhttpError::BodyPresent, .try_expect_body_absent());
asserhttp_test!(expect_body_first_should_not_be_destructive, "full.json", Full.responses(), .expect_body_json_eq(json!({"a": "b"})).expect_status_ok().expect_content_type_json());
}
mod customizable {
use super::Stub::*;
use asserhttp::AsserhttpResult;
asserhttp::asserhttp_customize!(MyHttpDsl);
pub trait MyHttpDsl<T>: asserhttp::Asserhttp<T> {
fn is_status_ok(&mut self) -> &mut T {
self.expect_status_ok()
}
fn try_is_status_ok(&mut self) -> AsserhttpResult<&mut T> {
self.try_expect_status(200)
}
fn is_json(&mut self) -> &mut T {
self.expect_content_type_json()
}
fn try_is_json(&mut self) -> AsserhttpResult<&mut T> {
self.try_expect_header(asserhttp::headers::CONTENT_TYPE, Self::APPLICATION_JSON)
}
fn has_body(&mut self) -> &mut T {
self.expect_body_present()
}
fn try_has_body(&mut self) -> AsserhttpResult<&mut T> {
self.try_expect_body_present()
}
}
asserhttp_test!(custom_status_should_succeed, "status/ok.json", StatusOk.responses(), .is_status_ok());
asserhttp_test!(fallible_custom_status_should_succeed, "status/ok.json", StatusOk.responses(), .try_is_status_ok().unwrap());
asserhttp_test!(custom_content_type_json_should_succeed, "header/json.json", HeaderJson.responses(), .is_json());
asserhttp_test!(fallible_custom_content_type_json_should_succeed, "header/json.json", HeaderJson.responses(), .try_is_json().unwrap());
asserhttp_test!(custom_body_present_should_succeed, "body/bytes/value.json", BodyBytes.responses(), .has_body());
asserhttp_test!(fallible_custom_body_present_should_succeed, "body/bytes/value.json", BodyBytes.responses(), .try_has_body().unwrap());
}