mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-11-26 00:22:10 +03:00
Add toInt filter
This commit is contained in:
parent
45050a4aed
commit
ffd31a271c
@ -418,6 +418,7 @@ filter:
|
||||
| count-filter
|
||||
| url-encode-filter
|
||||
| url-decode-filter
|
||||
| to-int
|
||||
|
||||
regex-filter: "regex" sp (quoted-string | regex)
|
||||
|
||||
@ -427,6 +428,8 @@ url-encode-filter: "urlEncode"
|
||||
|
||||
url-decode-filter: "urlDecode"
|
||||
|
||||
to-int: "toInt"
|
||||
|
||||
|
||||
# Lexical Grammar
|
||||
|
||||
|
21
integration/tests_failed/filter.err
Normal file
21
integration/tests_failed/filter.err
Normal file
@ -0,0 +1,21 @@
|
||||
error: Filter Error
|
||||
--> tests_failed/filter.hurl:4:17
|
||||
|
|
||||
4 | jsonpath "$.id" toInt == 123
|
||||
| ^^^^^ Invalid Filter Input: string <123x>
|
||||
|
|
||||
|
||||
error: Filter Error
|
||||
--> tests_failed/filter.hurl:5:21
|
||||
|
|
||||
5 | jsonpath "$.status" toInt == 0
|
||||
| ^^^^^ Invalid Filter Input: bool <true>
|
||||
|
|
||||
|
||||
error: Filter Error
|
||||
--> tests_failed/filter.hurl:6:22
|
||||
|
|
||||
6 | jsonpath "$.unknown" toInt == 1
|
||||
| ^^^^^ Missing value to apply the filter
|
||||
|
|
||||
|
1
integration/tests_failed/filter.exit
Normal file
1
integration/tests_failed/filter.exit
Normal file
@ -0,0 +1 @@
|
||||
4
|
6
integration/tests_failed/filter.hurl
Normal file
6
integration/tests_failed/filter.hurl
Normal file
@ -0,0 +1,6 @@
|
||||
GET http://localhost:8000/error-filter
|
||||
HTTP 200
|
||||
[Asserts]
|
||||
jsonpath "$.id" toInt == 123
|
||||
jsonpath "$.status" toInt == 0
|
||||
jsonpath "$.unknown" toInt == 1
|
14
integration/tests_failed/filter.py
Normal file
14
integration/tests_failed/filter.py
Normal file
@ -0,0 +1,14 @@
|
||||
from app import app
|
||||
from flask import Response
|
||||
|
||||
|
||||
@app.route("/error-filter")
|
||||
def error_filter():
|
||||
return Response(
|
||||
"""{
|
||||
"id":"123x",
|
||||
"status": true
|
||||
}
|
||||
""",
|
||||
mimetype="application/json",
|
||||
)
|
@ -74,7 +74,7 @@ error: Filter Error
|
||||
--> tests_failed/predicate.hurl:14:22
|
||||
|
|
||||
14 | jsonpath "$.message" count == 1
|
||||
| ^^^^^ Invalid Filter Input <string>
|
||||
| ^^^^^ Invalid Filter Input: string
|
||||
|
|
||||
|
||||
error: Assert failure
|
||||
|
@ -10,10 +10,14 @@
|
||||
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.url"</span> <span class="filter-type">urlEncode</span> <span class="predicate-type">==</span> <span class="string">"https%3A//mozilla.org/%3Fx%3D%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"</span></span>
|
||||
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.encoded_url"</span> <span class="filter-type">urlDecode</span> <span class="predicate-type">==</span> <span class="string">"https://mozilla.org/?x=шеллы"</span></span>
|
||||
<span class="line"><span class="query-type">variable</span> <span class="string">"url"</span> <span class="filter-type">urlEncode</span> <span class="filter-type">urlDecode</span> <span class="predicate-type">==</span> <span class="string">"{{url}}"</span></span>
|
||||
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.id"</span> <span class="filter-type">toInt</span> <span class="predicate-type">==</span> <span class="number">123</span></span>
|
||||
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.score"</span> <span class="filter-type">toInt</span> <span class="predicate-type">==</span> <span class="number">1</span></span>
|
||||
<span class="json"><span class="line">{</span>
|
||||
<span class="line"> "list": [1,2,3],</span>
|
||||
<span class="line"> "message": "Hello Bob!",</span>
|
||||
<span class="line"> "url": "https://mozilla.org/?x=шеллы",</span>
|
||||
<span class="line"> "encoded_url": "https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"</span>
|
||||
<span class="line"> "encoded_url": "https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B",</span>
|
||||
<span class="line"> "id": "123",</span>
|
||||
<span class="line"> "score": 1.6</span>
|
||||
<span class="line">}</span></span>
|
||||
</span></span></code></pre>
|
||||
|
@ -10,9 +10,13 @@ jsonpath "$.url" == "https://mozilla.org/?x=шеллы"
|
||||
jsonpath "$.url" urlEncode == "https%3A//mozilla.org/%3Fx%3D%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"
|
||||
jsonpath "$.encoded_url" urlDecode == "https://mozilla.org/?x=шеллы"
|
||||
variable "url" urlEncode urlDecode == "{{url}}"
|
||||
jsonpath "$.id" toInt == 123
|
||||
jsonpath "$.score" toInt == 1
|
||||
{
|
||||
"list": [1,2,3],
|
||||
"message": "Hello Bob!",
|
||||
"url": "https://mozilla.org/?x=шеллы",
|
||||
"encoded_url": "https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"
|
||||
"encoded_url": "https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B",
|
||||
"id": "123",
|
||||
"score": 1.6
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/filter"},"response":{"status":200,"captures":[{"name":"url","query":{"type":"jsonpath","expr":"$.url"}}],"asserts":[{"query":{"type":"jsonpath","expr":"$.list"},"filters":[{"type":"count"}],"predicate":{"type":"equal","value":3}},{"query":{"type":"jsonpath","expr":"$.message"},"filters":[{"type":"regex","expr":{"type":"regex","value":"Hello (.*)!"}}],"predicate":{"type":"equal","value":"Bob"}},{"query":{"type":"jsonpath","expr":"$.url"},"predicate":{"type":"equal","value":"https://mozilla.org/?x=шеллы"}},{"query":{"type":"jsonpath","expr":"$.url"},"filters":[{"type":"urlEncode"}],"predicate":{"type":"equal","value":"https%3A//mozilla.org/%3Fx%3D%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"}},{"query":{"type":"jsonpath","expr":"$.encoded_url"},"filters":[{"type":"urlDecode"}],"predicate":{"type":"equal","value":"https://mozilla.org/?x=шеллы"}},{"query":{"type":"variable","name":"url"},"filters":[{"type":"urlEncode"},{"type":"urlDecode"}],"predicate":{"type":"equal","value":"{{url}}"}}],"body":{"type":"json","value":{"list":[1,2,3],"message":"Hello Bob!","url":"https://mozilla.org/?x=шеллы","encoded_url":"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"}}}}]}
|
||||
{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/filter"},"response":{"status":200,"captures":[{"name":"url","query":{"type":"jsonpath","expr":"$.url"}}],"asserts":[{"query":{"type":"jsonpath","expr":"$.list"},"filters":[{"type":"count"}],"predicate":{"type":"equal","value":3}},{"query":{"type":"jsonpath","expr":"$.message"},"filters":[{"type":"regex","expr":{"type":"regex","value":"Hello (.*)!"}}],"predicate":{"type":"equal","value":"Bob"}},{"query":{"type":"jsonpath","expr":"$.url"},"predicate":{"type":"equal","value":"https://mozilla.org/?x=шеллы"}},{"query":{"type":"jsonpath","expr":"$.url"},"filters":[{"type":"urlEncode"}],"predicate":{"type":"equal","value":"https%3A//mozilla.org/%3Fx%3D%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"}},{"query":{"type":"jsonpath","expr":"$.encoded_url"},"filters":[{"type":"urlDecode"}],"predicate":{"type":"equal","value":"https://mozilla.org/?x=шеллы"}},{"query":{"type":"variable","name":"url"},"filters":[{"type":"urlEncode"},{"type":"urlDecode"}],"predicate":{"type":"equal","value":"{{url}}"}},{"query":{"type":"jsonpath","expr":"$.id"},"filters":[{"type":"toInt"}],"predicate":{"type":"equal","value":123}},{"query":{"type":"jsonpath","expr":"$.score"},"filters":[{"type":"toInt"}],"predicate":{"type":"equal","value":1}}],"body":{"type":"json","value":{"list":[1,2,3],"message":"Hello Bob!","url":"https://mozilla.org/?x=шеллы","encoded_url":"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B","id":"123","score":1.6}}}}]}
|
||||
|
@ -7,5 +7,7 @@ def filter():
|
||||
"list": [1,2,3],
|
||||
"message": "Hello Bob!",
|
||||
"url": "https://mozilla.org/?x=шеллы",
|
||||
"encoded_url": "https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"
|
||||
"encoded_url": "https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B",
|
||||
"id": "123",
|
||||
"score": 1.6
|
||||
}"""
|
||||
|
@ -162,7 +162,7 @@ impl Error for runner::Error {
|
||||
"Missing value to apply the filter".to_string()
|
||||
}
|
||||
RunnerError::FilterInvalidInput(message) => {
|
||||
format!("Invalid Filter Input <{}>", message)
|
||||
format!("Invalid Filter Input: {}", message)
|
||||
}
|
||||
RunnerError::FilterRegexNoCapture { .. } => "Capture not found".to_string(),
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ use percent_encoding::AsciiSet;
|
||||
use regex::Regex;
|
||||
use std::collections::HashMap;
|
||||
|
||||
// TODO: indicated whether you running the filter in an assert / this produce an "assert" error
|
||||
pub fn eval_filters(
|
||||
filters: &Vec<Filter>,
|
||||
value: &Value,
|
||||
@ -46,6 +47,7 @@ fn eval_filter(
|
||||
FilterValue::Count {} => eval_count(value, &filter.source_info),
|
||||
FilterValue::UrlEncode { .. } => eval_url_encode(value, &filter.source_info),
|
||||
FilterValue::UrlDecode { .. } => eval_url_decode(value, &filter.source_info),
|
||||
FilterValue::ToInt { .. } => eval_to_int(value, &filter.source_info),
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,6 +153,26 @@ fn eval_url_decode(value: &Value, source_info: &SourceInfo) -> Result<Value, Err
|
||||
}
|
||||
}
|
||||
|
||||
fn eval_to_int(value: &Value, source_info: &SourceInfo) -> Result<Value, Error> {
|
||||
match value {
|
||||
Value::Integer(v) => Ok(Value::Integer(*v)),
|
||||
Value::Float(v) => Ok(Value::Integer(*v as i64)),
|
||||
Value::String(v) => match v.parse::<i64>() {
|
||||
Ok(i) => Ok(Value::Integer(i)),
|
||||
Err(_) => Err(Error {
|
||||
source_info: source_info.clone(),
|
||||
inner: RunnerError::FilterInvalidInput(value.display()),
|
||||
assert: false,
|
||||
}),
|
||||
},
|
||||
v => Err(Error {
|
||||
source_info: source_info.clone(),
|
||||
inner: RunnerError::FilterInvalidInput(v.display()),
|
||||
assert: false,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
@ -321,4 +343,48 @@ pub mod tests {
|
||||
Value::String("https://mozilla.org/?x=шеллы".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn eval_filter_to_int() {
|
||||
let variables = HashMap::new();
|
||||
let filter = Filter {
|
||||
source_info: SourceInfo::new(1, 1, 1, 1),
|
||||
value: FilterValue::ToInt {},
|
||||
};
|
||||
assert_eq!(
|
||||
eval_filter(&filter, &Value::String("123".to_string()), &variables).unwrap(),
|
||||
Value::Integer(123)
|
||||
);
|
||||
assert_eq!(
|
||||
eval_filter(&filter, &Value::Integer(123), &variables).unwrap(),
|
||||
Value::Integer(123)
|
||||
);
|
||||
assert_eq!(
|
||||
eval_filter(&filter, &Value::Float(1.6), &variables).unwrap(),
|
||||
Value::Integer(1)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn eval_filter_to_int_error() {
|
||||
let variables = HashMap::new();
|
||||
let filter = Filter {
|
||||
source_info: SourceInfo::new(1, 1, 1, 1),
|
||||
value: FilterValue::ToInt {},
|
||||
};
|
||||
let err = eval_filter(&filter, &Value::String("123x".to_string()), &variables)
|
||||
.err()
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
err.inner,
|
||||
RunnerError::FilterInvalidInput("string <123x>".to_string())
|
||||
);
|
||||
let err = eval_filter(&filter, &Value::Bool(true), &variables)
|
||||
.err()
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
err.inner,
|
||||
RunnerError::FilterInvalidInput("bool <true>".to_string())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -877,4 +877,5 @@ pub enum FilterValue {
|
||||
},
|
||||
UrlEncode {},
|
||||
UrlDecode {},
|
||||
ToInt {},
|
||||
}
|
||||
|
@ -1083,6 +1083,7 @@ impl Htmlable for FilterValue {
|
||||
}
|
||||
FilterValue::UrlEncode {} => "<span class=\"filter-type\">urlEncode</span>".to_string(),
|
||||
FilterValue::UrlDecode {} => "<span class=\"filter-type\">urlDecode</span>".to_string(),
|
||||
FilterValue::ToInt {} => "<span class=\"filter-type\">toInt</span>".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ pub fn filter(reader: &mut Reader) -> ParseResult<'static, Filter> {
|
||||
regex_filter,
|
||||
url_encode_filter,
|
||||
url_decode_filter,
|
||||
to_int_filter,
|
||||
],
|
||||
reader,
|
||||
)
|
||||
@ -97,6 +98,11 @@ fn url_decode_filter(reader: &mut Reader) -> ParseResult<'static, FilterValue> {
|
||||
Ok(FilterValue::UrlDecode {})
|
||||
}
|
||||
|
||||
fn to_int_filter(reader: &mut Reader) -> ParseResult<'static, FilterValue> {
|
||||
try_literal("toInt", reader)?;
|
||||
Ok(FilterValue::ToInt {})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::ast::Pos;
|
||||
|
@ -535,6 +535,9 @@ impl ToJson for FilterValue {
|
||||
FilterValue::UrlDecode { .. } => {
|
||||
attributes.push(("type".to_string(), JValue::String("urlDecode".to_string())));
|
||||
}
|
||||
FilterValue::ToInt { .. } => {
|
||||
attributes.push(("type".to_string(), JValue::String("toInt".to_string())));
|
||||
}
|
||||
}
|
||||
JValue::Object(attributes)
|
||||
}
|
||||
|
@ -1167,6 +1167,7 @@ impl Tokenizable for Filter {
|
||||
FilterValue::Count { .. } => vec![Token::FilterType(String::from("count"))],
|
||||
FilterValue::UrlEncode { .. } => vec![Token::FilterType(String::from("urlEncode"))],
|
||||
FilterValue::UrlDecode { .. } => vec![Token::FilterType(String::from("urlDecode"))],
|
||||
FilterValue::ToInt { .. } => vec![Token::FilterType(String::from("toInt"))],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user