use hurl_core::ast::{MultilineString, MultilineStringKind};
use hurl_core::types::ToSource;
use serde_json::json;
use super::error::RunnerError;
use super::json::eval_json_value;
use super::template::eval_template;
use super::variable::VariableSet;
pub fn eval_multiline(
multiline: &MultilineString,
variables: &VariableSet,
) -> Result<String, RunnerError> {
match &multiline.kind {
MultilineStringKind::Text(value)
| MultilineStringKind::Json(value)
| MultilineStringKind::Xml(value) => {
let s = eval_template(value, variables)?;
Ok(s)
}
MultilineStringKind::Raw(value) => {
let s = value.to_source().to_string();
Ok(s)
}
MultilineStringKind::GraphQl(graphql) => {
let query = eval_template(&graphql.value, variables)?;
let body = match &graphql.variables {
None => json!({ "query": query.trim()}).to_string(),
Some(vars) => {
let s = eval_json_value(&vars.value, variables, false)?;
let query = json!(query.trim());
format!(r#"{{"query":{query},"variables":{s}}}"#)
}
};
Ok(body)
}
}
}
#[cfg(test)]
mod tests {
use hurl_core::ast::{
GraphQl, GraphQlVariables, JsonObjectElement, JsonValue, MultilineString,
MultilineStringKind, SourceInfo, Template, TemplateElement, Whitespace,
};
use hurl_core::reader::Pos;
use hurl_core::types::ToSource;
use crate::runner::VariableSet;
use crate::runner::multiline::eval_multiline;
fn whitespace() -> Whitespace {
Whitespace {
value: String::from(" "),
source_info: SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0)),
}
}
fn newline() -> Whitespace {
Whitespace {
value: String::from("\n"),
source_info: SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0)),
}
}
fn empty_source_info() -> SourceInfo {
SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0))
}
#[test]
fn eval_graphql_multiline_simple() {
let query = r#"{
human(id: "1000") {
name
height(unit: FOOT)
}
}"#;
let variables = VariableSet::new();
let multiline = MultilineString {
space: whitespace(),
newline: newline(),
kind: MultilineStringKind::GraphQl(GraphQl {
value: Template::new(
None,
vec![TemplateElement::String {
value: query.to_string(),
source: query.to_source(),
}],
empty_source_info(),
),
variables: None,
}),
};
let body = eval_multiline(&multiline, &variables).unwrap();
assert_eq!(
body,
r#"{"query":"{\n human(id: \"1000\") {\n name\n height(unit: FOOT)\n }\n}"}"#
.to_string()
);
}
#[test]
fn eval_graphql_multiline_with_graphql_variables() {
let query = r#"{
human(id: "1000") {
name
height(unit: FOOT)
}
}"#;
let hurl_variables = VariableSet::new();
let graphql_variables = GraphQlVariables {
space: whitespace(),
value: JsonValue::Object {
space0: String::new(),
elements: vec![
JsonObjectElement {
space0: String::new(),
name: Template::new(
Some('"'),
vec![TemplateElement::String {
value: "episode".to_string(),
source: "episode".to_source(),
}],
empty_source_info(),
),
space1: String::new(),
space2: String::new(),
value: JsonValue::String(Template::new(
Some('"'),
vec![TemplateElement::String {
value: "JEDI".to_string(),
source: "JEDI".to_source(),
}],
empty_source_info(),
)),
space3: String::new(),
},
JsonObjectElement {
space0: String::new(),
name: Template::new(
Some('"'),
vec![TemplateElement::String {
value: "withFriends".to_string(),
source: "withFriends".to_source(),
}],
empty_source_info(),
),
space1: String::new(),
space2: String::new(),
value: JsonValue::Boolean(false),
space3: String::new(),
},
],
},
whitespace: whitespace(),
};
let multiline = MultilineString {
space: whitespace(),
newline: newline(),
kind: MultilineStringKind::GraphQl(GraphQl {
value: Template::new(
None,
vec![TemplateElement::String {
value: query.to_string(),
source: query.to_source(),
}],
empty_source_info(),
),
variables: Some(graphql_variables),
}),
};
let body = eval_multiline(&multiline, &hurl_variables).unwrap();
assert_eq!(body, r#"{"query":"{\n human(id: \"1000\") {\n name\n height(unit: FOOT)\n }\n}","variables":{"episode":"JEDI","withFriends":false}}"#.to_string());
}
}