feat(render): add variable injection mechanism to renderer #856
This commit is contained in:
parent
9a2c27a202
commit
40e8dace33
|
@ -17,14 +17,11 @@
|
||||||
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::renderer::VAR_REGEX;
|
|
||||||
use log::error;
|
use log::error;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::{
|
use crate::{Extension, ExtensionOutput, ExtensionResult, Params, Value};
|
||||||
renderer::render_variables, Extension, ExtensionOutput, ExtensionResult, Params, Value,
|
|
||||||
};
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref EMPTY_PARAMS: Params = Params::new();
|
static ref EMPTY_PARAMS: Params = Params::new();
|
||||||
|
@ -59,7 +56,7 @@ impl<'a> Extension for FormExtension<'a> {
|
||||||
fn calculate(
|
fn calculate(
|
||||||
&self,
|
&self,
|
||||||
_: &crate::Context,
|
_: &crate::Context,
|
||||||
scope: &crate::Scope,
|
_: &crate::Scope,
|
||||||
params: &Params,
|
params: &Params,
|
||||||
) -> crate::ExtensionResult {
|
) -> crate::ExtensionResult {
|
||||||
let layout = if let Some(Value::String(layout)) = params.get("layout") {
|
let layout = if let Some(Value::String(layout)) = params.get("layout") {
|
||||||
|
@ -68,15 +65,12 @@ impl<'a> Extension for FormExtension<'a> {
|
||||||
return crate::ExtensionResult::Error(FormExtensionError::MissingLayout.into());
|
return crate::ExtensionResult::Error(FormExtensionError::MissingLayout.into());
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut fields = if let Some(Value::Object(fields)) = params.get("fields") {
|
let fields = if let Some(Value::Object(fields)) = params.get("fields") {
|
||||||
fields.clone()
|
fields.clone()
|
||||||
} else {
|
} else {
|
||||||
Params::new()
|
Params::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Inject scope variables into fields (if needed)
|
|
||||||
inject_scope(&mut fields, scope);
|
|
||||||
|
|
||||||
match self.provider.show(layout, &fields, &EMPTY_PARAMS) {
|
match self.provider.show(layout, &fields, &EMPTY_PARAMS) {
|
||||||
FormProviderResult::Success(values) => {
|
FormProviderResult::Success(values) => {
|
||||||
ExtensionResult::Success(ExtensionOutput::Multiple(values))
|
ExtensionResult::Success(ExtensionOutput::Multiple(values))
|
||||||
|
@ -87,25 +81,6 @@ impl<'a> Extension for FormExtension<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test
|
|
||||||
fn inject_scope(fields: &mut HashMap<String, Value>, scope: &HashMap<&str, ExtensionOutput>) {
|
|
||||||
for value in fields.values_mut() {
|
|
||||||
if let Value::Object(field_options) = value {
|
|
||||||
if let Some(Value::String(default_value)) = field_options.get_mut("default") {
|
|
||||||
if VAR_REGEX.is_match(default_value) {
|
|
||||||
match render_variables(default_value, scope) {
|
|
||||||
Ok(rendered) => *default_value = rendered,
|
|
||||||
Err(err) => error!(
|
|
||||||
"error while injecting variable in form default value: {}",
|
|
||||||
err
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum FormExtensionError {
|
pub enum FormExtensionError {
|
||||||
#[error("missing layout parameter")]
|
#[error("missing layout parameter")]
|
||||||
|
|
|
@ -98,6 +98,7 @@ impl Default for Template {
|
||||||
pub struct Variable {
|
pub struct Variable {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub var_type: String,
|
pub var_type: String,
|
||||||
|
pub inject_vars: bool,
|
||||||
pub params: Params,
|
pub params: Params,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +107,7 @@ impl Default for Variable {
|
||||||
Self {
|
Self {
|
||||||
name: "".to_string(),
|
name: "".to_string(),
|
||||||
var_type: "".to_string(),
|
var_type: "".to_string(),
|
||||||
|
inject_vars: true,
|
||||||
params: Params::new(),
|
params: Params::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of esp name: (), var_type: (), params: ()anso.
|
* This file is part of espanso.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2019-2021 Federico Terzi
|
* Copyright (C) 2019-2021 Federico Terzi
|
||||||
*
|
*
|
||||||
|
@ -17,18 +17,22 @@
|
||||||
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
|
collections::{HashMap, HashSet},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
CasingStyle, Context, Extension, ExtensionOutput, ExtensionResult, RenderOptions, RenderResult,
|
CasingStyle, Context, Extension, ExtensionOutput, ExtensionResult, RenderOptions, RenderResult,
|
||||||
Renderer, Scope, Template, Value, Variable,
|
Renderer, Scope, Template, Value, Variable,
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
|
||||||
use log::{error, warn};
|
use log::{error, warn};
|
||||||
use regex::{Captures, Regex};
|
use regex::{Captures, Regex};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use util::get_body_variable_names;
|
use util::get_body_variable_names;
|
||||||
|
|
||||||
|
use self::util::{inject_variables_into_params, render_variables};
|
||||||
|
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
@ -123,7 +127,22 @@ impl<'a> Renderer for DefaultRenderer<'a> {
|
||||||
return RenderResult::Error(RendererError::MissingSubMatch.into());
|
return RenderResult::Error(RendererError::MissingSubMatch.into());
|
||||||
}
|
}
|
||||||
} else if let Some(extension) = self.extensions.get(&variable.var_type) {
|
} else if let Some(extension) = self.extensions.get(&variable.var_type) {
|
||||||
match extension.calculate(context, &scope, &variable.params) {
|
let variable_params = if variable.inject_vars {
|
||||||
|
match inject_variables_into_params(&variable.params, &scope) {
|
||||||
|
Ok(augmented_params) => Cow::Owned(augmented_params),
|
||||||
|
Err(err) => {
|
||||||
|
error!(
|
||||||
|
"unable to inject variables into params of variable '{}': {}",
|
||||||
|
variable.name, err
|
||||||
|
);
|
||||||
|
return RenderResult::Error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Cow::Borrowed(&variable.params)
|
||||||
|
};
|
||||||
|
|
||||||
|
match extension.calculate(context, &scope, &variable_params) {
|
||||||
ExtensionResult::Success(output) => {
|
ExtensionResult::Success(output) => {
|
||||||
scope.insert(&variable.name, output);
|
scope.insert(&variable.name, output);
|
||||||
}
|
}
|
||||||
|
@ -192,52 +211,6 @@ impl<'a> Renderer for DefaultRenderer<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test
|
|
||||||
pub(crate) fn render_variables(body: &str, scope: &Scope) -> Result<String> {
|
|
||||||
let mut replacing_error = None;
|
|
||||||
let output = VAR_REGEX
|
|
||||||
.replace_all(body, |caps: &Captures| {
|
|
||||||
let var_name = caps.name("name").unwrap().as_str();
|
|
||||||
let var_subname = caps.name("subname");
|
|
||||||
match scope.get(var_name) {
|
|
||||||
Some(output) => match output {
|
|
||||||
ExtensionOutput::Single(output) => output,
|
|
||||||
ExtensionOutput::Multiple(results) => match var_subname {
|
|
||||||
Some(var_subname) => {
|
|
||||||
let var_subname = var_subname.as_str();
|
|
||||||
results.get(var_subname).map_or("", |value| &*value)
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
error!(
|
|
||||||
"nested name missing from multi-value variable: {}",
|
|
||||||
var_name
|
|
||||||
);
|
|
||||||
replacing_error = Some(RendererError::MissingVariable(format!(
|
|
||||||
"nested name missing from multi-value variable: {}",
|
|
||||||
var_name
|
|
||||||
)));
|
|
||||||
""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
replacing_error = Some(RendererError::MissingVariable(format!(
|
|
||||||
"variable '{}' is missing",
|
|
||||||
var_name
|
|
||||||
)));
|
|
||||||
""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.to_string();
|
|
||||||
|
|
||||||
if let Some(error) = replacing_error {
|
|
||||||
return Err(error.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(output)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_matching_template<'a>(
|
fn get_matching_template<'a>(
|
||||||
variable: &Variable,
|
variable: &Variable,
|
||||||
templates: &'a [&Template],
|
templates: &'a [&Template],
|
||||||
|
@ -324,6 +297,7 @@ mod tests {
|
||||||
params: vec![("echo".to_string(), Value::String((*value).to_string()))]
|
params: vec![("echo".to_string(), Value::String((*value).to_string()))]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<Params>(),
|
.collect::<Params>(),
|
||||||
|
..Default::default()
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
Template {
|
Template {
|
||||||
|
@ -415,6 +389,7 @@ mod tests {
|
||||||
"echo".to_string(),
|
"echo".to_string(),
|
||||||
Value::String("world".to_string()),
|
Value::String("world".to_string()),
|
||||||
)]),
|
)]),
|
||||||
|
..Default::default()
|
||||||
}],
|
}],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
@ -435,6 +410,7 @@ mod tests {
|
||||||
params: vec![("echo".to_string(), Value::String("Bob".to_string()))]
|
params: vec![("echo".to_string(), Value::String("Bob".to_string()))]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<Params>(),
|
.collect::<Params>(),
|
||||||
|
..Default::default()
|
||||||
},
|
},
|
||||||
Variable {
|
Variable {
|
||||||
name: "var".to_string(),
|
name: "var".to_string(),
|
||||||
|
@ -454,6 +430,7 @@ mod tests {
|
||||||
"read".to_string(),
|
"read".to_string(),
|
||||||
Value::String("local".to_string()),
|
Value::String("local".to_string()),
|
||||||
)]),
|
)]),
|
||||||
|
..Default::default()
|
||||||
}],
|
}],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
@ -473,6 +450,7 @@ mod tests {
|
||||||
params: vec![("trigger".to_string(), Value::String("nested".to_string()))]
|
params: vec![("trigger".to_string(), Value::String("nested".to_string()))]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<Params>(),
|
.collect::<Params>(),
|
||||||
|
..Default::default()
|
||||||
}],
|
}],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
@ -503,6 +481,7 @@ mod tests {
|
||||||
params: vec![("trigger".to_string(), Value::String("nested".to_string()))]
|
params: vec![("trigger".to_string(), Value::String("nested".to_string()))]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<Params>(),
|
.collect::<Params>(),
|
||||||
|
..Default::default()
|
||||||
}],
|
}],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
@ -527,6 +506,7 @@ mod tests {
|
||||||
params: vec![("abort".to_string(), Value::Null)]
|
params: vec![("abort".to_string(), Value::Null)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<Params>(),
|
.collect::<Params>(),
|
||||||
|
..Default::default()
|
||||||
}],
|
}],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
@ -545,10 +525,93 @@ mod tests {
|
||||||
params: vec![("error".to_string(), Value::Null)]
|
params: vec![("error".to_string(), Value::Null)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<Params>(),
|
.collect::<Params>(),
|
||||||
|
..Default::default()
|
||||||
}],
|
}],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let res = renderer.render(&template, &Default::default(), &Default::default());
|
let res = renderer.render(&template, &Default::default(), &Default::default());
|
||||||
assert!(matches!(res, RenderResult::Error(_)));
|
assert!(matches!(res, RenderResult::Error(_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn variable_injection() {
|
||||||
|
let renderer = get_renderer();
|
||||||
|
let mut template = template_for_str("hello {{fullname}}");
|
||||||
|
template.vars = vec![
|
||||||
|
Variable {
|
||||||
|
name: "firstname".to_string(),
|
||||||
|
var_type: "mock".to_string(),
|
||||||
|
params: Params::from_iter(vec![(
|
||||||
|
"echo".to_string(),
|
||||||
|
Value::String("John".to_string()),
|
||||||
|
)]),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Variable {
|
||||||
|
name: "lastname".to_string(),
|
||||||
|
var_type: "mock".to_string(),
|
||||||
|
params: Params::from_iter(vec![(
|
||||||
|
"echo".to_string(),
|
||||||
|
Value::String("Snow".to_string()),
|
||||||
|
)]),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Variable {
|
||||||
|
name: "fullname".to_string(),
|
||||||
|
var_type: "mock".to_string(),
|
||||||
|
params: Params::from_iter(vec![(
|
||||||
|
"echo".to_string(),
|
||||||
|
Value::String("{{firstname}} {{lastname}}".to_string()),
|
||||||
|
)]),
|
||||||
|
inject_vars: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let res = renderer.render(&template, &Default::default(), &Default::default());
|
||||||
|
assert!(matches!(res, RenderResult::Success(str) if str == "hello John Snow"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn disable_variable_injection() {
|
||||||
|
let renderer = get_renderer();
|
||||||
|
let mut template = template_for_str("hello {{second}}");
|
||||||
|
template.vars = vec![
|
||||||
|
Variable {
|
||||||
|
name: "first".to_string(),
|
||||||
|
var_type: "mock".to_string(),
|
||||||
|
params: Params::from_iter(vec![("echo".to_string(), Value::String("one".to_string()))]),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Variable {
|
||||||
|
name: "second".to_string(),
|
||||||
|
var_type: "mock".to_string(),
|
||||||
|
params: Params::from_iter(vec![(
|
||||||
|
"echo".to_string(),
|
||||||
|
Value::String("{{first}} two".to_string()),
|
||||||
|
)]),
|
||||||
|
inject_vars: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let res = renderer.render(&template, &Default::default(), &Default::default());
|
||||||
|
assert!(matches!(res, RenderResult::Success(str) if str == "hello {{first}} two"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn variable_injection_missing_var() {
|
||||||
|
let renderer = get_renderer();
|
||||||
|
let mut template = template_for_str("hello {{second}}");
|
||||||
|
template.vars = vec![Variable {
|
||||||
|
name: "second".to_string(),
|
||||||
|
var_type: "mock".to_string(),
|
||||||
|
params: Params::from_iter(vec![(
|
||||||
|
"echo".to_string(),
|
||||||
|
Value::String("the next is {{missing}}".to_string()),
|
||||||
|
)]),
|
||||||
|
..Default::default()
|
||||||
|
}];
|
||||||
|
|
||||||
|
let res = renderer.render(&template, &Default::default(), &Default::default());
|
||||||
|
assert!(matches!(res, RenderResult::Error(_)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,11 @@
|
||||||
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use crate::{renderer::RendererError, ExtensionOutput, Params, Scope, Value};
|
||||||
|
use anyhow::Result;
|
||||||
|
use log::error;
|
||||||
|
use regex::Captures;
|
||||||
|
|
||||||
use super::VAR_REGEX;
|
use super::VAR_REGEX;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
@ -29,10 +34,91 @@ pub(crate) fn get_body_variable_names(body: &str) -> HashSet<&str> {
|
||||||
variables
|
variables
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn render_variables(body: &str, scope: &Scope) -> Result<String> {
|
||||||
|
let mut replacing_error = None;
|
||||||
|
let output = VAR_REGEX
|
||||||
|
.replace_all(body, |caps: &Captures| {
|
||||||
|
let var_name = caps.name("name").unwrap().as_str();
|
||||||
|
let var_subname = caps.name("subname");
|
||||||
|
match scope.get(var_name) {
|
||||||
|
Some(output) => match output {
|
||||||
|
ExtensionOutput::Single(output) => output,
|
||||||
|
ExtensionOutput::Multiple(results) => match var_subname {
|
||||||
|
Some(var_subname) => {
|
||||||
|
let var_subname = var_subname.as_str();
|
||||||
|
results.get(var_subname).map_or("", |value| &*value)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
error!(
|
||||||
|
"nested name missing from multi-value variable: {}",
|
||||||
|
var_name
|
||||||
|
);
|
||||||
|
replacing_error = Some(RendererError::MissingVariable(format!(
|
||||||
|
"nested name missing from multi-value variable: {}",
|
||||||
|
var_name
|
||||||
|
)));
|
||||||
|
""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
replacing_error = Some(RendererError::MissingVariable(format!(
|
||||||
|
"variable '{}' is missing",
|
||||||
|
var_name
|
||||||
|
)));
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
if let Some(error) = replacing_error {
|
||||||
|
return Err(error.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn inject_variables_into_params(params: &Params, scope: &Scope) -> Result<Params> {
|
||||||
|
let mut params = params.clone();
|
||||||
|
|
||||||
|
for (_, value) in params.iter_mut() {
|
||||||
|
inject_variables_into_value(value, scope)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inject_variables_into_value(value: &mut Value, scope: &Scope) -> Result<()> {
|
||||||
|
match value {
|
||||||
|
Value::String(s_value) => {
|
||||||
|
let new_value = render_variables(s_value, scope)?;
|
||||||
|
|
||||||
|
if &new_value != s_value {
|
||||||
|
s_value.clear();
|
||||||
|
s_value.push_str(&new_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Array(values) => {
|
||||||
|
for value in values {
|
||||||
|
inject_variables_into_value(value, scope)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Object(fields) => {
|
||||||
|
for value in fields.values_mut() {
|
||||||
|
inject_variables_into_value(value, scope)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::iter::FromIterator;
|
use std::{collections::HashMap, iter::FromIterator};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn get_body_variable_names_no_vars() {
|
fn get_body_variable_names_no_vars() {
|
||||||
|
@ -49,4 +135,44 @@ mod tests {
|
||||||
HashSet::from_iter(vec!["world", "greet"]),
|
HashSet::from_iter(vec!["world", "greet"]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_inject_variables_into_params() {
|
||||||
|
let mut params = Params::new();
|
||||||
|
params.insert(
|
||||||
|
"field1".to_string(),
|
||||||
|
Value::String("this contains {{first}}".to_string()),
|
||||||
|
);
|
||||||
|
params.insert("field2".to_string(), Value::Bool(true));
|
||||||
|
params.insert(
|
||||||
|
"field3".to_string(),
|
||||||
|
Value::Array(vec![Value::String("this contains {{first}}".to_string())]),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut nested = HashMap::new();
|
||||||
|
nested.insert(
|
||||||
|
"subfield1".to_string(),
|
||||||
|
Value::String("also contains {{first}}".to_string()),
|
||||||
|
);
|
||||||
|
params.insert("field4".to_string(), Value::Object(nested));
|
||||||
|
|
||||||
|
let mut scope = Scope::new();
|
||||||
|
scope.insert("first", ExtensionOutput::Single("one".to_string()));
|
||||||
|
|
||||||
|
let result = inject_variables_into_params(¶ms, &scope).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(result.len(), 4);
|
||||||
|
assert_eq!(
|
||||||
|
result.get("field1").unwrap(),
|
||||||
|
&Value::String("this contains one".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(result.get("field2").unwrap(), &Value::Bool(true));
|
||||||
|
assert_eq!(
|
||||||
|
result.get("field3").unwrap(),
|
||||||
|
&Value::Array(vec![Value::String("this contains one".to_string())])
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
matches!(result.get("field4").unwrap(), Value::Object(fields) if fields.get("subfield1").unwrap() == &Value::String("also contains one".to_string()))
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user