diff options
| -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)] | 
