mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-11-24 12:46:01 +03:00
Merge pull request #176 from Orange-OpenSource/feature/type_input_variables
Type input variables
This commit is contained in:
commit
866074fb9f
@ -1 +1 @@
|
||||
<div class="hurl-file"><div class="hurl-entry"><div class="request"><span class="line"><span class="method">POST</span> <span class="url">http://localhost:8000/variables</span></span></div><span class="line">{<span class="line"> "name": "{{name}}",</span><span class="line"> "age": {{age}},</span><span class="line"> "female": {{female}}</span><span class="line">}</span></div><span class="line"> </span></div>
|
||||
<div class="hurl-file"><div class="hurl-entry"><div class="request"><span class="line"><span class="method">POST</span> <span class="url">http://localhost:8000/variables</span></span></div><span class="line">{<span class="line"> "name": "{{name}}",</span><span class="line"> "age": {{age}},</span><span class="line"> "height": {{height}},</span><span class="line"> "female": {{female}},</span><span class="line"> "id": "{{id}}",</span><span class="line"> "a_null": {{a_null}}</span><span class="line">}</span><div class="response"><span class="line"></span><span class="line"><span class="version">HTTP/*</span> <span class="status">200</span></span><span class="line section-header">[Asserts]</span></span><span class="line"><span class="query-type">variable</span> <span class="string">"name"</span> <span class="predicate-type">equals</span> <span class="string">"Jennifer"</span></span><span class="line"><span class="query-type">variable</span> <span class="string">"female"</span> <span class="predicate-type">equals</span> <span class="boolean">true</span></span><span class="line"><span class="query-type">variable</span> <span class="string">"age"</span> <span class="predicate-type">equals</span> <span class="number">30</span></span><span class="line"><span class="query-type">variable</span> <span class="string">"height"</span> <span class="predicate-type">equals</span> <span class="number">1.70</span></span><span class="line"><span class="query-type">variable</span> <span class="string">"a_null"</span> <span class="predicate-type">equals</span> <span class="null">null</span></span><span class="line"><span class="query-type">variable</span> <span class="string">"id"</span> <span class="predicate-type">equals</span> <span class="string">"123"</span></span></div></div></div>
|
@ -2,6 +2,17 @@ POST http://localhost:8000/variables
|
||||
{
|
||||
"name": "{{name}}",
|
||||
"age": {{age}},
|
||||
"female": {{female}}
|
||||
"height": {{height}},
|
||||
"female": {{female}},
|
||||
"id": "{{id}}",
|
||||
"a_null": {{a_null}}
|
||||
}
|
||||
|
||||
|
||||
HTTP/* 200
|
||||
[Asserts]
|
||||
variable "name" equals "Jennifer"
|
||||
variable "female" equals true
|
||||
variable "age" equals 30
|
||||
variable "height" equals 1.70
|
||||
variable "a_null" equals null
|
||||
variable "id" equals "123"
|
||||
|
@ -1 +1 @@
|
||||
{"entries":[{"request":{"method":"POST","url":"http://localhost:8000/variables","body":{"type":"json","value":{"name":"{{name}}","age":"{{age}}","female":"{{female}}"}}}}]}
|
||||
{"entries":[{"request":{"method":"POST","url":"http://localhost:8000/variables","body":{"type":"json","value":{"name":"{{name}}","age":"{{age}}","height":"{{height}}","female":"{{female}}","id":"{{id}}","a_null":"{{a_null}}"}}},"response":{"status":200,"asserts":[{"query":{"type":"variable","name":"name"},"predicate":{"type":"equal","value":"Jennifer"}},{"query":{"type":"variable","name":"female"},"predicate":{"type":"equal","value":true}},{"query":{"type":"variable","name":"age"},"predicate":{"type":"equal","value":30}},{"query":{"type":"variable","name":"height"},"predicate":{"type":"equal","value":1.70}},{"query":{"type":"variable","name":"a_null"},"predicate":{"type":"equal","value":null}},{"query":{"type":"variable","name":"id"},"predicate":{"type":"equal","value":"123"}}]}}]}
|
@ -1,4 +1,7 @@
|
||||
# Variables for hurl
|
||||
name=Jennifer
|
||||
age=30
|
||||
height=1.70
|
||||
id="123"
|
||||
a_null=null
|
||||
|
||||
|
@ -11,6 +11,9 @@ def variables():
|
||||
assert data['name'] == 'Jennifer'
|
||||
assert data['age'] == 30
|
||||
assert data['female'] == True
|
||||
assert data['id'] == '123'
|
||||
assert data['height'] == 1.7
|
||||
assert data['a_null'] == None
|
||||
return ''
|
||||
|
||||
|
||||
|
@ -21,10 +21,12 @@ pub use self::logger::{
|
||||
log_info, make_logger_error_message, make_logger_parser_error, make_logger_runner_error,
|
||||
make_logger_verbose,
|
||||
};
|
||||
pub use self::variables::parse as parse_variable;
|
||||
|
||||
mod fs;
|
||||
pub mod interactive;
|
||||
mod logger;
|
||||
mod variables;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct CLIError {
|
||||
|
137
packages/hurl/src/cli/variables.rs
Normal file
137
packages/hurl/src/cli/variables.rs
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* hurl (https://hurl.dev)
|
||||
* Copyright (C) 2020 Orange
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
use crate::cli::CLIError;
|
||||
use crate::runner::Value;
|
||||
|
||||
pub fn parse(s: &str) -> Result<(String, Value), CLIError> {
|
||||
match s.find('=') {
|
||||
None => Err(CLIError {
|
||||
message: format!("Missing value for variable {}!", s),
|
||||
}),
|
||||
Some(index) => {
|
||||
let (name, value) = s.split_at(index);
|
||||
let value = parse_value(&value[1..])?;
|
||||
Ok((name.to_string(), value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_value(s: &str) -> Result<Value, CLIError> {
|
||||
if s == "true" {
|
||||
Ok(Value::Bool(true))
|
||||
} else if s == "false" {
|
||||
Ok(Value::Bool(false))
|
||||
} else if s == "null" {
|
||||
Ok(Value::Null {})
|
||||
} else if let Ok(v) = s.parse::<i64>() {
|
||||
Ok(Value::Integer(v))
|
||||
} else if let Ok(v) = s.parse::<f64>() {
|
||||
Ok(Value::Float(
|
||||
v.trunc() as i64,
|
||||
(v.fract() * 1_000_000_000_000_000_000.0).round() as u64,
|
||||
))
|
||||
} else if let Some(s) = s.strip_prefix('"') {
|
||||
if let Some(s) = s.strip_suffix('"') {
|
||||
Ok(Value::String(s.to_string()))
|
||||
} else {
|
||||
Err(CLIError {
|
||||
message: "Value should end with a double quote".to_string(),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
Ok(Value::String(s.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_parse() {
|
||||
assert_eq!(
|
||||
parse("name=Jennifer").unwrap(),
|
||||
("name".to_string(), Value::String("Jennifer".to_string()))
|
||||
);
|
||||
assert_eq!(
|
||||
parse("female=true").unwrap(),
|
||||
("female".to_string(), Value::Bool(true))
|
||||
);
|
||||
assert_eq!(
|
||||
parse("age=30").unwrap(),
|
||||
("age".to_string(), Value::Integer(30))
|
||||
);
|
||||
assert_eq!(
|
||||
parse("height=1.7").unwrap(),
|
||||
(
|
||||
"height".to_string(),
|
||||
Value::Float(1, 700_000_000_000_000_000)
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
parse("id=\"123\"").unwrap(),
|
||||
("id".to_string(), Value::String("123".to_string()))
|
||||
);
|
||||
assert_eq!(
|
||||
parse("a_null=null").unwrap(),
|
||||
("a_null".to_string(), Value::Null {})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_error() {
|
||||
assert_eq!(
|
||||
parse("name").err().unwrap(),
|
||||
CLIError {
|
||||
message: "Missing value for variable name!".to_string()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_value() {
|
||||
assert_eq!(
|
||||
parse_value("Jennifer").unwrap(),
|
||||
Value::String("Jennifer".to_string())
|
||||
);
|
||||
assert_eq!(parse_value("true").unwrap(), Value::Bool(true));
|
||||
assert_eq!(parse_value("30").unwrap(), Value::Integer(30));
|
||||
assert_eq!(
|
||||
parse_value("1.7").unwrap(),
|
||||
Value::Float(1, 700_000_000_000_000_000)
|
||||
);
|
||||
assert_eq!(parse_value("1.0").unwrap(), Value::Float(1, 0));
|
||||
assert_eq!(parse_value("-1.0").unwrap(), Value::Float(-1, 0));
|
||||
assert_eq!(
|
||||
parse_value("\"123\"").unwrap(),
|
||||
Value::String("123".to_string())
|
||||
);
|
||||
assert_eq!(parse_value("null").unwrap(), Value::Null {});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_value_error() {
|
||||
assert_eq!(
|
||||
parse_value("\"123").err().unwrap(),
|
||||
CLIError {
|
||||
message: "Value should end with a double quote".to_string()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@ use hurl::cli::CLIError;
|
||||
use hurl::html;
|
||||
use hurl::http;
|
||||
use hurl::runner;
|
||||
use hurl::runner::{HurlResult, RunnerOptions};
|
||||
use hurl::runner::{HurlResult, RunnerOptions, Value};
|
||||
use hurl_core::ast::{Pos, SourceInfo};
|
||||
use hurl_core::error::Error;
|
||||
use hurl_core::parser;
|
||||
@ -46,7 +46,7 @@ pub struct CLIOptions {
|
||||
pub fail_fast: bool,
|
||||
pub insecure: bool,
|
||||
pub interactive: bool,
|
||||
pub variables: HashMap<String, String>,
|
||||
pub variables: HashMap<String, Value>,
|
||||
pub to_entry: Option<usize>,
|
||||
pub follow_location: bool,
|
||||
pub max_redirect: Option<usize>,
|
||||
@ -287,7 +287,7 @@ fn html_report(matches: ArgMatches) -> Result<Option<std::path::PathBuf>, CLIErr
|
||||
}
|
||||
}
|
||||
|
||||
fn variables(matches: ArgMatches) -> Result<HashMap<String, String>, CLIError> {
|
||||
fn variables(matches: ArgMatches) -> Result<HashMap<String, Value>, CLIError> {
|
||||
let mut variables = HashMap::new();
|
||||
|
||||
if let Some(filename) = matches.value_of("variables_file") {
|
||||
@ -313,45 +313,22 @@ fn variables(matches: ArgMatches) -> Result<HashMap<String, String>, CLIError> {
|
||||
if line.starts_with('#') || line.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let (name, value) = parse_variable(line)?;
|
||||
if variables.contains_key(name.as_str()) {
|
||||
return Err(CLIError {
|
||||
message: format!("Variable {} defined twice!", name),
|
||||
});
|
||||
}
|
||||
variables.insert(name.to_string(), value[1..].to_string());
|
||||
let (name, value) = cli::parse_variable(line)?;
|
||||
variables.insert(name.to_string(), value);
|
||||
}
|
||||
}
|
||||
|
||||
if matches.is_present("variable") {
|
||||
let input: Vec<_> = matches.values_of("variable").unwrap().collect();
|
||||
for s in input {
|
||||
let (name, value) = parse_variable(s)?;
|
||||
|
||||
if variables.contains_key(name.as_str()) {
|
||||
return Err(CLIError {
|
||||
message: format!("Variable {} defined twice!", name),
|
||||
});
|
||||
}
|
||||
variables.insert(name.to_string(), value[1..].to_string());
|
||||
let (name, value) = cli::parse_variable(s)?;
|
||||
variables.insert(name.to_string(), value);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(variables)
|
||||
}
|
||||
|
||||
fn parse_variable(s: &str) -> Result<(String, String), CLIError> {
|
||||
match s.find('=') {
|
||||
None => Err(CLIError {
|
||||
message: format!("Missing variable value for {}!", s),
|
||||
}),
|
||||
Some(index) => {
|
||||
let (name, value) = s.split_at(index);
|
||||
Ok((name.to_string(), value.to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn app() -> clap::App<'static, 'static> {
|
||||
clap::App::new("hurl")
|
||||
//.author(clap::crate_authors!())
|
||||
|
@ -25,7 +25,7 @@ use super::value::Value;
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct RunnerOptions {
|
||||
pub fail_fast: bool,
|
||||
pub variables: HashMap<String, String>,
|
||||
pub variables: HashMap<String, Value>,
|
||||
pub to_entry: Option<usize>,
|
||||
pub context_dir: String,
|
||||
pub pre_entry: fn() -> bool,
|
||||
|
@ -23,7 +23,6 @@ use hurl_core::ast::*;
|
||||
|
||||
use super::core::*;
|
||||
use super::entry;
|
||||
use super::value::Value;
|
||||
|
||||
/// Run a Hurl file with the hurl http client
|
||||
///
|
||||
@ -101,7 +100,7 @@ pub fn run(
|
||||
let mut variables = HashMap::default();
|
||||
|
||||
for (key, value) in options.variables {
|
||||
variables.insert(key.to_string(), Value::String(value.to_string()));
|
||||
variables.insert(key.to_string(), value);
|
||||
}
|
||||
|
||||
let n = if let Some(to_entry) = options.to_entry {
|
||||
|
@ -26,6 +26,7 @@
|
||||
pub use self::core::{Error, HurlResult, RunnerError, RunnerOptions};
|
||||
pub use self::hurl_file::run as run_hurl_file;
|
||||
pub use self::log_deserialize::parse_results as deserialize_results;
|
||||
pub use self::value::Value;
|
||||
|
||||
mod assert;
|
||||
mod body;
|
||||
|
@ -78,7 +78,11 @@ impl Value {
|
||||
pub fn is_renderable(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Value::Integer(_) | Value::Bool(_) | Value::Float(_, _) | Value::String(_)
|
||||
Value::Integer(_)
|
||||
| Value::Bool(_)
|
||||
| Value::Float(_, _)
|
||||
| Value::String(_)
|
||||
| Value::Null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ pub enum Value {
|
||||
|
||||
// can not use simply Float(f64)
|
||||
// the trait `std::cmp::Eq` is not implemented for `f64`
|
||||
// integer part, decimal part (9 digits) TODO Clarify your custom type
|
||||
// integer part, decimal part (18 digits) TODO Clarify your custom type
|
||||
Float(i64, u64),
|
||||
|
||||
String(String),
|
||||
@ -55,7 +55,7 @@ impl fmt::Display for Value {
|
||||
Value::Object(_) => "Object()".to_string(),
|
||||
Value::Nodeset(x) => format!("Nodeset{:?}", x),
|
||||
Value::Bytes(x) => format!("Bytes({:x?})", x),
|
||||
Value::Null => "Null".to_string(),
|
||||
Value::Null => "null".to_string(),
|
||||
Value::Unit => "Unit".to_string(),
|
||||
};
|
||||
write!(f, "{}", value)
|
||||
|
Loading…
Reference in New Issue
Block a user