Skip to content

Commit

Permalink
Merge pull request #479 from tienvx/apply-generators-for-form-urlencoded
Browse files Browse the repository at this point in the history
feat(pact_matching): Apply generators for form urlencoded
  • Loading branch information
rholshausen authored Dec 19, 2024
2 parents a7303e6 + b1cb2d5 commit c1bf98e
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 2 deletions.
3 changes: 2 additions & 1 deletion rust/pact_matching/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ exclude = [
]

[features]
default = ["datetime", "xml", "plugins", "multipart"]
default = ["datetime", "xml", "plugins", "multipart", "form_urlencoded"]
datetime = ["pact_models/datetime", "pact-plugin-driver?/datetime", "dep:chrono"] # Support for date/time matchers and expressions
xml = ["pact_models/xml", "pact-plugin-driver?/xml", "dep:sxd-document"] # support for matching XML documents
plugins = ["dep:pact-plugin-driver"]
multipart = ["dep:multer"] # suport for MIME multipart bodies
form_urlencoded = ["pact_models/form_urlencoded"] # suport for matching form urlencoded

[dependencies]
ansi_term = "0.12.1"
Expand Down
51 changes: 50 additions & 1 deletion rust/pact_matching/src/generators/bodies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ use pact_models::plugins::PluginData;

#[cfg(feature = "xml")] use crate::generators::XmlHandler;

#[cfg(feature = "form_urlencoded")] use pact_models::generators::form_urlencoded::FormUrlEncodedHandler;

/// Apply the generators to the body, returning a new body
#[allow(unused_variables)]
pub async fn generators_process_body(
Expand Down Expand Up @@ -67,6 +69,30 @@ pub async fn generators_process_body(
warn!("Generating XML documents requires the xml feature to be enabled");
Ok(body.clone())
}
} else if content_type.is_form_urlencoded() {
debug!("apply_body_generators: FORM URLENCODED content type");
#[cfg(feature = "form_urlencoded")]
{
let result: Result<Vec<(String, String)>, serde_urlencoded::de::Error> = serde_urlencoded::from_bytes(&body.value().unwrap_or_default());
match result {
Ok(val) => {
let mut handler = FormUrlEncodedHandler { params: val };
Ok(handler.process_body(generators, mode, context, &matcher.boxed()).unwrap_or_else(|err| {
error!("Failed to generate the body: {}", err);
body.clone()
}))
},
Err(err) => {
error!("Failed to parse the body, so not applying any generators: {}", err);
Ok(body.clone())
}
}
}
#[cfg(not(feature = "form_urlencoded"))]
{
warn!("Generating FORM URLENCODED query string requires the form_urlencoded feature to be enabled");
Ok(body.clone())
}
}
else {
#[cfg(feature = "plugins")]
Expand Down Expand Up @@ -97,9 +123,11 @@ mod tests {
use expectest::prelude::*;
use maplit::hashmap;

use pact_models::generators::Generator;
use pact_models::bodies::OptionalBody;
use pact_models::content_types::{JSON, TEXT};
use pact_models::content_types::{JSON, TEXT, XML, FORM_URLENCODED};
use pact_models::generators::GeneratorTestMode;
use pact_models::path_exp::DocPath;

use super::generators_process_body;
use crate::DefaultVariantMatcher;
Expand Down Expand Up @@ -131,4 +159,25 @@ mod tests {
expect!(generators_process_body(&GeneratorTestMode::Provider, &body, Some(TEXT.clone()),
&hashmap!{}, &hashmap!{}, &DefaultVariantMatcher{}, &vec![], &hashmap!{}).await.unwrap()).to(be_equal_to(body));
}

#[tokio::test]
async fn apply_generator_to_json_body_test() {
let body = OptionalBody::Present("{\"a\":100}".into(), None, None);
expect!(generators_process_body(&GeneratorTestMode::Provider, &body, Some(JSON.clone()),
&hashmap!{}, &hashmap!{DocPath::new_unwrap("$.a") => Generator::RandomInt(0, 10)}, &DefaultVariantMatcher{}, &vec![], &hashmap!{}).await.unwrap()).to_not(be_equal_to(body));
}

#[tokio::test]
async fn do_not_apply_generator_to_xml_body_because_unimplemented() {
let body = OptionalBody::Present("<a>100</a>".into(), None, None);
expect!(generators_process_body(&GeneratorTestMode::Provider, &body, Some(XML.clone()),
&hashmap!{}, &hashmap!{DocPath::new_unwrap("$.name") => Generator::RandomInt(0, 10)}, &DefaultVariantMatcher{}, &vec![], &hashmap!{}).await.unwrap()).to(be_equal_to(body));
}

#[tokio::test]
async fn apply_generator_to_form_urlencoded_body_test() {
let body = OptionalBody::Present("a=100".into(), None, None);
expect!(generators_process_body(&GeneratorTestMode::Provider, &body, Some(FORM_URLENCODED.clone()),
&hashmap!{}, &hashmap!{DocPath::new_unwrap("$.a") => Generator::RandomInt(0, 10)}, &DefaultVariantMatcher{}, &vec![], &hashmap!{}).await.unwrap()).to_not(be_equal_to(body));
}
}

0 comments on commit c1bf98e

Please sign in to comment.