aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Pasquet <dev@etenil.net>2022-03-07 00:06:29 +0000
committerGuillaume Pasquet <dev@etenil.net>2022-03-07 00:06:29 +0000
commite2b8352d597a1e52db99abf3dc822f25428f7ea0 (patch)
tree39a7b16ec1eb0a1a8ebc0eeb47e5bd5b2c29d713
parent57af17cfa6e08a6fe9bf6d73d401af17dccfa3bb (diff)
parenta77bf71866ffb3f3d4d0547d822092d5f287df43 (diff)
Merge branch 'fix/14-parse-all-variables' into 'main'
Fix/14 parse all variables Closes #14 See merge request guillaume54/barb!1
-rw-r--r--src/barbfile.rs60
-rw-r--r--src/executor.rs67
-rw-r--r--src/main.rs11
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)]