kxio/tests/net.rs
Paul Campbell 8534eca219
All checks were successful
Test / build (map[name:nightly]) (push) Successful in 4m43s
Test / build (map[name:stable]) (push) Successful in 5m3s
Release Please / Release-plz (push) Successful in 40s
feat(net): don't use panic to signal test should fail
2024-12-12 15:17:46 +00:00

644 lines
15 KiB
Rust

use http::StatusCode;
//
use kxio::net::{Error, MockNet, Net};
use assert2::let_assert;
#[tokio::test]
async fn test_get_url() {
//given
let mock_net = kxio::net::mock();
let url = "https://www.example.com";
let url_alpha = format!("{url}/alpha");
let url_beta = format!("{url}/beta");
mock_net
.on()
.get(&url_alpha)
.respond(StatusCode::OK)
.body("Get OK alpha")
.expect("mock alpha");
mock_net
.on()
.get(&url_beta)
.respond(StatusCode::OK)
.body("Get OK beta")
.expect("mock beta");
mock_net
.on()
.get(url)
.respond(StatusCode::OK)
.body("Get OK")
.expect("mock");
let net = Net::from(mock_net);
//when
let response_alpha = net.get(url_alpha).send().await.expect("response alpha");
let response_beta = net.get(url_beta).send().await.expect("response beta");
let response = net.get(url).send().await.expect("response");
//then
assert_eq!(response_alpha.status(), http::StatusCode::OK);
assert_eq!(
response_alpha.bytes().await.expect("response body alpha"),
"Get OK alpha"
);
assert_eq!(response_beta.status(), http::StatusCode::OK);
assert_eq!(
response_beta.bytes().await.expect("response body beta"),
"Get OK beta"
);
assert_eq!(response.status(), http::StatusCode::OK);
assert_eq!(response.bytes().await.expect("response body"), "Get OK");
}
#[tokio::test]
async fn test_post_url() {
//given
let net = kxio::net::mock();
let client = net.client();
let url = "https://www.example.com";
net.on()
.post(url)
.respond(StatusCode::OK)
.body("post OK")
.expect("mock");
//when
let response = Net::from(net)
.send(client.post(url))
.await
.expect("reponse");
//then
assert_eq!(response.status(), http::StatusCode::OK);
assert_eq!(response.bytes().await.expect("response body"), "post OK");
}
#[tokio::test]
async fn test_put_url() {
//given
let net = kxio::net::mock();
let client = net.client();
let url = "https://www.example.com";
net.on()
.put(url)
.respond(StatusCode::OK)
.body("put OK")
.expect("mock");
//when
let response = Net::from(net).send(client.put(url)).await.expect("reponse");
//then
assert_eq!(response.status(), http::StatusCode::OK);
assert_eq!(response.bytes().await.expect("response body"), "put OK");
}
#[tokio::test]
async fn test_delete_url() {
//given
let net = kxio::net::mock();
let client = net.client();
let url = "https://www.example.com";
net.on()
.delete(url)
.respond(StatusCode::OK)
.body("delete OK")
.expect("mock");
//when
let response = Net::from(net)
.send(client.delete(url))
.await
.expect("reponse");
//then
assert_eq!(response.status(), http::StatusCode::OK);
assert_eq!(response.bytes().await.expect("response body"), "delete OK");
}
#[tokio::test]
async fn test_head_url() {
//given
let net = kxio::net::mock();
let client = net.client();
let url = "https://www.example.com";
net.on()
.head(url)
.respond(StatusCode::OK)
.body("head OK")
.expect("mock");
//when
let response = Net::from(net)
.send(client.head(url))
.await
.expect("reponse");
//then
assert_eq!(response.status(), http::StatusCode::OK);
assert_eq!(response.bytes().await.expect("response body"), "head OK");
}
#[tokio::test]
async fn test_patch_url() {
//given
let net = kxio::net::mock();
let client = net.client();
let url = "https://www.example.com";
net.on()
.patch(url)
.respond(StatusCode::OK)
.body("patch OK")
.expect("mock");
//when
let response = Net::from(net)
.send(client.patch(url))
.await
.expect("reponse");
//then
assert_eq!(response.status(), http::StatusCode::OK);
assert_eq!(response.bytes().await.expect("response body"), "patch OK");
}
// #[tokio::test]
// async fn test_get_auth_url() {
// //given
// let net = kxio::net::mock();
//
// let url = "https://user:pass@www.example.com";
//
// net.on()
// .get(url)
// .respond(StatusCode::OK)
// .body("post OK")
// .expect("mock");
//
// //when
// let response = Net::from(net).get(url).send().await.expect("reponse");
//
// //then
// assert_eq!(response.status(), http::StatusCode::OK);
// assert_eq!(response.bytes().await.expect("response body"), "post OK");
// }
#[tokio::test]
async fn test_get_wrong_url() {
//given
let net = kxio::net::mock();
let client = net.client();
let url = "https://www.example.com";
net.on()
.get(url)
.respond(StatusCode::OK)
.body("Get OK")
.expect("mock");
let net = Net::from(net);
//when
let_assert!(
Err(Error::UnexpectedMockRequest { request }) =
net.send(client.get("https://some.other.url/")).await
);
//then
assert_eq!(request.url().to_string(), "https://some.other.url/");
// remove pending unmatched request - we never meant to match against it
let mock_net = MockNet::try_from(net).await.expect("recover net");
mock_net.reset();
}
#[tokio::test]
async fn test_post_by_method() {
//given
let net = kxio::net::mock();
let client = net.client();
// NOTE: No URL specified - so should match any URL
net.on().respond(StatusCode::OK).body("").expect("mock");
//when
let response = Net::from(net)
.send(client.post("https://some.other.url"))
.await
.expect("response");
//then
assert_eq!(response.status(), http::StatusCode::OK);
assert_eq!(response.bytes().await.expect("response body"), "");
}
#[tokio::test]
async fn test_post_by_body() {
//given
let net = kxio::net::mock();
let client = net.client();
// No URL - so any POST with a matching body
net.on()
.body("match on body")
.respond(StatusCode::OK)
.body("response body")
.expect("mock");
//when
let response = Net::from(net)
.send(client.post("https://some.other.url").body("match on body"))
.await
.expect("response");
//then
assert_eq!(response.status(), http::StatusCode::OK);
assert_eq!(
response.bytes().await.expect("response body"),
"response body"
);
}
#[tokio::test]
async fn test_post_by_header() {
//given
let net = kxio::net::mock();
let client = net.client();
net.on()
.header("test", "match")
.respond(StatusCode::OK)
.body("response body")
.expect("mock");
//when
let response = Net::from(net)
.send(
client
.post("https://some.other.url")
.body("any body")
.header("test", "match"),
)
.await
.expect("response");
//then
assert_eq!(response.status(), http::StatusCode::OK);
assert_eq!(
response.bytes().await.expect("response body"),
"response body"
);
}
#[tokio::test]
async fn test_post_by_header_wrong_value() {
//given
let mock_net = kxio::net::mock();
let client = mock_net.client();
mock_net
.on()
.header("test", "match")
.respond(StatusCode::OK)
.body("response body")
.expect("mock");
let net = Net::from(mock_net);
//when
let response = net
.send(
client
.post("https://some.other.url")
.body("any body")
.header("test", "no match"),
)
.await;
//then
let_assert!(Err(kxio::net::Error::UnexpectedMockRequest { request: _ }) = response);
MockNet::try_from(net).await.expect("recover mock").reset();
}
#[tokio::test]
#[should_panic(expected = "1 expected requests were not made")]
async fn test_unused_post_as_net() {
//given
let mock_net = kxio::net::mock();
let url = "https://www.example.com";
mock_net
.on()
.post(url)
.respond(StatusCode::OK)
.body("Post OK")
.expect("mock");
let net = Net::from(mock_net);
//when
// don't send the planned request
// let _response = net.send(client.post(url)).await.expect("send");
//then
net.assert_no_unused_plans();
}
#[tokio::test]
#[should_panic(expected = "1 expected requests were not made")]
async fn test_unused_post_as_mocknet() {
//given
let mock_net = kxio::net::mock();
let url = "https://www.example.com";
mock_net
.on()
.post(url)
.respond(StatusCode::OK)
.body("Post OK")
.expect("mock");
//when
// don't send the planned request
// let _response = mock_net.send(client.post(url)).await.expect("send");
//then
mock_net.assert_no_unused_plans();
}
#[tokio::test]
async fn test_get_url_with_fragment() {
//given
let net = kxio::net::mock();
let client = net.client();
let url = "https://www.example.com#test";
net.on()
.get(url)
.respond(StatusCode::OK)
.body("post OK")
.expect("mock");
//when
let response = Net::from(net).send(client.get(url)).await.expect("reponse");
//then
assert_eq!(response.status(), http::StatusCode::OK);
assert_eq!(response.bytes().await.expect("response body"), "post OK");
}
#[tokio::test]
async fn test_get_with_query_parameters() {
//given
let mock_net = kxio::net::mock();
let url = "https://www.example.com/path";
mock_net
.on()
.get(url)
.query("key-1", "value-1")
.respond(StatusCode::OK)
.body("with query parameters 1/1")
.expect("mock");
mock_net
.on()
.get(url)
.query("key-1", "value-2")
.respond(StatusCode::OK)
.body("with query parameters 1/2")
.expect("mock");
mock_net
.on()
.get(url)
.query("key-2", "value-2")
.respond(StatusCode::OK)
.body("with query parameters 2/2")
.expect("mock");
mock_net
.on()
.get(url)
.respond(StatusCode::OK)
.body("sans query parameters")
.expect("mock");
let net = Net::from(mock_net);
//when
// The order of 12 nad 11 should be in that order to ensure we test the discrimination of the
// query value when the keys are the same
let response_with_12 = net
.get(url)
.query("key-1", "value-2")
.send()
.await
.expect("response with qp 1/2");
let response_with_11 = net
.get(url)
.query("key-1", "value-1")
.send()
.await
.expect("response with qp 1/1");
let response_with_22 = net
.get(url)
.query("key-2", "value-2")
.send()
.await
.expect("response with qp 2/2");
let response_sans_qp = net.get(url).send().await.expect("response sans qp");
//then
assert_eq!(
response_with_11.bytes().await.expect("with qp 1/1 body"),
"with query parameters 1/1"
);
assert_eq!(
response_with_12.bytes().await.expect("with qp 1/2 body"),
"with query parameters 1/2"
);
assert_eq!(
response_with_22.bytes().await.expect("with qp 2/2 body"),
"with query parameters 2/2"
);
assert_eq!(
response_sans_qp.bytes().await.expect("sans qp body"),
"sans query parameters"
);
}
#[tokio::test]
async fn test_get_with_duplicate_query_keys() {
//given
let mock_net = kxio::net::mock();
let url = "https://www.example.com/path";
mock_net
.on()
.get(url)
.query("key", "value-1")
.query("key", "value-2")
.respond(StatusCode::OK)
.body("key:value-1,value-2")
.expect("mock");
mock_net
.on()
.get(url)
.query("key", "value-3")
.query("key", "value-4")
.respond(StatusCode::OK)
.body("key:value-3,value-4")
.expect("mock");
let net = Net::from(mock_net);
//when
let response_a = net
.get(url)
.query("key", "value-2")
.query("key", "value-1")
.send()
.await
.expect("response a");
let response_b = net
.get(url)
.query("key", "value-3")
.query("key", "value-4")
.send()
.await
.expect("response b");
//then
assert_eq!(
response_a.bytes().await.expect("response a bytes"),
"key:value-1,value-2"
);
assert_eq!(
response_b.bytes().await.expect("response b bytes"),
"key:value-3,value-4"
);
}
#[tokio::test]
async fn test_get_with_basic_auth() {
//given
let mock_net = kxio::net::mock();
let url = "https://www.example.com/path";
mock_net
.on()
.get(url)
.basic_auth("bob", Some("secret"))
.respond(StatusCode::OK)
.mock()
.expect("mock");
mock_net
.on()
.get(url)
.basic_auth("bob", None::<String>)
.respond(StatusCode::FORBIDDEN)
.mock()
.expect("mock");
let net = Net::from(mock_net);
//when
let invalid = net.get(url).basic_auth("bob", None::<String>).send().await;
let valid = net
.get(url)
.basic_auth("bob", Some("secret"))
.send()
.await
.expect("valid response");
//then
let_assert!(Err(Error::ResponseError { response }) = invalid);
assert_eq!(response.status(), StatusCode::FORBIDDEN);
assert_eq!(valid.status(), StatusCode::OK);
}
#[tokio::test]
async fn test_get_with_bearer_auth() {
//given
let mock_net = kxio::net::mock();
let url = "https://www.example.com/path";
mock_net
.on()
.get(url)
.bearer_auth("token")
.respond(StatusCode::OK)
.mock()
.expect("mock");
mock_net
.on()
.get(url)
.bearer_auth("invalid")
.respond(StatusCode::FORBIDDEN)
.mock()
.expect("mock");
let net = Net::from(mock_net);
//when
let invalid = net.get(url).bearer_auth("invalid").send().await;
let valid = net
.get(url)
.bearer_auth("token")
.send()
.await
.expect("valid response");
//then
let_assert!(Err(Error::ResponseError { response }) = invalid);
assert_eq!(response.status(), StatusCode::FORBIDDEN);
assert_eq!(valid.status(), StatusCode::OK);
}
#[tokio::test]
async fn test_get_with_user_agent() {
//given
let mock_net = kxio::net::mock();
let url = "https://www.example.com/path";
mock_net
.on()
.get(url)
.user_agent("007")
.respond(StatusCode::OK)
.mock()
.expect("mock");
mock_net
.on()
.get(url)
.user_agent("orange")
.respond(StatusCode::FORBIDDEN)
.mock()
.expect("mock");
let net = Net::from(mock_net);
//when
let invalid = net.get(url).user_agent("orange").send().await;
let valid = net
.get(url)
.user_agent("007")
.send()
.await
.expect("valid response");
//then
let_assert!(Err(Error::ResponseError { response }) = invalid);
assert_eq!(response.status(), StatusCode::FORBIDDEN);
assert_eq!(valid.status(), StatusCode::OK);
}