-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
239 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,6 +46,7 @@ pub fn parse_inputs_to_request_data(input: &CliInput) -> Result<PartialRequestDa | |
.fold(base_request, |req_data, item| { | ||
[ | ||
parsers_request_items::query_param_value, | ||
parsers_request_items::nested_body_value, | ||
parsers_request_items::non_string_body_value, | ||
parsers_request_items::body_value, | ||
parsers_request_items::header_value, | ||
|
@@ -59,6 +60,8 @@ pub fn parse_inputs_to_request_data(input: &CliInput) -> Result<PartialRequestDa | |
} | ||
|
||
mod parsers_request_items { | ||
use serde_json::Map; | ||
|
||
use super::*; | ||
use crate::utils::regexes; | ||
|
||
|
@@ -188,6 +191,74 @@ mod parsers_request_items { | |
|
||
Some(request) | ||
} | ||
|
||
pub fn nested_body_value( | ||
s: &str, | ||
base_request: &PartialRequestData, | ||
) -> Option<PartialRequestData> { | ||
let re = regexes::request_items::body_value(); | ||
let matcher = re.captures(s)?; | ||
|
||
// Key=Value | ||
let key = matcher.name("key")?.as_str(); | ||
let value = matcher.name("value")?.as_str(); | ||
|
||
// Extract the root key and sub keys from "key" input | ||
// ---- | ||
// Key[SubKey1][SubKey2] => Key, [SubKey1, SubKey2] | ||
// ---- | ||
let (root_key, sub_keys) = { | ||
let re = regexes::request_items::nested_body_keys(); | ||
let matcher = re.captures(key)?; | ||
|
||
( | ||
matcher.name("root_key")?.as_str(), | ||
matcher | ||
.name("sub_keys")? | ||
.as_str() | ||
.split(['[', ']']) | ||
.filter(|s| !s.is_empty()) | ||
.collect::<Vec<_>>(), | ||
) | ||
}; | ||
|
||
let mut request = base_request.clone(); | ||
|
||
let mut root_map: Map<String, Value> = match request.body { | ||
Some(BodyPayload::Json(serde_json::Value::Object(v))) => v, | ||
_ => Map::new(), | ||
}; | ||
|
||
let root_value: &mut Value = root_map | ||
.entry(root_key) | ||
.or_insert(Value::Object(Map::new())); | ||
|
||
let target_value: &mut Value = | ||
sub_keys | ||
.iter() | ||
.fold(root_value, |map_value, key| match map_value { | ||
Value::Object(map) => map | ||
.entry(key.to_string()) | ||
.or_insert(Value::Object(Map::new())), | ||
_ => { | ||
*map_value = Value::Object(Map::new()); | ||
match map_value { | ||
Value::Object(map) => map | ||
.entry(key.to_string()) | ||
.or_insert(Value::Object(Map::new())), | ||
_ => unreachable!(), | ||
} | ||
} | ||
}); | ||
|
||
*target_value = serde_json::from_str(value) | ||
.ok() | ||
.unwrap_or(Value::String(value.to_string())); | ||
|
||
request.body = BodyPayload::Json(serde_json::Value::Object(root_map)).into(); | ||
|
||
Some(request) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
|
@@ -358,11 +429,11 @@ pub mod tests_parsers_request_items { | |
#[test] | ||
fn test_body_value_append() { | ||
let input = "password=123"; | ||
let base_request = PartialRequestData::default() | ||
.with_body(r#"{ "email": "[email protected]" }"#.to_string()); | ||
let base_request = | ||
PartialRequestData::default().with_body(r#"{ "email": "[email protected]" }"#); | ||
|
||
let expected_request = PartialRequestData::default() | ||
.with_body(r#"{ "email": "[email protected]", "password": "123" }"#.to_string()); | ||
.with_body(r#"{ "email": "[email protected]", "password": "123" }"#); | ||
|
||
assert_eq!( | ||
Some(expected_request), | ||
|
@@ -374,10 +445,10 @@ pub mod tests_parsers_request_items { | |
fn test_body_value_append_overwrite() { | ||
let input = "password=123456"; | ||
let base_request = PartialRequestData::default() | ||
.with_body(r#"{ "email": "[email protected]", "password": "123" }"#.to_string()); | ||
.with_body(r#"{ "email": "[email protected]", "password": "123" }"#); | ||
|
||
let expected_request = PartialRequestData::default() | ||
.with_body(r#"{ "email": "[email protected]", "password": "123456" }"#.to_string()); | ||
.with_body(r#"{ "email": "[email protected]", "password": "123456" }"#); | ||
|
||
assert_eq!( | ||
Some(expected_request), | ||
|
@@ -395,24 +466,101 @@ pub mod tests_parsers_request_items { | |
|
||
for request in base_requests { | ||
let expected_request = | ||
PartialRequestData::default().with_body(r#"{ "password": "123" }"#.to_string()); | ||
PartialRequestData::default().with_body(r#"{ "password": "123" }"#); | ||
assert_eq!( | ||
Some(expected_request), | ||
parsers_request_items::body_value(input, &request) | ||
) | ||
} | ||
} | ||
#[test] | ||
|
||
#[test] | ||
fn test_body_value_with_base_body_none() { | ||
let input = "password=123"; | ||
let base_request = PartialRequestData::default(); | ||
|
||
let expected_request = | ||
PartialRequestData::default().with_body(r#"{ "password": "123" }"#.to_string()); | ||
let expected_request = PartialRequestData::default().with_body(r#"{ "password": "123" }"#); | ||
assert_eq!( | ||
Some(expected_request), | ||
parsers_request_items::body_value(input, &base_request) | ||
) | ||
} | ||
|
||
#[test] | ||
fn test_nested_body_value_basic() { | ||
let cases = [ | ||
("user[name]=John", r#"{ "user": { "name": "John"} }"#), | ||
( | ||
"user[name][first]=John", | ||
r#"{ "user": { "name": { "first": "John"} } }"#, | ||
), | ||
]; | ||
|
||
for (input, expected_json_output) in cases { | ||
let base_request = PartialRequestData::default(); | ||
let expected_request = PartialRequestData::default().with_body(expected_json_output); | ||
assert_eq!( | ||
Some(expected_request), | ||
parsers_request_items::nested_body_value(input, &base_request) | ||
) | ||
} | ||
} | ||
|
||
#[test] | ||
fn test_nested_body_value_overwriting_fields() { | ||
// 1. appending in a nested object | ||
let input = "user[name]=John"; | ||
let base_json = r#"{ "user": {} }"#; | ||
let expected_output_json = r#"{ "user": { "name": "John" } }"#; | ||
let base_request = PartialRequestData::default().with_body(base_json); | ||
let expected_request = PartialRequestData::default().with_body(expected_output_json); | ||
assert_eq!( | ||
Some(expected_request), | ||
parsers_request_items::nested_body_value(input, &base_request) | ||
); | ||
|
||
// 2. overwriting existing field | ||
let input = "user[name]=Mary"; | ||
let base_json = r#"{ "user": { "name": "John" } }"#; | ||
let expected_output_json = r#"{ "user": { "name": "Mary" } }"#; | ||
let base_request = PartialRequestData::default().with_body(base_json); | ||
let expected_request = PartialRequestData::default().with_body(expected_output_json); | ||
assert_eq!( | ||
Some(expected_request), | ||
parsers_request_items::nested_body_value(input, &base_request) | ||
); | ||
|
||
// 3. appending in a nested object with another fields | ||
let input = "user[name][first]=John"; | ||
let base_json = r#"{ "user": { "name": { "last": "Doe"} } }"#; | ||
let expected_output_json = r#"{ "user": { "name": { "first": "John", "last": "Doe"} } }"#; | ||
let base_request = PartialRequestData::default().with_body(base_json); | ||
let expected_request = PartialRequestData::default().with_body(expected_output_json); | ||
assert_eq!( | ||
Some(expected_request), | ||
parsers_request_items::nested_body_value(input, &base_request) | ||
); | ||
|
||
// 4. replacing fields to object | ||
let input = "user[name]=Mary"; | ||
let base_json = r#"{ "user": "a-string-to-be-replaced" }"#; | ||
let expected_output_json = r#"{ "user": { "name": "Mary" } }"#; | ||
let base_request = PartialRequestData::default().with_body(base_json); | ||
let expected_request = PartialRequestData::default().with_body(expected_output_json); | ||
assert_eq!( | ||
Some(expected_request), | ||
parsers_request_items::nested_body_value(input, &base_request) | ||
); | ||
|
||
// 5. replacing fields to nested object | ||
let input = "user[name][first]=John"; | ||
let base_json = r#"{ "user": "a-string-to-be-replaced" }"#; | ||
let expected_output_json = r#"{ "user": { "name": { "first": "John" } } }"#; | ||
let base_request = PartialRequestData::default().with_body(base_json); | ||
let expected_request = PartialRequestData::default().with_body(expected_output_json); | ||
assert_eq!( | ||
Some(expected_request), | ||
parsers_request_items::nested_body_value(input, &base_request) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
...ts/r#mod__view__map_input_to_commands__should_parse_body_values_with_nested_json_too.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--- | ||
source: tests/view/map_input_to_commands.rs | ||
expression: output.unwrap() | ||
--- | ||
- SubmitRequest: | ||
request: | ||
url: | ||
ValidatedUrl: | ||
protocol: ~ | ||
host: url.com | ||
port: ~ | ||
paths: [] | ||
query_params: [] | ||
anchor: ~ | ||
method: POST | ||
headers: {} | ||
body: | ||
Json: | ||
id: "1" | ||
type: user | ||
user: | ||
address: | ||
city: NY | ||
age: 30 | ||
name: John | ||
|