mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-12-25 12:05:32 +03:00
Merge pull request #97 from Orange-OpenSource/fix/jsonpath-parse-extra-dot
Parse extra dot in jsonpath expression
This commit is contained in:
commit
6d5239a3d2
File diff suppressed because one or more lines are too long
@ -39,3 +39,10 @@ jsonpath "$.tags" includes "test"
|
||||
jsonpath "$.tags" not includes "prod"
|
||||
jsonpath "$.tags" not includes null
|
||||
|
||||
|
||||
GET http://localhost:8000/assert-json/list
|
||||
HTTP/1.0 200
|
||||
[Asserts]
|
||||
jsonpath "$" countEquals 2
|
||||
jsonpath "$.[0].name" equals "Bob"
|
||||
jsonpath "$[0].name" equals "Bob"
|
||||
|
@ -1 +1 @@
|
||||
{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/assert-json"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"jsonpath","expr":"$.success"},"predicate":{"type":"equal","value":false}},{"query":{"type":"jsonpath","expr":"$.success"},"predicate":{"not":true,"type":"equal","value":null}},{"query":{"type":"jsonpath","expr":"$.success"},"predicate":{"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.errors"},"predicate":{"type":"count","value":2}},{"query":{"type":"jsonpath","expr":"$.warnings"},"predicate":{"type":"count","value":0}},{"query":{"type":"jsonpath","expr":"$.toto"},"predicate":{"not":true,"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.warnings"},"predicate":{"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.warnings"},"predicate":{"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.errors[0]"},"predicate":{"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.errors[0].id"},"predicate":{"type":"equal","value":"error1"}},{"query":{"type":"jsonpath","expr":"$.errors[0]['id']"},"predicate":{"type":"equal","value":"error1"}},{"query":{"type":"jsonpath","expr":"$.duration"},"predicate":{"type":"equal","value":1.5}},{"query":{"type":"jsonpath","expr":"$.duration"},"predicate":{"type":"less-than-or-equal","value":"2.0"}},{"query":{"type":"jsonpath","expr":"$.duration"},"predicate":{"type":"greater-than","value":"2"}},{"query":{"type":"jsonpath","expr":"$.nullable"},"predicate":{"type":"equal","value":null}}],"body":{"type":"json","value":{"success":false,"errors":[{"id":"error1"},{"id":"error2"}],"warnings":[],"duration":1.5,"tags":["test"],"nullable":null}}}},{"request":{"method":"GET","url":"http://localhost:8000/assert-json/index"},"response":{"version":"HTTP/1.0","status":200,"captures":[{"name":"index","query":{"type":"body"}}]}},{"request":{"method":"GET","url":"http://localhost:8000/assert-json"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"jsonpath","expr":"$.errors[{{index}}].id"},"predicate":{"type":"equal","value":"error2"}},{"query":{"type":"jsonpath","expr":"$.tags"},"predicate":{"type":"include","value":"test"}},{"query":{"type":"jsonpath","expr":"$.tags"},"predicate":{"not":true,"type":"include","value":"prod"}},{"query":{"type":"jsonpath","expr":"$.tags"},"predicate":{"not":true,"type":"include","value":null}}]}}]}
|
||||
{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/assert-json"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"jsonpath","expr":"$.success"},"predicate":{"type":"equal","value":false}},{"query":{"type":"jsonpath","expr":"$.success"},"predicate":{"not":true,"type":"equal","value":null}},{"query":{"type":"jsonpath","expr":"$.success"},"predicate":{"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.errors"},"predicate":{"type":"count","value":2}},{"query":{"type":"jsonpath","expr":"$.warnings"},"predicate":{"type":"count","value":0}},{"query":{"type":"jsonpath","expr":"$.toto"},"predicate":{"not":true,"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.warnings"},"predicate":{"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.warnings"},"predicate":{"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.errors[0]"},"predicate":{"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.errors[0].id"},"predicate":{"type":"equal","value":"error1"}},{"query":{"type":"jsonpath","expr":"$.errors[0]['id']"},"predicate":{"type":"equal","value":"error1"}},{"query":{"type":"jsonpath","expr":"$.duration"},"predicate":{"type":"equal","value":1.5}},{"query":{"type":"jsonpath","expr":"$.duration"},"predicate":{"type":"less-than-or-equal","value":"2.0"}},{"query":{"type":"jsonpath","expr":"$.duration"},"predicate":{"type":"greater-than","value":"2"}},{"query":{"type":"jsonpath","expr":"$.nullable"},"predicate":{"type":"equal","value":null}}],"body":{"type":"json","value":{"success":false,"errors":[{"id":"error1"},{"id":"error2"}],"warnings":[],"duration":1.5,"tags":["test"],"nullable":null}}}},{"request":{"method":"GET","url":"http://localhost:8000/assert-json/index"},"response":{"version":"HTTP/1.0","status":200,"captures":[{"name":"index","query":{"type":"body"}}]}},{"request":{"method":"GET","url":"http://localhost:8000/assert-json"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"jsonpath","expr":"$.errors[{{index}}].id"},"predicate":{"type":"equal","value":"error2"}},{"query":{"type":"jsonpath","expr":"$.tags"},"predicate":{"type":"include","value":"test"}},{"query":{"type":"jsonpath","expr":"$.tags"},"predicate":{"not":true,"type":"include","value":"prod"}},{"query":{"type":"jsonpath","expr":"$.tags"},"predicate":{"not":true,"type":"include","value":null}}]}},{"request":{"method":"GET","url":"http://localhost:8000/assert-json/list"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"jsonpath","expr":"$"},"predicate":{"type":"count","value":2}},{"query":{"type":"jsonpath","expr":"$.[0].name"},"predicate":{"type":"equal","value":"Bob"}},{"query":{"type":"jsonpath","expr":"$[0].name"},"predicate":{"type":"equal","value":"Bob"}}]}}]}
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"success": false,
|
||||
"errors": [{"id":"error1"},{"id":"error2"}],
|
||||
"warnings": [],
|
||||
"duration": 1.5,
|
||||
"tags": ["test"],
|
||||
"nullable": null
|
||||
}
|
@ -16,3 +16,11 @@ def assert_json():
|
||||
@app.route("/assert-json/index")
|
||||
def assert_json_index():
|
||||
return "1"
|
||||
|
||||
@app.route("/assert-json/list")
|
||||
def assert_json_list():
|
||||
return Response('''[
|
||||
{ "id": 1, "name": "Bob"},
|
||||
{ "id": 2, "name": "Bill"}
|
||||
]''', mimetype='application/json')
|
||||
|
||||
|
@ -57,7 +57,7 @@ fn selector(reader: &mut Reader) -> ParseResult<Selector> {
|
||||
}
|
||||
|
||||
fn selector_array_index(reader: &mut Reader) -> Result<Selector, Error> {
|
||||
try_literal("[", reader)?;
|
||||
try_left_bracket(reader)?;
|
||||
let i = match natural(reader) {
|
||||
Err(e) => {
|
||||
return Err(Error {
|
||||
@ -80,7 +80,7 @@ fn selector_filter(reader: &mut Reader) -> Result<Selector, Error> {
|
||||
}
|
||||
|
||||
fn selector_object_key_bracket(reader: &mut Reader) -> Result<Selector, Error> {
|
||||
try_literal("[", reader)?;
|
||||
try_left_bracket(reader)?;
|
||||
match string_value(reader) {
|
||||
Err(_) => Err(Error {
|
||||
pos: reader.state.pos.clone(),
|
||||
@ -134,6 +134,15 @@ fn selector_recursive_key(reader: &mut Reader) -> Result<Selector, Error> {
|
||||
Ok(Selector::RecursiveKey(k))
|
||||
}
|
||||
|
||||
fn try_left_bracket(reader: &mut Reader) -> Result<(), Error> {
|
||||
let start = reader.state.clone();
|
||||
if literal(".[", reader).is_err() {
|
||||
reader.state = start;
|
||||
try_literal("[", reader)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn predicate(reader: &mut Reader) -> ParseResult<Predicate> {
|
||||
// predicate always on key?
|
||||
// TODO parsing key-value
|
||||
@ -213,6 +222,21 @@ mod tests {
|
||||
use super::super::Pos;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
pub fn test_try_left_bracket() {
|
||||
let mut reader = Reader::init("xxx");
|
||||
let error = try_left_bracket(&mut reader).err().unwrap();
|
||||
assert!(error.recoverable);
|
||||
|
||||
let mut reader = Reader::init("[xxx");
|
||||
assert!(try_left_bracket(&mut reader).is_ok());
|
||||
assert_eq!(reader.state.cursor, 1);
|
||||
|
||||
let mut reader = Reader::init(".[xxx");
|
||||
assert!(try_left_bracket(&mut reader).is_ok());
|
||||
assert_eq!(reader.state.cursor, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_query() {
|
||||
let expected_query = Query {
|
||||
@ -268,13 +292,44 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_selector() {
|
||||
// Array index
|
||||
pub fn test_selector_filter() {
|
||||
// Filter equal on string with single quotes
|
||||
let mut reader = Reader::init("[?(@.key=='value')]");
|
||||
assert_eq!(
|
||||
selector(&mut reader).unwrap(),
|
||||
Selector::Filter(Predicate {
|
||||
key: "key".to_string(),
|
||||
func: PredicateFunc::EqualString("value".to_string()),
|
||||
})
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 19);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_selector_recursive() {
|
||||
let mut reader = Reader::init("..book");
|
||||
assert_eq!(
|
||||
selector(&mut reader).unwrap(),
|
||||
Selector::RecursiveKey("book".to_string())
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_selector_array_index() {
|
||||
let mut reader = Reader::init("[2]");
|
||||
assert_eq!(selector(&mut reader).unwrap(), Selector::ArrayIndex(2));
|
||||
assert_eq!(reader.state.cursor, 3);
|
||||
|
||||
// Key bracket notation
|
||||
// you don't need to keep the exact string
|
||||
// this is not part of the AST
|
||||
let mut reader = Reader::init(".[2]");
|
||||
assert_eq!(selector(&mut reader).unwrap(), Selector::ArrayIndex(2));
|
||||
assert_eq!(reader.state.cursor, 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_key_bracket_selector() {
|
||||
let mut reader = Reader::init("['key']");
|
||||
assert_eq!(
|
||||
selector(&mut reader).unwrap(),
|
||||
@ -282,14 +337,23 @@ mod tests {
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 7);
|
||||
|
||||
let mut reader = Reader::init(".['key']");
|
||||
assert_eq!(
|
||||
selector(&mut reader).unwrap(),
|
||||
Selector::NameChild("key".to_string())
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 8);
|
||||
|
||||
let mut reader = Reader::init("['key1']");
|
||||
assert_eq!(
|
||||
selector(&mut reader).unwrap(),
|
||||
Selector::NameChild("key1".to_string())
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 8);
|
||||
}
|
||||
|
||||
// Key dot notation
|
||||
#[test]
|
||||
pub fn test_selector_key_dot_notation() {
|
||||
let mut reader = Reader::init(".key");
|
||||
assert_eq!(
|
||||
selector(&mut reader).unwrap(),
|
||||
@ -303,24 +367,6 @@ mod tests {
|
||||
Selector::NameChild("key1".to_string())
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 5);
|
||||
|
||||
// Filter equal on string with single quotes
|
||||
let mut reader = Reader::init("[?(@.key=='value')]");
|
||||
assert_eq!(
|
||||
selector(&mut reader).unwrap(),
|
||||
Selector::Filter(Predicate {
|
||||
key: "key".to_string(),
|
||||
func: PredicateFunc::EqualString("value".to_string()),
|
||||
})
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 19);
|
||||
|
||||
let mut reader = Reader::init("..book");
|
||||
assert_eq!(
|
||||
selector(&mut reader).unwrap(),
|
||||
Selector::RecursiveKey("book".to_string())
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -42,6 +42,10 @@ fn test_bookstore_path() {
|
||||
test_ok("$.store.book[0].title", value.clone()),
|
||||
vec![json!("Sayings of the Century")]
|
||||
);
|
||||
assert_eq!(
|
||||
test_ok("$.store.book.[0].title", value.clone()),
|
||||
vec![json!("Sayings of the Century")]
|
||||
);
|
||||
assert_eq!(
|
||||
test_ok("$.store.book[0].title", value.clone()),
|
||||
vec![json!("Sayings of the Century")]
|
||||
|
Loading…
Reference in New Issue
Block a user