From c80f8036ec0c7b8b5fb19567a12e45b438f8b62b Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Fri, 15 Nov 2024 09:06:45 +0000 Subject: [PATCH] feat: re-export Method, Url, Request, Response and RequestBuilder from http, url and reqwest crates --- Cargo.toml | 2 +- examples/get.rs | 12 ++++++++---- src/net/mod.rs | 23 ++++++++++++++++------- src/net/result.rs | 4 +++- src/net/system.rs | 37 +++++++++++++++++++------------------ tests/net.rs | 7 +++---- 6 files changed, 50 insertions(+), 35 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f148ad5..9b696ae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ derive_more = { version = "1.0", features = [ ] } http = "1.1" path-clean = "1.0" -reqwest = "0.12" +reqwest = { version = "0.12", features = [ "json" ] } url = "2.5" tempfile = "3.10" diff --git a/examples/get.rs b/examples/get.rs index 96edaea..30b075c 100644 --- a/examples/get.rs +++ b/examples/get.rs @@ -62,7 +62,8 @@ async fn download_and_save_to_file( println!("fetching: {url}"); // Uses the network abstraction to create a perfectly normal `reqwest::ResponseBuilder`. - let request: reqwest::RequestBuilder = net.client().get(url); + // `kxio::net::RequestBuilder` is an alias. + let request: kxio::net::RequestBuilder = net.client().get(url); // Rather than calling `.build().send()?` on the request, pass it to the `net` // This allows the `net` to either make the network request as normal, or, if we are @@ -70,7 +71,8 @@ async fn download_and_save_to_file( // NOTE: if the `.build().send()` is called on the `request` then that WILL result in // a real network request being made, even under test conditions. Only ever use the // `net.send(...)` function to keep your code testable. - let response: reqwest::Response = net.send(request).await?; + // `kxio::net::Response` is an alias for `reqwest::Response`. + let response: kxio::net::Response = net.send(request).await?; let body = response.text().await?; println!("fetched {} bytes", body.bytes().len()); @@ -102,6 +104,8 @@ fn delete_file(file_path: &Path, fs: &kxio::fs::FileSystem) -> kxio::Result<()> mod tests { use super::*; + use kxio::net::{Method, Url}; + // This test demonstrates how to use the `kxio` to test your program. #[tokio::test] async fn should_save_remote_body() { @@ -116,8 +120,8 @@ mod tests { // declare what response should be made for a given request let response = mock_net.response().body("contents").expect("response body"); mock_net - .on(http::Method::GET) - .url(url::Url::parse(url).expect("parse url")) + .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 diff --git a/src/net/mod.rs b/src/net/mod.rs index 943b1a4..db17f20 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -21,7 +21,7 @@ //! //! Write your program to take a reference to [Net]. //! -//! Use the [Net::client] functionto create a [reqwest::RequestBuilder] which you should then pass to the [Net::send] method. +//! Use the [Net::client] functionto create a [RequestBuilder] which you should then pass to the [Net::send] method. //! This is rather than building the request and calling its own `send` method, doing so would result in the network request being sent, even under-test. //! //! ```rust @@ -62,12 +62,14 @@ //! let mock_net = net::mock(); //! ``` //! -//! Create a [reqwest::Client] using [MockNet::client()]. +//! Create a [Client] using [MockNet::client()]. //! //! ```rust //! # let mock_net = kxio::net::mock(); //! let client = mock_net.client(); //! // this is the same as: +//! let client = kxio::net::Client::new(); +//! // this is also the same as: //! let client = reqwest::Client::new(); //! ``` //! @@ -77,16 +79,16 @@ //! //! ```rust //! use kxio::net; -//! use kxio::net::MatchOn; +//! use kxio::net::{Method, Url}; //! //! # #[tokio::main] //! # async fn main() -> net::Result<()> { //! # let mock_net = net::mock(); -//! mock_net.on(http::Method::GET) -//! .url(url::Url::parse("https://example.com")?) +//! mock_net.on(Method::GET) +//! .url(Url::parse("https://example.com")?) //! .respond(mock_net.response().status(200).body("")?); -//! mock_net.on(http::Method::GET) -//! .url(url::Url::parse("https://example.com/foo")?) +//! mock_net.on(Method::GET) +//! .url(Url::parse("https://example.com/foo")?) //! .respond(mock_net.response().status(500).body("Mocked response")?); //! # mock_net.reset(); //! # Ok(()) @@ -151,6 +153,13 @@ pub use result::{Error, Result}; pub use system::{MatchOn, MockNet, Net}; +pub use http::Method; +pub use reqwest::Client; +pub use reqwest::Request; +pub use reqwest::RequestBuilder; +pub use reqwest::Response; +pub use url::Url; + /// Creates a new `Net`. pub const fn new() -> Net { Net::new() diff --git a/src/net/result.rs b/src/net/result.rs index eb4d962..c4f20c0 100644 --- a/src/net/result.rs +++ b/src/net/result.rs @@ -1,6 +1,8 @@ // use derive_more::derive::From; +use crate::net::Request; + /// The Errors that may occur within [kxio::net][crate::net]. #[derive(Debug, From, derive_more::Display)] pub enum Error { @@ -20,7 +22,7 @@ pub enum Error { /// There was network request that doesn't match any that were expected #[display("Unexpected request: {0}", 0.to_string())] - UnexpectedMockRequest(reqwest::Request), + UnexpectedMockRequest(Request), /// There was an error accessing the list of expected requests. RwLockLocked, diff --git a/src/net/system.rs b/src/net/system.rs index f81337d..3b4b775 100644 --- a/src/net/system.rs +++ b/src/net/system.rs @@ -3,6 +3,8 @@ use std::cell::RefCell; use reqwest::{Body, Client}; +use crate::net::{Method, Request, RequestBuilder, Response, Url}; + use super::{Error, Result}; /// A list of planned requests and responses @@ -29,10 +31,10 @@ pub enum MatchOn { /// Contains a list of the criteria that a request must meet before being considered a match. struct Plan { match_request: Vec, - response: reqwest::Response, + response: Response, } impl Plan { - fn matches(&self, request: &reqwest::Request) -> bool { + fn matches(&self, request: &Request) -> bool { self.match_request.iter().all(|criteria| match criteria { MatchRequest::Method(method) => request.method() == method, MatchRequest::Url(uri) => request.url() == uri, @@ -72,7 +74,7 @@ impl Net { } } impl Net { - /// Helper to create a default [reqwest::Client]. + /// Helper to create a default [Client]. /// /// # Example /// @@ -82,7 +84,7 @@ impl Net { /// let client = net.client(); /// let request = client.get("https://hyper.rs"); /// ``` - pub fn client(&self) -> reqwest::Client { + pub fn client(&self) -> Client { Default::default() } @@ -105,10 +107,7 @@ impl Net { /// # Ok(()) /// # } /// ``` - pub async fn send( - &self, - request: impl Into, - ) -> Result { + pub async fn send(&self, request: impl Into) -> Result { let Some(plans) = &self.plans else { return request.into().send().await.map_err(Error::from); }; @@ -148,13 +147,14 @@ impl TryFrom for MockNet { /// # Example /// /// ```rust +/// use kxio::net::{Method, Url}; /// # use kxio::net::Result; /// # fn run() -> Result<()> { /// let mock_net = kxio::net::mock(); /// let client = mock_net.client(); /// // define an expected requet, and the response that should be returned -/// mock_net.on(http::Method::GET) -/// .url(url::Url::parse("https://hyper.rs")?) +/// mock_net.on(Method::GET) +/// .url(Url::parse("https://hyper.rs")?) /// .respond(mock_net.response().status(200).body("Ok")?); /// let net: kxio::net::Net = mock_net.into(); /// // use 'net' in your program, by passing it as a reference @@ -170,7 +170,7 @@ pub struct MockNet { plans: RefCell, } impl MockNet { - /// Helper to create a default [reqwest::Client]. + /// Helper to create a default [Client]. /// /// # Example /// @@ -188,17 +188,18 @@ impl MockNet { /// # Example /// /// ```rust + /// use kxio::net::{Method, Url}; /// # use kxio::net::Result; /// # fn run() -> Result<()> { /// let mock_net = kxio::net::mock(); /// let client = mock_net.client(); - /// mock_net.on(http::Method::GET) - /// .url(url::Url::parse("https://hyper.rs")?) + /// mock_net.on(Method::GET) + /// .url(Url::parse("https://hyper.rs")?) /// .respond(mock_net.response().status(200).body("Ok")?); /// # Ok(()) /// # } /// ``` - pub fn on(&self, method: impl Into) -> WhenRequest { + pub fn on(&self, method: impl Into) -> WhenRequest { WhenRequest::new(self, method) } @@ -256,8 +257,8 @@ impl Drop for Net { } pub enum MatchRequest { - Method(http::Method), - Url(reqwest::Url), + Method(Method), + Url(Url), Header { name: String, value: String }, Body(String), } @@ -268,7 +269,7 @@ pub struct WhenRequest<'net> { } impl<'net> WhenRequest<'net> { - pub fn url(mut self, url: impl Into) -> Self { + pub fn url(mut self, url: impl Into) -> Self { self.match_on.push(MatchRequest::Url(url.into())); self } @@ -293,7 +294,7 @@ impl<'net> WhenRequest<'net> { }); } - fn new(net: &'net MockNet, method: impl Into) -> Self { + fn new(net: &'net MockNet, method: impl Into) -> Self { Self { net, match_on: vec![MatchRequest::Method(method.into())], diff --git a/tests/net.rs b/tests/net.rs index 6a5e010..c7f28e9 100644 --- a/tests/net.rs +++ b/tests/net.rs @@ -1,8 +1,7 @@ -use assert2::let_assert; -use http::Method; // -use kxio::net::{Error, MockNet, Net}; -use reqwest::Url; +use kxio::net::{Error, Method, MockNet, Net, Url}; + +use assert2::let_assert; #[tokio::test] async fn test_get_url() {