Skip to content

Commit f705eb6

Browse files
committed
Adding Form Body
1 parent 860e75e commit f705eb6

File tree

5 files changed

+69
-3
lines changed

5 files changed

+69
-3
lines changed

mocktail/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ prost = "0.14"
2828
rand = "0.9"
2929
serde = "1"
3030
serde_json = "1"
31+
serde_urlencoded = "0.7"
3132
thiserror = "2"
3233
tokio = "1"
3334
tokio-stream = "0"

mocktail/src/form.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use crate::body::Body;
2+
3+
/// The body of a mock request or response as a form.
4+
#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
5+
pub struct FormBody {
6+
fields: Vec<(String, String)>,
7+
}
8+
9+
impl FormBody {
10+
/// Creates an empty form.
11+
pub fn empty() -> Self {
12+
Self::default()
13+
}
14+
15+
/// Adds a field to the form.
16+
pub fn add_field(&mut self, name: impl Into<String>, value: impl Into<String>) {
17+
self.fields.push((name.into(), value.into()));
18+
}
19+
20+
/// Converts the form body to a URL-encoded string.
21+
pub fn url_encoded(&self) -> String {
22+
self.fields
23+
.iter()
24+
.map(|(k, v)| format!("{k}={v}"))
25+
.collect::<Vec<_>>()
26+
.join("&")
27+
}
28+
}
29+
30+
impl PartialEq<Body> for FormBody {
31+
fn eq(&self, other: &Body) -> bool {
32+
let mut body_copy = other.clone();
33+
let other_form_body =
34+
serde_urlencoded::from_bytes::<Vec<(String, String)>>(&body_copy.as_bytes());
35+
36+
match other_form_body {
37+
Ok(other) => self.fields == other,
38+
Err(_) => false,
39+
}
40+
}
41+
}

mocktail/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub mod prelude {
3030
}
3131
mod ext;
3232
mod service;
33+
mod form;
3334

3435
/// Represents errors that can occur while serving mocks.
3536
#[derive(thiserror::Error, Debug)]

mocktail/src/matchers.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use std::{any::Any, borrow::Cow, cmp::Ordering};
33

44
use super::{body::Body, headers::Headers, request::Request};
5-
use crate::request::Method;
5+
use crate::{form::FormBody, request::Method};
66

77
/// A matcher.
88
pub trait Matcher: std::fmt::Debug + Send + Sync + 'static + AsMatcherEq {
@@ -97,6 +97,23 @@ pub fn body(body: Body) -> BodyMatcher {
9797
BodyMatcher(body)
9898
}
9999

100+
/// Form body matcher.
101+
#[derive(Debug, PartialEq, PartialOrd)]
102+
pub struct FormMatcher(FormBody);
103+
104+
impl Matcher for FormMatcher {
105+
fn name(&self) -> &str {
106+
"form_body"
107+
}
108+
fn matches(&self, req: &Request) -> bool {
109+
self.0 == req.body
110+
}
111+
}
112+
113+
pub fn form(body: FormBody) -> FormMatcher {
114+
FormMatcher(body)
115+
}
116+
100117
/// Headers matcher.
101118
#[derive(Debug, PartialEq, PartialOrd)]
102119
pub struct HeadersMatcher(Headers);

mocktail/src/mock_builder/when.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ use bytes::Bytes;
55

66
use crate::{
77
body::Body,
8+
form::FormBody,
89
headers::{HeaderName, HeaderValue, Headers},
9-
matchers,
10-
matchers::Matcher,
10+
matchers::{self, Matcher},
1111
request::Method,
1212
};
1313

@@ -66,6 +66,12 @@ impl When {
6666
self
6767
}
6868

69+
/// Form Body.
70+
pub fn form(self, body: FormBody) -> Self {
71+
self.push(matchers::form(body));
72+
self
73+
}
74+
6975
/// Headers.
7076
///
7177
/// Cannonicalizes passed in header name and values to ensure matching is done in a

0 commit comments

Comments
 (0)