feat(net): chose what to match on for request
Default match on method and url
This commit is contained in:
parent
a3369ce890
commit
b4ca82e85a
3 changed files with 88 additions and 15 deletions
|
@ -7,7 +7,7 @@ mod result;
|
||||||
|
|
||||||
pub use result::{Error, Result};
|
pub use result::{Error, Result};
|
||||||
|
|
||||||
pub use system::Net;
|
pub use system::{MatchOn, Net};
|
||||||
use system::{Mocked, Unmocked};
|
use system::{Mocked, Unmocked};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
//
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
//
|
|
||||||
use super::{Error, Result};
|
use super::{Error, Result};
|
||||||
|
|
||||||
pub trait NetType {}
|
pub trait NetType {}
|
||||||
|
@ -12,10 +12,19 @@ impl NetType for Unmocked {}
|
||||||
|
|
||||||
type Plans = Vec<Plan>;
|
type Plans = Vec<Plan>;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub enum MatchOn {
|
||||||
|
Method,
|
||||||
|
Url,
|
||||||
|
Body,
|
||||||
|
Headers,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Plan {
|
pub struct Plan {
|
||||||
request: reqwest::Request,
|
request: reqwest::Request,
|
||||||
response: reqwest::Response,
|
response: reqwest::Response,
|
||||||
|
match_on: Vec<MatchOn>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Net<T: NetType> {
|
pub struct Net<T: NetType> {
|
||||||
|
@ -50,15 +59,34 @@ impl Net<Mocked> {
|
||||||
pub async fn send(&mut self, request: reqwest::RequestBuilder) -> Result<reqwest::Response> {
|
pub async fn send(&mut self, request: reqwest::RequestBuilder) -> Result<reqwest::Response> {
|
||||||
let request = request.build()?;
|
let request = request.build()?;
|
||||||
let index = self.plans.iter().position(|plan| {
|
let index = self.plans.iter().position(|plan| {
|
||||||
// TODO: add support or only matching on selected criteria
|
// METHOD
|
||||||
|
(if plan.match_on.contains(&MatchOn::Method) {
|
||||||
plan.request.method() == request.method()
|
plan.request.method() == request.method()
|
||||||
&& plan.request.url() == request.url()
|
} else {
|
||||||
&& match (plan.request.body(), request.body()) {
|
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,
|
(None, None) => true,
|
||||||
(Some(plan), Some(request)) => plan.as_bytes() == request.as_bytes(),
|
(Some(plan), Some(request)) => plan.as_bytes() == request.as_bytes(),
|
||||||
_ => false,
|
_ => 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 {
|
match index {
|
||||||
Some(i) => Ok(self.plans.remove(i).response),
|
Some(i) => Ok(self.plans.remove(i).response),
|
||||||
|
@ -70,11 +98,24 @@ impl Net<Mocked> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on(&mut self, request: reqwest::Request) -> OnRequest {
|
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) {
|
fn _on(
|
||||||
self.plans.push(Plan { request, response })
|
&mut self,
|
||||||
|
request: reqwest::Request,
|
||||||
|
response: reqwest::Response,
|
||||||
|
match_on: Vec<MatchOn>,
|
||||||
|
) {
|
||||||
|
self.plans.push(Plan {
|
||||||
|
request,
|
||||||
|
response,
|
||||||
|
match_on,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<T: NetType> Drop for Net<T> {
|
impl<T: NetType> Drop for Net<T> {
|
||||||
|
@ -86,9 +127,13 @@ impl<T: NetType> Drop for Net<T> {
|
||||||
pub struct OnRequest<'net> {
|
pub struct OnRequest<'net> {
|
||||||
net: &'net mut Net<Mocked>,
|
net: &'net mut Net<Mocked>,
|
||||||
request: reqwest::Request,
|
request: reqwest::Request,
|
||||||
|
match_on: Vec<MatchOn>,
|
||||||
}
|
}
|
||||||
impl<'net> OnRequest<'net> {
|
impl<'net> OnRequest<'net> {
|
||||||
|
pub fn match_on(self, match_on: Vec<MatchOn>) -> Self {
|
||||||
|
Self{net:self.net, request:self.request, match_on}
|
||||||
|
}
|
||||||
pub fn respond(self, response: reqwest::Response) {
|
pub fn respond(self, response: reqwest::Response) {
|
||||||
self.net._on(self.request, response)
|
self.net._on(self.request, response, self.match_on)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
36
tests/net.rs
36
tests/net.rs
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
use kxio::net::Error;
|
use kxio::net::{Error, MatchOn};
|
||||||
|
|
||||||
type TestResult = Result<(), Error>;
|
type TestResult = Result<(), Error>;
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ async fn test_get() -> TestResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_post() -> TestResult {
|
async fn test_post() {
|
||||||
//given
|
//given
|
||||||
let mut net = kxio::net::mock();
|
let mut net = kxio::net::mock();
|
||||||
let client = net.client();
|
let client = net.client();
|
||||||
|
@ -46,13 +46,41 @@ async fn test_post() -> TestResult {
|
||||||
net.on(request).respond(my_response.into());
|
net.on(request).respond(my_response.into());
|
||||||
|
|
||||||
//when
|
//when
|
||||||
let response = net.send(client.post(url)).await?;
|
let response = net.send(client.post(url)).await.expect("reponse");
|
||||||
|
|
||||||
//then
|
//then
|
||||||
assert_eq!(response.status(), http::StatusCode::OK);
|
assert_eq!(response.status(), http::StatusCode::OK);
|
||||||
assert_eq!(response.bytes().await.expect("response body"), "Post 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]
|
#[tokio::test]
|
||||||
|
|
Loading…
Reference in a new issue