diff options
author | Guillaume Pasquet <dev@etenil.net> | 2022-03-07 00:06:29 +0000 |
---|---|---|
committer | Guillaume Pasquet <dev@etenil.net> | 2022-03-07 00:06:29 +0000 |
commit | a77bf71866ffb3f3d4d0547d822092d5f287df43 (patch) | |
tree | 39a7b16ec1eb0a1a8ebc0eeb47e5bd5b2c29d713 | |
parent | 57af17cfa6e08a6fe9bf6d73d401af17dccfa3bb (diff) |
Fix/14 parse all variables
-rw-r--r-- | src/barbfile.rs | 60 | ||||
-rw-r--r-- | src/executor.rs | 67 | ||||
-rw-r--r-- | src/main.rs | 11 |
3 files changed, 103 insertions, 35 deletions
diff --git a/src/barbfile.rs b/src/barbfile.rs index f3cb58f..858d035 100644 --- a/src/barbfile.rs +++ b/src/barbfile.rs @@ -1,11 +1,10 @@ +use jsonpath_rust::JsonPathQuery; use regex::Regex; +use serde_json::Value; use std::str::FromStr; use std::string::ToString; use std::{error::Error, fmt}; -use jsonpath_rust::JsonPathQuery; -use serde_json::{json, Value}; - #[cfg(feature = "jq")] use jq_rs; @@ -157,12 +156,20 @@ impl BarbFilter { #[cfg(feature = "jq")] fn apply_jq(&self, body: &String) -> Result<String, String> { + if let FilterType::JQ = self.filter_type { + return Err(String::from("Incorrect filter type")); + } + jq_rs::run(self.filter.as_str(), body.as_str()) .map_err(|x| x.to_string()) .map(|x| String::from(x.trim().trim_matches('"'))) } fn apply_path(&self, body: &String) -> Result<String, String> { + if let FilterType::JQ = self.filter_type { + return Err(String::from("Incorrect filter type")); + } + let json: Value = serde_json::from_str(body.as_str()) .map_err(|_| String::from("Failed to decode body"))?; let path = &json.path(self.filter.as_str())?; @@ -300,7 +307,6 @@ mod tests { #[test] fn test_method_from_str() { assert!(matches!(Method::from_str("GET").unwrap(), Method::GET)); - assert!(matches!(Method::from_str("GET").unwrap(), Method::GET)); assert!(matches!(Method::from_str("PUT").unwrap(), Method::PUT)); assert!(matches!(Method::from_str("POST").unwrap(), Method::POST)); assert!(matches!(Method::from_str("PATCH").unwrap(), Method::PATCH)); @@ -311,6 +317,15 @@ mod tests { } #[test] + fn test_method_takes_body() { + assert!(!Method::GET.takes_body()); + assert!(Method::PUT.takes_body()); + assert!(Method::POST.takes_body()); + assert!(Method::PATCH.takes_body()); + assert!(!Method::DELETE.takes_body()); + } + + #[test] fn test_decode_url_line() { let (method, url) = decode_url_line("#GET^http://blahblah").unwrap(); assert!(matches!(method, Method::GET)); @@ -359,16 +374,49 @@ mod tests { } #[test] - fn test_parse_named_filter() { + fn test_jq_parse_named_filter() { let filter = BarbFilter::from_str("#FOO|.bar.foo").unwrap(); assert_eq!(filter.name, Some(String::from("FOO"))); assert_eq!(filter.filter, String::from(".bar.foo")); + assert!(matches!(filter.filter_type, FilterType::JQ)); } #[test] - fn test_parse_named_filter_no_name() { + fn test_jq_parse_named_filter_no_name() { let filter = BarbFilter::from_str("#|.bar.foo").unwrap(); assert_eq!(filter.name, None); assert_eq!(filter.filter, String::from(".bar.foo")); + assert!(matches!(filter.filter_type, FilterType::JQ)); + } + + #[test] + fn test_path_parse_named_filter() { + let filter = BarbFilter::from_str("#FOO$$.bar.foo").unwrap(); + assert_eq!(filter.name, Some(String::from("FOO"))); + assert_eq!(filter.filter, String::from("$.bar.foo")); + assert!(matches!(filter.filter_type, FilterType::PATH)); + } + + #[test] + fn test_path_parse_named_filter_no_name() { + let filter = BarbFilter::from_str("#$$.bar.foo").unwrap(); + assert_eq!(filter.name, None); + assert_eq!(filter.filter, String::from("$.bar.foo")); + assert!(matches!(filter.filter_type, FilterType::PATH)); + } + + #[cfg(feature = "jq")] + #[test] + fn test_apply_filter_jq() { + let jq_f = BarbFilter::from_str("#|.status").unwrap(); + let subject = String::from(r#"{"status": "OK"}"#); + assert_eq!(jq_f.apply(&subject).unwrap(), String::from("OK")); + } + + #[test] + fn test_apply_filter_path() { + let path_f = BarbFilter::from_str("#$$.status").unwrap(); + let subject = String::from(r#"{"status": "OK"}"#); + assert_eq!(path_f.apply(&subject).unwrap(), String::from("OK")); } } diff --git a/src/executor.rs b/src/executor.rs index eccab39..54ca491 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -1,12 +1,11 @@ use crate::barbfile::{BarbFile, BarbFilter}; use crate::output::BarbOutput; - +use regex::Regex; use std::collections::HashMap; -use ureq; -use ureq::Error as UreqError; - use std::fs; use std::str::FromStr; +use ureq; +use ureq::Error as UreqError; pub struct Context { vars: HashMap<String, String>, @@ -30,22 +29,20 @@ impl Context { } } - // Preserved for future reference - // pub fn get_var(&self, name: String) -> Option<String> { - // self.vars - // .get(&name) - // .map(|val| val.clone()) - // .or_else(|| env::var(name).ok()) - // } - fn key_str(&self, key: &String) -> String { format!("{{{}}}", key) } pub fn substitute(&self, string: &String) -> String { let mut buffer = string.clone(); - for (key, val) in self.vars.iter() { - buffer = buffer.replace(self.key_str(key).as_str(), val); + let re = Regex::new(r"\{([A-Za-z0-9_]+)\}").unwrap(); + + for var in re.captures_iter(string) { + let key = String::from(&var[1]); + buffer = buffer.replace( + self.key_str(&key).as_str(), + self.vars.get(&key).or(Some(&String::from(""))).unwrap(), + ); } buffer @@ -150,11 +147,16 @@ impl Executor { } } -// TODO: tests #[cfg(test)] -mod tests { +mod tests_context { use super::*; - use std::str::FromStr; + + fn have_vars() -> Vec<(String, String)> { + return vec![ + (String::from("foo"), String::from("bar")), + (String::from("bar"), String::from("baz")), + ]; + } #[test] fn test_context_key_str() { @@ -164,20 +166,43 @@ mod tests { #[test] fn test_context_substitute() { - let vars: Vec<(String, String)> = vec![ - (String::from("foo"), String::from("bar")), - (String::from("bar"), String::from("baz")), - ]; + let vars = have_vars(); let ctx = Context::new(vars.into_iter()); assert_eq!( ctx.substitute(&String::from("blah blah {foo} blah")), String::from("blah blah bar blah") ); + } + + #[test] + fn test_context_substitute_multi() { + let vars = have_vars(); + let ctx = Context::new(vars.into_iter()); assert_eq!( ctx.substitute(&String::from("blah {foo} {bar} blah")), String::from("blah bar baz blah") ); + assert_eq!( + ctx.substitute(&String::from("blah {bar} {foo} blah")), + String::from("blah baz bar blah") + ); + } + + #[test] + fn test_context_substitute_missing() { + let vars: Vec<(String, String)> = vec![]; + let ctx = Context::new(vars.into_iter()); + assert_eq!( + ctx.substitute(&String::from("blah blah {foo} blah")), + String::from("blah blah blah") + ); } +} + +#[cfg(test)] +mod tests_make_req { + use super::*; + use std::str::FromStr; #[test] fn test_make_req_simple_get() { diff --git a/src/main.rs b/src/main.rs index 1738391..6dfb7d3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,17 +1,12 @@ mod barbfile; mod executor; mod output; - -use std::slice::Iter; - +use clap::Parser; +use dotenv::dotenv; use executor::{Context, Executor}; use output::BarbOutput; - -use clap::Parser; - use std::env; - -use dotenv::dotenv; +use std::slice::Iter; #[derive(Parser, Debug)] #[clap(version)] |