feat(net)!: new api: .on().{get,post, etc}(url), replacing .on(method).get(url)
The `http::Method` parameter is not needed as we now use named methods that the methods on the underlying `reqwest` client. The `url` parameter can be a `String` or `&str` rather than a parsed, and error handled `url::Url`.
This commit is contained in:
parent
a84643e6ae
commit
7da221bfde
4 changed files with 175 additions and 75 deletions
|
@ -104,8 +104,6 @@ fn delete_file(file_path: &Path, fs: &kxio::fs::FileSystem) -> kxio::Result<()>
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use kxio::net::{Method, Url};
|
|
||||||
|
|
||||||
// This test demonstrates how to use the `kxio` to test your program.
|
// This test demonstrates how to use the `kxio` to test your program.
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn should_save_remote_body() {
|
async fn should_save_remote_body() {
|
||||||
|
@ -119,10 +117,7 @@ mod tests {
|
||||||
|
|
||||||
// declare what response should be made for a given request
|
// declare what response should be made for a given request
|
||||||
let response = mock_net.response().body("contents").expect("response body");
|
let response = mock_net.response().body("contents").expect("response body");
|
||||||
mock_net
|
mock_net.on().get(url).respond(response);
|
||||||
.on(Method::GET)
|
|
||||||
.url(Url::parse(url).expect("parse url"))
|
|
||||||
.respond(response);
|
|
||||||
|
|
||||||
// Create a temporary directory that will be deleted with `fs` goes out of scope
|
// Create a temporary directory that will be deleted with `fs` goes out of scope
|
||||||
let fs = kxio::fs::temp().expect("temp fs");
|
let fs = kxio::fs::temp().expect("temp fs");
|
||||||
|
|
|
@ -79,16 +79,14 @@
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! use kxio::net;
|
//! use kxio::net;
|
||||||
//! use kxio::net::{Method, Url};
|
|
||||||
//!
|
|
||||||
//! # #[tokio::main]
|
//! # #[tokio::main]
|
||||||
//! # async fn main() -> net::Result<()> {
|
//! # async fn main() -> net::Result<()> {
|
||||||
//! # let mock_net = net::mock();
|
//! # let mock_net = net::mock();
|
||||||
//! mock_net.on(Method::GET)
|
//! mock_net.on()
|
||||||
//! .url(Url::parse("https://example.com")?)
|
//! .get("https://example.com")
|
||||||
//! .respond(mock_net.response().status(200).body("")?);
|
//! .respond(mock_net.response().status(200).body("")?);
|
||||||
//! mock_net.on(Method::GET)
|
//! mock_net.on()
|
||||||
//! .url(Url::parse("https://example.com/foo")?)
|
//! .get("https://example.com/foo")
|
||||||
//! .respond(mock_net.response().status(500).body("Mocked response")?);
|
//! .respond(mock_net.response().status(500).body("Mocked response")?);
|
||||||
//! # mock_net.reset();
|
//! # mock_net.reset();
|
||||||
//! # Ok(())
|
//! # Ok(())
|
||||||
|
@ -157,7 +155,6 @@ pub use reqwest::Client;
|
||||||
pub use reqwest::Request;
|
pub use reqwest::Request;
|
||||||
pub use reqwest::RequestBuilder;
|
pub use reqwest::RequestBuilder;
|
||||||
pub use reqwest::Response;
|
pub use reqwest::Response;
|
||||||
pub use url::Url;
|
|
||||||
|
|
||||||
/// Creates a new `Net`.
|
/// Creates a new `Net`.
|
||||||
pub const fn new() -> Net {
|
pub const fn new() -> Net {
|
||||||
|
|
|
@ -2,10 +2,13 @@
|
||||||
|
|
||||||
use std::{cell::RefCell, ops::Deref, rc::Rc, sync::Arc};
|
use std::{cell::RefCell, ops::Deref, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
|
use derive_more::derive::{Display, From};
|
||||||
|
use http::Method;
|
||||||
use reqwest::{Body, Client};
|
use reqwest::{Body, Client};
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
use crate::net::{Method, Request, RequestBuilder, Response, Url};
|
use crate::net::{Request, RequestBuilder, Response};
|
||||||
|
|
||||||
use super::{Error, Result};
|
use super::{Error, Result};
|
||||||
|
|
||||||
|
@ -129,15 +132,14 @@ impl MockNet {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use kxio::net::{Method, Url};
|
|
||||||
/// # use kxio::net::Result;
|
/// # use kxio::net::Result;
|
||||||
/// # #[tokio::main]
|
/// # #[tokio::main]
|
||||||
/// # async fn run() -> Result<()> {
|
/// # async fn run() -> Result<()> {
|
||||||
/// let mock_net = kxio::net::mock();
|
/// let mock_net = kxio::net::mock();
|
||||||
/// let client = mock_net.client();
|
/// let client = mock_net.client();
|
||||||
/// // define an expected requet, and the response that should be returned
|
/// // define an expected requet, and the response that should be returned
|
||||||
/// mock_net.on(Method::GET)
|
/// mock_net.on()
|
||||||
/// .url(Url::parse("https://hyper.rs")?)
|
/// .get("https://hyper.rs")
|
||||||
/// .respond(mock_net.response().status(200).body("Ok")?);
|
/// .respond(mock_net.response().status(200).body("Ok")?);
|
||||||
/// let net: kxio::net::Net = mock_net.into();
|
/// let net: kxio::net::Net = mock_net.into();
|
||||||
/// // use 'net' in your program, by passing it as a reference
|
/// // use 'net' in your program, by passing it as a reference
|
||||||
|
@ -172,19 +174,18 @@ impl MockNet {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use kxio::net::{Method, Url};
|
|
||||||
/// # use kxio::net::Result;
|
/// # use kxio::net::Result;
|
||||||
/// # fn run() -> Result<()> {
|
/// # fn run() -> Result<()> {
|
||||||
/// let mock_net = kxio::net::mock();
|
/// let mock_net = kxio::net::mock();
|
||||||
/// let client = mock_net.client();
|
/// let client = mock_net.client();
|
||||||
/// mock_net.on(Method::GET)
|
/// mock_net.on()
|
||||||
/// .url(Url::parse("https://hyper.rs")?)
|
/// .get("https://hyper.rs")
|
||||||
/// .respond(mock_net.response().status(200).body("Ok")?);
|
/// .respond(mock_net.response().status(200).body("Ok")?);
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn on(&self, method: impl Into<Method>) -> WhenRequest {
|
pub fn on(&self) -> WhenRequest {
|
||||||
WhenRequest::new(self, method)
|
WhenRequest::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _when(&self, plan: Plan) {
|
fn _when(&self, plan: Plan) {
|
||||||
|
@ -249,15 +250,47 @@ pub enum MatchRequest {
|
||||||
Body(String),
|
Body(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Display, From)]
|
||||||
|
enum MockError {
|
||||||
|
UrlParse(#[from] url::ParseError),
|
||||||
|
}
|
||||||
|
impl std::error::Error for MockError {}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct WhenRequest<'net> {
|
pub struct WhenRequest<'net> {
|
||||||
net: &'net MockNet,
|
net: &'net MockNet,
|
||||||
match_on: Vec<MatchRequest>,
|
match_on: Vec<MatchRequest>,
|
||||||
|
errors: Vec<MockError>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'net> WhenRequest<'net> {
|
impl<'net> WhenRequest<'net> {
|
||||||
pub fn url(mut self, url: impl Into<Url>) -> Self {
|
pub fn get(self, url: impl Into<String>) -> Self {
|
||||||
self.match_on.push(MatchRequest::Url(url.into()));
|
self._url(Method::GET, url)
|
||||||
|
}
|
||||||
|
pub fn post(self, url: impl Into<String>) -> Self {
|
||||||
|
self._url(Method::POST, url)
|
||||||
|
}
|
||||||
|
pub fn put(self, url: impl Into<String>) -> Self {
|
||||||
|
self._url(Method::PUT, url)
|
||||||
|
}
|
||||||
|
pub fn delete(self, url: impl Into<String>) -> Self {
|
||||||
|
self._url(Method::DELETE, url)
|
||||||
|
}
|
||||||
|
pub fn head(self, url: impl Into<String>) -> Self {
|
||||||
|
self._url(Method::HEAD, url)
|
||||||
|
}
|
||||||
|
pub fn patch(self, url: impl Into<String>) -> Self {
|
||||||
|
self._url(Method::PATCH, url)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _url(mut self, method: http::Method, url: impl Into<String>) -> Self {
|
||||||
|
self.match_on.push(MatchRequest::Method(method));
|
||||||
|
match Url::parse(&url.into()) {
|
||||||
|
Ok(url) => {
|
||||||
|
self.match_on.push(MatchRequest::Url(url));
|
||||||
|
}
|
||||||
|
Err(err) => self.errors.push(err.into()),
|
||||||
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn header(mut self, name: impl Into<String>, value: impl Into<String>) -> Self {
|
pub fn header(mut self, name: impl Into<String>, value: impl Into<String>) -> Self {
|
||||||
|
@ -281,10 +314,11 @@ impl<'net> WhenRequest<'net> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(net: &'net MockNet, method: impl Into<Method>) -> Self {
|
fn new(net: &'net MockNet) -> Self {
|
||||||
Self {
|
Self {
|
||||||
net,
|
net,
|
||||||
match_on: vec![MatchRequest::Method(method.into())],
|
match_on: vec![],
|
||||||
|
errors: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
172
tests/net.rs
172
tests/net.rs
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
use kxio::net::{Error, Method, MockNet, Net, Url};
|
use kxio::net::{Error, MockNet, Net};
|
||||||
|
|
||||||
use assert2::let_assert;
|
use assert2::let_assert;
|
||||||
|
|
||||||
|
@ -17,8 +17,8 @@ async fn test_get_url() {
|
||||||
.expect("body");
|
.expect("body");
|
||||||
|
|
||||||
mock_net
|
mock_net
|
||||||
.on(Method::GET)
|
.on()
|
||||||
.url(Url::parse(url).expect("parse url"))
|
.get("https://www.example.com")
|
||||||
.respond(my_response);
|
.respond(my_response);
|
||||||
|
|
||||||
//when
|
//when
|
||||||
|
@ -32,6 +32,118 @@ async fn test_get_url() {
|
||||||
assert_eq!(response.bytes().await.expect("response body"), "Get 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(net.response().status(200).body("post OK").expect("body"));
|
||||||
|
|
||||||
|
//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(net.response().status(200).body("put OK").expect("body"));
|
||||||
|
|
||||||
|
//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(net.response().status(200).body("delete OK").expect("body"));
|
||||||
|
|
||||||
|
//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(net.response().status(200).body("head OK").expect("body"));
|
||||||
|
|
||||||
|
//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(net.response().status(200).body("patch OK").expect("body"));
|
||||||
|
|
||||||
|
//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]
|
#[tokio::test]
|
||||||
async fn test_get_wrong_url() {
|
async fn test_get_wrong_url() {
|
||||||
//given
|
//given
|
||||||
|
@ -45,10 +157,7 @@ async fn test_get_wrong_url() {
|
||||||
.body("Get OK")
|
.body("Get OK")
|
||||||
.expect("body");
|
.expect("body");
|
||||||
|
|
||||||
mock_net
|
mock_net.on().get(url).respond(my_response);
|
||||||
.on(Method::GET)
|
|
||||||
.url(Url::parse(url).expect("parse url"))
|
|
||||||
.respond(my_response);
|
|
||||||
|
|
||||||
let net = Net::from(mock_net);
|
let net = Net::from(mock_net);
|
||||||
|
|
||||||
|
@ -66,30 +175,6 @@ async fn test_get_wrong_url() {
|
||||||
mock_net.reset();
|
mock_net.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn test_post_url() {
|
|
||||||
//given
|
|
||||||
let net = kxio::net::mock();
|
|
||||||
let client = net.client();
|
|
||||||
|
|
||||||
let url = "https://www.example.com";
|
|
||||||
let my_response = net.response().status(200).body("Post OK").expect("body");
|
|
||||||
|
|
||||||
net.on(Method::POST)
|
|
||||||
.url(Url::parse(url).expect("parse url"))
|
|
||||||
.respond(my_response);
|
|
||||||
|
|
||||||
//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]
|
#[tokio::test]
|
||||||
async fn test_post_by_method() {
|
async fn test_post_by_method() {
|
||||||
//given
|
//given
|
||||||
|
@ -98,8 +183,8 @@ async fn test_post_by_method() {
|
||||||
|
|
||||||
let my_response = net.response().status(200).body("").expect("response body");
|
let my_response = net.response().status(200).body("").expect("response body");
|
||||||
|
|
||||||
net.on(Method::POST)
|
net.on()
|
||||||
// NOTE: No URL specified - so shou∂ match any URL
|
// NOTE: No URL specified - so should match any URL
|
||||||
.respond(my_response);
|
.respond(my_response);
|
||||||
|
|
||||||
//when
|
//when
|
||||||
|
@ -125,7 +210,7 @@ async fn test_post_by_body() {
|
||||||
.body("response body")
|
.body("response body")
|
||||||
.expect("body");
|
.expect("body");
|
||||||
|
|
||||||
net.on(Method::POST)
|
net.on()
|
||||||
// No URL - so any POST with a matching body
|
// No URL - so any POST with a matching body
|
||||||
.body("match on body")
|
.body("match on body")
|
||||||
.respond(my_response);
|
.respond(my_response);
|
||||||
|
@ -156,9 +241,7 @@ async fn test_post_by_header() {
|
||||||
.body("response body")
|
.body("response body")
|
||||||
.expect("body");
|
.expect("body");
|
||||||
|
|
||||||
net.on(Method::POST)
|
net.on().header("test", "match").respond(my_response);
|
||||||
.header("test", "match")
|
|
||||||
.respond(my_response);
|
|
||||||
|
|
||||||
//when
|
//when
|
||||||
let response = Net::from(net)
|
let response = Net::from(net)
|
||||||
|
@ -191,10 +274,7 @@ async fn test_post_by_header_wrong_value() {
|
||||||
.body("response body")
|
.body("response body")
|
||||||
.expect("body");
|
.expect("body");
|
||||||
|
|
||||||
mock_net
|
mock_net.on().header("test", "match").respond(my_response);
|
||||||
.on(Method::POST)
|
|
||||||
.header("test", "match")
|
|
||||||
.respond(my_response);
|
|
||||||
let net = Net::from(mock_net);
|
let net = Net::from(mock_net);
|
||||||
|
|
||||||
//when
|
//when
|
||||||
|
@ -226,10 +306,7 @@ async fn test_unused_post_as_net() {
|
||||||
.body("Post OK")
|
.body("Post OK")
|
||||||
.expect("body");
|
.expect("body");
|
||||||
|
|
||||||
mock_net
|
mock_net.on().post(url).respond(my_response);
|
||||||
.on(Method::POST)
|
|
||||||
.url(Url::parse(url).expect("prase url"))
|
|
||||||
.respond(my_response);
|
|
||||||
|
|
||||||
let _net = Net::from(mock_net);
|
let _net = Net::from(mock_net);
|
||||||
|
|
||||||
|
@ -254,10 +331,7 @@ async fn test_unused_post_as_mocknet() {
|
||||||
.body("Post OK")
|
.body("Post OK")
|
||||||
.expect("body");
|
.expect("body");
|
||||||
|
|
||||||
mock_net
|
mock_net.on().post(url).respond(my_response);
|
||||||
.on(Method::POST)
|
|
||||||
.url(Url::parse(url).expect("parse url"))
|
|
||||||
.respond(my_response);
|
|
||||||
|
|
||||||
//when
|
//when
|
||||||
// don't send the planned request
|
// don't send the planned request
|
||||||
|
|
Loading…
Reference in a new issue