From b4ca82e85a209747bd3d14792d7545a4021391d1 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Wed, 6 Nov 2024 21:22:25 +0000 Subject: [PATCH] feat(net): chose what to match on for request Default match on method and url --- src/net/mod.rs | 2 +- src/net/system.rs | 65 +++++++++++++++++++++++++++++++++++++++-------- tests/net.rs | 36 +++++++++++++++++++++++--- 3 files changed, 88 insertions(+), 15 deletions(-) diff --git a/src/net/mod.rs b/src/net/mod.rs index 601bc60..a1d2f29 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -7,7 +7,7 @@ mod result; pub use result::{Error, Result}; -pub use system::Net; +pub use system::{MatchOn, Net}; use system::{Mocked, Unmocked}; diff --git a/src/net/system.rs b/src/net/system.rs index 7396c89..9cd4872 100644 --- a/src/net/system.rs +++ b/src/net/system.rs @@ -1,6 +1,6 @@ +// use std::marker::PhantomData; -// use super::{Error, Result}; pub trait NetType {} @@ -12,10 +12,19 @@ impl NetType for Unmocked {} type Plans = Vec; +#[derive(Debug, PartialEq, Eq)] +pub enum MatchOn { + Method, + Url, + Body, + Headers, +} + #[derive(Debug)] pub struct Plan { request: reqwest::Request, response: reqwest::Response, + match_on: Vec, } pub struct Net { @@ -50,15 +59,34 @@ impl Net { pub async fn send(&mut self, request: reqwest::RequestBuilder) -> Result { let request = request.build()?; let index = self.plans.iter().position(|plan| { - // TODO: add support or only matching on selected criteria - plan.request.method() == request.method() - && plan.request.url() == request.url() - && match (plan.request.body(), request.body()) { + // METHOD + (if plan.match_on.contains(&MatchOn::Method) { + plan.request.method() == request.method() + } else { + true + }) + // URL + && (if plan.match_on.contains(&MatchOn::Url) { + plan.request.url() == request.url() + } else { + true + }) + // BODY + && (if plan.match_on.contains(&MatchOn::Body) { + match (plan.request.body(), request.body()) { (None, None) => true, (Some(plan), Some(request)) => plan.as_bytes() == request.as_bytes(), _ => false, } - && plan.request.headers() == request.headers() + } else { + true + }) + // HEADERS + && (if plan.match_on.contains(&MatchOn::Headers) { + plan.request.headers() == request.headers() + } else { + true + }) }); match index { Some(i) => Ok(self.plans.remove(i).response), @@ -70,11 +98,24 @@ impl Net { } pub fn on(&mut self, request: reqwest::Request) -> OnRequest { - OnRequest { net: self, request } + OnRequest { + net: self, + request, + match_on: vec![MatchOn::Method, MatchOn::Url], + } } - fn _on(&mut self, request: reqwest::Request, response: reqwest::Response) { - self.plans.push(Plan { request, response }) + fn _on( + &mut self, + request: reqwest::Request, + response: reqwest::Response, + match_on: Vec, + ) { + self.plans.push(Plan { + request, + response, + match_on, + }) } } impl Drop for Net { @@ -86,9 +127,13 @@ impl Drop for Net { pub struct OnRequest<'net> { net: &'net mut Net, request: reqwest::Request, + match_on: Vec, } impl<'net> OnRequest<'net> { + pub fn match_on(self, match_on: Vec) -> Self { + Self{net:self.net, request:self.request, match_on} + } pub fn respond(self, response: reqwest::Response) { - self.net._on(self.request, response) + self.net._on(self.request, response, self.match_on) } } diff --git a/tests/net.rs b/tests/net.rs index 426b919..21d67f9 100644 --- a/tests/net.rs +++ b/tests/net.rs @@ -1,5 +1,5 @@ // -use kxio::net::Error; +use kxio::net::{Error, MatchOn}; type TestResult = Result<(), Error>; @@ -30,7 +30,7 @@ async fn test_get() -> TestResult { } #[tokio::test] -async fn test_post() -> TestResult { +async fn test_post() { //given let mut net = kxio::net::mock(); let client = net.client(); @@ -46,13 +46,41 @@ async fn test_post() -> TestResult { net.on(request).respond(my_response.into()); //when - let response = net.send(client.post(url)).await?; + let response = 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"); +} - Ok(()) +#[tokio::test] +async fn test_post_by_url() { + //given + let mut net = kxio::net::mock(); + let client = net.client(); + + let url = "https://www.example.com"; + let request = client.post(url).build().expect("build request"); + let my_response = net + .response() + .status(200) + .body("Post OK") + .expect("request body"); + + net.on(request) + .match_on(vec![ + // MatchOn::Method, + MatchOn::Url + ]) + .respond(my_response.into()); + + //when + // This request is a GET, not POST - but should still match + let response = net.send(client.get(url)).await.expect("response"); + + //then + assert_eq!(response.status(), http::StatusCode::OK); + assert_eq!(response.bytes().await.expect("response body"), "Post OK"); } #[tokio::test]