kxio/tests/net.rs
Paul Campbell 41973abe18
All checks were successful
Test / build (map[name:nightly]) (push) Successful in 7m10s
Test / build (map[name:stable]) (push) Successful in 13m3s
Release Please / Release-plz (push) Successful in 1m54s
feat(net): mock requests based on query parameters
Changed the way URLs were matched, by breaking them down into their component parts, so that we can match query parameters when they are speciifed in either the URL string, or via the `query` method, or both.
2024-12-03 19:15:36 +00:00

533 lines
13 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(invalid_request)) =
net.send(client.get("https://some.other.url/")).await
);
//then
assert_eq!(invalid_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("nay 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("nay body")
.header("test", "no match"),
)
.await;
//then
let_assert!(Err(kxio::net::Error::UnexpectedMockRequest(_)) = response);
MockNet::try_from(net).await.expect("recover mock").reset();
}
#[tokio::test]
#[should_panic]
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::from(net).send(client.post(url)).await.expect("send");
//then
// Drop implementation for net should panic
}
#[tokio::test]
#[should_panic]
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 = Net::from(net).send(client.post(url)).await.expect("send");
//then
// Drop implementation for mock_net should panic
}
#[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"
);
}