From 22ca0ad934f5ec1a455af3a8588ede2db4fd642e Mon Sep 17 00:00:00 2001 From: jcamiel Date: Fri, 26 Jan 2024 18:11:08 +0100 Subject: [PATCH] Display source request when there are asserts/runtime errors --- .../hurl/tests_failed/assert_base64.err | 2 + .../hurl/tests_failed/assert_bytearray.err | 4 + .../tests_failed/assert_content_encoding.err | 2 + .../hurl/tests_failed/assert_decompress.err | 2 + integration/hurl/tests_failed/assert_file.err | 2 + .../tests_failed/assert_header_not_found.err | 2 + .../hurl/tests_failed/assert_header_value.err | 2 + .../hurl/tests_failed/assert_http_version.err | 1 + .../assert_invalid_predicate_type.err | 2 + .../hurl/tests_failed/assert_match_utf8.err | 2 + .../assert_match_utf8.out.pattern | 2 +- .../hurl/tests_failed/assert_newline.err | 2 + .../hurl/tests_failed/assert_query_cookie.err | 6 + .../assert_query_invalid_regex.err | 2 + .../assert_query_invalid_xpath.err | 2 + .../hurl/tests_failed/assert_status.err | 2 + .../tests_failed/assert_status.out.pattern | 2 +- .../assert_template_variable_not_found.err | 2 + ...rt_template_variable_not_found.out.pattern | 2 +- .../hurl/tests_failed/assert_value_error.err | 16 ++ .../assert_value_error.out.pattern | 2 +- .../hurl/tests_failed/assert_variable.err | 8 + integration/hurl/tests_failed/body_json.err | 2 + .../hurl/tests_failed/continue_on_error.err | 2 + .../error_format_long.err.pattern | 10 + integration/hurl/tests_failed/fail_at_end.err | 2 + .../hurl/tests_failed/file_read_access.err | 1 + .../hurl/tests_failed/file_unauthorized.err | 6 + integration/hurl/tests_failed/filter.err | 10 + .../hurl/tests_failed/filter_decode.err | 6 + .../hurl/tests_failed/filter_in_capture.err | 2 + .../hurl/tests_failed/hello_gb2312_failed.err | 2 + .../hurl/tests_failed/invalid_jsonpath.err | 12 + integration/hurl/tests_failed/invalid_xml.err | 2 + .../hurl/tests_failed/key_template.err | 2 + .../hurl/tests_failed/multipart_form_data.err | 2 + .../hurl/tests_failed/options_template.err | 2 + integration/hurl/tests_failed/predicate.err | 78 ++++++ .../tests_failed/query_header_not_found.err | 2 + .../query_header_not_found.out.pattern | 2 +- .../hurl/tests_failed/query_invalid_json.err | 2 + .../hurl/tests_failed/query_invalid_utf8.err | 2 + .../hurl/tests_failed/query_match_none.err | 2 + .../hurl/tests_failed/retry.err.pattern | 6 + .../tests_failed/retry_option.err.pattern | 6 + .../template_variable_not_renderable.err | 6 + integration/hurl/tests_ok/junit.err.pattern | 2 + integration/hurl/tests_ok/junit.out.pattern | 2 + integration/hurl/tests_ok/retry.err.pattern | 8 + integration/hurl/tests_ok/retry.out.pattern | 2 +- .../hurl/tests_ok/retry_option.err.pattern | 8 + .../hurl/tests_ok/retry_option.out.pattern | 2 +- integration/hurl/tests_ok/test.err.pattern | 2 + packages/hurl/src/json/result.rs | 13 +- packages/hurl/src/main.rs | 2 +- packages/hurl/src/report/html/nav.rs | 3 +- packages/hurl/src/report/html/testcase.rs | 6 +- packages/hurl/src/report/junit/mod.rs | 3 +- packages/hurl/src/report/junit/testcase.rs | 6 +- packages/hurl/src/runner/hurl_file.rs | 6 +- packages/hurl/src/runner/result.rs | 14 +- packages/hurl/src/util/logger.rs | 223 ++++++++++++++---- 62 files changed, 466 insertions(+), 74 deletions(-) diff --git a/integration/hurl/tests_failed/assert_base64.err b/integration/hurl/tests_failed/assert_base64.err index 10d4ba5d2..9f2296ba6 100644 --- a/integration/hurl/tests_failed/assert_base64.err +++ b/integration/hurl/tests_failed/assert_base64.err @@ -1,6 +1,8 @@ error: Assert body value --> tests_failed/assert_base64.hurl:12:8 | + | GET http://localhost:8000/assert-base64 + | ... 12 | base64,bGluZTEKbGluZTIKbGluZTMK; | ^^^^^^^^^^^^^^^^^^^^^^^^ actual value is | diff --git a/integration/hurl/tests_failed/assert_bytearray.err b/integration/hurl/tests_failed/assert_bytearray.err index 3c210056f..90d151aa7 100644 --- a/integration/hurl/tests_failed/assert_bytearray.err +++ b/integration/hurl/tests_failed/assert_bytearray.err @@ -1,6 +1,8 @@ error: Assert failure --> tests_failed/assert_bytearray.hurl:4:0 | + | GET http://localhost:8000/error-assert-bytearray + | ... 4 | bytes == hex,00; | actual: byte array | expected: byte array <00> @@ -9,6 +11,8 @@ error: Assert failure error: Assert failure --> tests_failed/assert_bytearray.hurl:5:0 | + | GET http://localhost:8000/error-assert-bytearray + | ... 5 | sha256 == hex,a8100ae6aa1940d0b663bb31cd466142ebbdbd5187131b92d93818987832eb88; | actual: byte array | expected: byte array diff --git a/integration/hurl/tests_failed/assert_content_encoding.err b/integration/hurl/tests_failed/assert_content_encoding.err index 85782a3eb..64b194f1a 100644 --- a/integration/hurl/tests_failed/assert_content_encoding.err +++ b/integration/hurl/tests_failed/assert_content_encoding.err @@ -1,6 +1,8 @@ error: Decompression error --> tests_failed/assert_content_encoding.hurl:4:1 | + | GET http://localhost:8000/error/content-encoding + | ... 4 | `Hello World!` | ^ compression unknown is not supported | diff --git a/integration/hurl/tests_failed/assert_decompress.err b/integration/hurl/tests_failed/assert_decompress.err index fea4d0b90..b3268c7dd 100644 --- a/integration/hurl/tests_failed/assert_decompress.err +++ b/integration/hurl/tests_failed/assert_decompress.err @@ -1,6 +1,8 @@ error: Decompression error --> tests_failed/assert_decompress.hurl:3:1 | + | GET http://localhost:8000/error-assert-decompress + | ... 3 | `Hello World!` | ^ could not uncompress response with gzip | diff --git a/integration/hurl/tests_failed/assert_file.err b/integration/hurl/tests_failed/assert_file.err index 508093f4e..e2c54e29d 100644 --- a/integration/hurl/tests_failed/assert_file.err +++ b/integration/hurl/tests_failed/assert_file.err @@ -1,6 +1,8 @@ error: Assert body value --> tests_failed/assert_file.hurl:8:1 | + | GET http://localhost:8000/error-assert-file + | ... 8 | file,data.txt; | ^ actual value is | diff --git a/integration/hurl/tests_failed/assert_header_not_found.err b/integration/hurl/tests_failed/assert_header_not_found.err index da760db4b..cb2836b6a 100644 --- a/integration/hurl/tests_failed/assert_header_not_found.err +++ b/integration/hurl/tests_failed/assert_header_not_found.err @@ -1,6 +1,8 @@ error: Header not found --> tests_failed/assert_header_not_found.hurl:3:1 | + | GET http://localhost:8000/error-assert-header-not-found + | ... 3 | Custom: ??? | ^^^^^^ this header has not been found in the response | diff --git a/integration/hurl/tests_failed/assert_header_value.err b/integration/hurl/tests_failed/assert_header_value.err index da8c2c0b9..8c53fbe44 100644 --- a/integration/hurl/tests_failed/assert_header_value.err +++ b/integration/hurl/tests_failed/assert_header_value.err @@ -1,6 +1,8 @@ error: Assert header value --> tests_failed/assert_header_value.hurl:3:15 | + | GET http://localhost:8000/error-assert-header-value + | ... 3 | Content-Type: ??? | ^^^ actual value is | diff --git a/integration/hurl/tests_failed/assert_http_version.err b/integration/hurl/tests_failed/assert_http_version.err index 12f0a88ae..c42734e15 100644 --- a/integration/hurl/tests_failed/assert_http_version.err +++ b/integration/hurl/tests_failed/assert_http_version.err @@ -1,6 +1,7 @@ error: Assert HTTP version --> tests_failed/assert_http_version.hurl:2:1 | + | GET http://localhost:8000/error-assert/http-version 2 | HTTP/2 200 | ^^^^^^ actual value is | diff --git a/integration/hurl/tests_failed/assert_invalid_predicate_type.err b/integration/hurl/tests_failed/assert_invalid_predicate_type.err index 67e52ce4c..5025144bd 100644 --- a/integration/hurl/tests_failed/assert_invalid_predicate_type.err +++ b/integration/hurl/tests_failed/assert_invalid_predicate_type.err @@ -1,6 +1,8 @@ error: Assert failure --> tests_failed/assert_invalid_predicate_type.hurl:4:0 | + | GET http://localhost:8000/error-assert-invalid-predicate-type + | ... 4 | header "content-type" == 1 | actual: string | expected: int <1> diff --git a/integration/hurl/tests_failed/assert_match_utf8.err b/integration/hurl/tests_failed/assert_match_utf8.err index 72dda42af..7b259988e 100644 --- a/integration/hurl/tests_failed/assert_match_utf8.err +++ b/integration/hurl/tests_failed/assert_match_utf8.err @@ -1,6 +1,8 @@ error: Invalid decoding --> tests_failed/assert_match_utf8.hurl:4:1 | + | GET http://localhost:8000/error-assert/match-utf8 + | ... 4 | body matches ".*" | ^^^^ the body can not be decoded with charset 'utf-8' | diff --git a/integration/hurl/tests_failed/assert_match_utf8.out.pattern b/integration/hurl/tests_failed/assert_match_utf8.out.pattern index 907c38fb6..f55fa64d1 100644 --- a/integration/hurl/tests_failed/assert_match_utf8.out.pattern +++ b/integration/hurl/tests_failed/assert_match_utf8.out.pattern @@ -1 +1 @@ -{"cookies":[],"entries":[{"asserts":[{"line":2,"success":true},{"line":2,"success":true},{"line":4,"message":"Invalid decoding\n --> tests_failed/assert_match_utf8.hurl:4:1\n |\n 4 | body matches \".*\"\n | ^^^^ the body can not be decoded with charset 'utf-8'\n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/error-assert/match-utf8"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"text/html; charset=utf-8"},{"name":"Content-Length","value":"1"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":1,"line":1,"time":~~~}],"filename":"tests_failed/assert_match_utf8.hurl","success":false,"time":~~~} +{"cookies":[],"entries":[{"asserts":[{"line":2,"success":true},{"line":2,"success":true},{"line":4,"message":"Invalid decoding\n --> tests_failed/assert_match_utf8.hurl:4:1\n |\n | GET http://localhost:8000/error-assert/match-utf8\n | ...\n 4 | body matches \".*\"\n | ^^^^ the body can not be decoded with charset 'utf-8'\n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/error-assert/match-utf8"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"text/html; charset=utf-8"},{"name":"Content-Length","value":"1"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":1,"line":1,"time":~~~}],"filename":"tests_failed/assert_match_utf8.hurl","success":false,"time":~~~} diff --git a/integration/hurl/tests_failed/assert_newline.err b/integration/hurl/tests_failed/assert_newline.err index b9a0e31f5..e977dd086 100644 --- a/integration/hurl/tests_failed/assert_newline.err +++ b/integration/hurl/tests_failed/assert_newline.err @@ -1,6 +1,8 @@ error: Assert body value --> tests_failed/assert_newline.hurl:10:1 | + | GET http://localhost:8000/error-assert-newline + | ... 10 |

Hello

| ^ actual value is <

Hello

diff --git a/integration/hurl/tests_failed/assert_query_cookie.err b/integration/hurl/tests_failed/assert_query_cookie.err index 003f3b0cd..4a9270e99 100644 --- a/integration/hurl/tests_failed/assert_query_cookie.err +++ b/integration/hurl/tests_failed/assert_query_cookie.err @@ -1,6 +1,8 @@ error: Assert failure --> tests_failed/assert_query_cookie.hurl:7:0 | + | GET http://localhost:8000/error-assert-query-cookie + | ... 7 | cookie "cookie1[Secure]" == false # This is not valid, Secure attribute exists or not but does have a value | actual: none | expected: bool @@ -9,6 +11,8 @@ error: Assert failure error: Assert failure --> tests_failed/assert_query_cookie.hurl:11:0 | + | GET http://localhost:8000/error-assert-query-cookie + | ... 11 | cookie "cookie2[Secure]" == true # This is not valid, Secure attribute exists or not but does have a value | actual: unit | expected: bool @@ -18,6 +22,8 @@ error: Assert failure error: Assert failure --> tests_failed/assert_query_cookie.hurl:12:0 | + | GET http://localhost:8000/error-assert-query-cookie + | ... 12 | cookie "cookie2[Secure]" not == true # This is not valid, Secure attribute exists or not but does have a value | actual: unit | expected: not bool diff --git a/integration/hurl/tests_failed/assert_query_invalid_regex.err b/integration/hurl/tests_failed/assert_query_invalid_regex.err index 0ff082ccd..3208b1c3c 100644 --- a/integration/hurl/tests_failed/assert_query_invalid_regex.err +++ b/integration/hurl/tests_failed/assert_query_invalid_regex.err @@ -1,6 +1,8 @@ error: Invalid regex --> tests_failed/assert_query_invalid_regex.hurl:4:7 | + | GET http://localhost:8000/error-assert-query-invalid-regex + | ... 4 | regex "[x" exists | ^^^^ regex expression is not valid | diff --git a/integration/hurl/tests_failed/assert_query_invalid_xpath.err b/integration/hurl/tests_failed/assert_query_invalid_xpath.err index 2430387bd..8e3b4ae71 100644 --- a/integration/hurl/tests_failed/assert_query_invalid_xpath.err +++ b/integration/hurl/tests_failed/assert_query_invalid_xpath.err @@ -1,6 +1,8 @@ error: Invalid XPath expression --> tests_failed/assert_query_invalid_xpath.hurl:4:7 | + | GET http://localhost:8000/utf8 + | ... 4 | xpath "//" == 1 | ^^^^ the XPath expression is not valid | diff --git a/integration/hurl/tests_failed/assert_status.err b/integration/hurl/tests_failed/assert_status.err index 8334653ef..c75f5949e 100644 --- a/integration/hurl/tests_failed/assert_status.err +++ b/integration/hurl/tests_failed/assert_status.err @@ -1,6 +1,8 @@ error: Assert status code --> tests_failed/assert_status.hurl:9:6 | + | GET http://localhost:8000/not_found + | ... 9 | HTTP 200 | ^^^ actual value is <404> | diff --git a/integration/hurl/tests_failed/assert_status.out.pattern b/integration/hurl/tests_failed/assert_status.out.pattern index ffb297d34..26f30dc73 100644 --- a/integration/hurl/tests_failed/assert_status.out.pattern +++ b/integration/hurl/tests_failed/assert_status.out.pattern @@ -1 +1 @@ -{"cookies":[],"entries":[{"asserts":[{"line":9,"success":true},{"line":9,"message":"Assert status code\n --> tests_failed/assert_status.hurl:9:6\n |\n 9 | HTTP 200\n | ^^^ actual value is <404>\n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/not_found"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"text/html; charset=utf-8"},{"name":"Content-Length","value":"207"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":404},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":1,"line":7,"time":~~~}],"filename":"tests_failed/assert_status.hurl","success":false,"time":~~~} +{"cookies":[],"entries":[{"asserts":[{"line":9,"success":true},{"line":9,"message":"Assert status code\n --> tests_failed/assert_status.hurl:9:6\n |\n | GET http://localhost:8000/not_found\n | ...\n 9 | HTTP 200\n | ^^^ actual value is <404>\n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/not_found"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"text/html; charset=utf-8"},{"name":"Content-Length","value":"207"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":404},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":1,"line":7,"time":~~~}],"filename":"tests_failed/assert_status.hurl","success":false,"time":~~~} diff --git a/integration/hurl/tests_failed/assert_template_variable_not_found.err b/integration/hurl/tests_failed/assert_template_variable_not_found.err index eb4f724b5..a616ab5f3 100644 --- a/integration/hurl/tests_failed/assert_template_variable_not_found.err +++ b/integration/hurl/tests_failed/assert_template_variable_not_found.err @@ -1,6 +1,8 @@ error: Undefined variable --> tests_failed/assert_template_variable_not_found.hurl:4:29 | + | GET http://localhost:8000/error-assert-template-variable-not-found + | ... 4 | header "content-type" == "{{content_type}}" | ^^^^^^^^^^^^ you must set the variable content_type | diff --git a/integration/hurl/tests_failed/assert_template_variable_not_found.out.pattern b/integration/hurl/tests_failed/assert_template_variable_not_found.out.pattern index 80d7e93ff..298bc0cd2 100644 --- a/integration/hurl/tests_failed/assert_template_variable_not_found.out.pattern +++ b/integration/hurl/tests_failed/assert_template_variable_not_found.out.pattern @@ -1 +1 @@ -{"cookies":[],"entries":[{"asserts":[{"line":2,"success":true},{"line":2,"success":true},{"line":4,"message":"Undefined variable\n --> tests_failed/assert_template_variable_not_found.hurl:4:29\n |\n 4 | header \"content-type\" == \"{{content_type}}\"\n | ^^^^^^^^^^^^ you must set the variable content_type\n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/error-assert-template-variable-not-found"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"text/html; charset=utf-8"},{"name":"Content-Length","value":"0"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":1,"line":1,"time":~~~}],"filename":"tests_failed/assert_template_variable_not_found.hurl","success":false,"time":~~~} +{"cookies":[],"entries":[{"asserts":[{"line":2,"success":true},{"line":2,"success":true},{"line":4,"message":"Undefined variable\n --> tests_failed/assert_template_variable_not_found.hurl:4:29\n |\n | GET http://localhost:8000/error-assert-template-variable-not-found\n | ...\n 4 | header \"content-type\" == \"{{content_type}}\"\n | ^^^^^^^^^^^^ you must set the variable content_type\n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/error-assert-template-variable-not-found"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"text/html; charset=utf-8"},{"name":"Content-Length","value":"0"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":1,"line":1,"time":~~~}],"filename":"tests_failed/assert_template_variable_not_found.hurl","success":false,"time":~~~} diff --git a/integration/hurl/tests_failed/assert_value_error.err b/integration/hurl/tests_failed/assert_value_error.err index c87a31056..f1ce0a4b7 100644 --- a/integration/hurl/tests_failed/assert_value_error.err +++ b/integration/hurl/tests_failed/assert_value_error.err @@ -1,6 +1,8 @@ error: Assert failure --> tests_failed/assert_value_error.hurl:4:0 | + | GET http://localhost:8000/error-assert-value + | ... 4 | header "content-type" == "XXX" | actual: string | expected: string @@ -9,6 +11,8 @@ error: Assert failure error: Assert failure --> tests_failed/assert_value_error.hurl:5:0 | + | GET http://localhost:8000/error-assert-value + | ... 5 | header "content-type" != "text/html; charset=utf-8" | actual: string | expected: string @@ -17,6 +21,8 @@ error: Assert failure error: Assert failure --> tests_failed/assert_value_error.hurl:6:0 | + | GET http://localhost:8000/error-assert-value + | ... 6 | jsonpath "$.id" == "000001" | actual: none | expected: string <000001> @@ -25,6 +31,8 @@ error: Assert failure error: Assert failure --> tests_failed/assert_value_error.hurl:7:0 | + | GET http://localhost:8000/error-assert-value + | ... 7 | jsonpath "$.values" includes 100 | actual: [int <1>, int <2>, int <3>] | expected: includes int <100> @@ -33,6 +41,8 @@ error: Assert failure error: Assert failure --> tests_failed/assert_value_error.hurl:8:0 | + | GET http://localhost:8000/error-assert-value + | ... 8 | jsonpath "$.values" not contains "Hello" | actual: [int <1>, int <2>, int <3>] | expected: not contains string @@ -42,6 +52,8 @@ error: Assert failure error: Assert failure --> tests_failed/assert_value_error.hurl:9:0 | + | GET http://localhost:8000/error-assert-value + | ... 9 | jsonpath "$.count" > 5 | actual: int <2> | expected: greater than int <5> @@ -50,6 +62,8 @@ error: Assert failure error: Assert failure --> tests_failed/assert_value_error.hurl:10:0 | + | GET http://localhost:8000/error-assert-value + | ... 10 | jsonpath "$.count" isFloat | actual: int <2> | expected: float @@ -58,6 +72,8 @@ error: Assert failure error: Assert failure --> tests_failed/assert_value_error.hurl:11:0 | + | GET http://localhost:8000/error-assert-value + | ... 11 | bytes contains hex,00; | actual: byte array <7b202276616c756573223a205b312c322c335d2c2022636f756e74223a20327d> | expected: contains byte array <00> diff --git a/integration/hurl/tests_failed/assert_value_error.out.pattern b/integration/hurl/tests_failed/assert_value_error.out.pattern index 81c395a60..15bf6f40b 100644 --- a/integration/hurl/tests_failed/assert_value_error.out.pattern +++ b/integration/hurl/tests_failed/assert_value_error.out.pattern @@ -1 +1 @@ -{"cookies":[],"entries":[{"asserts":[{"line":2,"success":true},{"line":2,"success":true},{"line":4,"message":"Assert failure\n --> tests_failed/assert_value_error.hurl:4:0\n |\n 4 | header \"content-type\" == \"XXX\"\n | actual: string \n | expected: string \n |","success":false},{"line":5,"message":"Assert failure\n --> tests_failed/assert_value_error.hurl:5:0\n |\n 5 | header \"content-type\" != \"text/html; charset=utf-8\"\n | actual: string \n | expected: string \n |","success":false},{"line":6,"message":"Assert failure\n --> tests_failed/assert_value_error.hurl:6:0\n |\n 6 | jsonpath \"$.id\" == \"000001\"\n | actual: none\n | expected: string <000001>\n |","success":false},{"line":7,"message":"Assert failure\n --> tests_failed/assert_value_error.hurl:7:0\n |\n 7 | jsonpath \"$.values\" includes 100\n | actual: [int <1>, int <2>, int <3>]\n | expected: includes int <100>\n |","success":false},{"line":8,"message":"Assert failure\n --> tests_failed/assert_value_error.hurl:8:0\n |\n 8 | jsonpath \"$.values\" not contains \"Hello\"\n | actual: [int <1>, int <2>, int <3>]\n | expected: not contains string \n | >>> types between actual and expected are not consistent\n |","success":false},{"line":9,"message":"Assert failure\n --> tests_failed/assert_value_error.hurl:9:0\n |\n 9 | jsonpath \"$.count\" > 5\n | actual: int <2>\n | expected: greater than int <5>\n |","success":false},{"line":10,"message":"Assert failure\n --> tests_failed/assert_value_error.hurl:10:0\n |\n10 | jsonpath \"$.count\" isFloat\n | actual: int <2>\n | expected: float\n |","success":false},{"line":11,"message":"Assert failure\n --> tests_failed/assert_value_error.hurl:11:0\n |\n11 | bytes contains hex,00;\n | actual: byte array <7b202276616c756573223a205b312c322c335d2c2022636f756e74223a20327d>\n | expected: contains byte array <00>\n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/error-assert-value"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"text/html; charset=utf-8"},{"name":"Content-Length","value":"32"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":1,"line":1,"time":~~~}],"filename":"tests_failed/assert_value_error.hurl","success":false,"time":~~~} +{"cookies":[],"entries":[{"asserts":[{"line":2,"success":true},{"line":2,"success":true},{"line":4,"message":"Assert failure\n --> tests_failed/assert_value_error.hurl:4:0\n |\n | GET http://localhost:8000/error-assert-value\n | ...\n 4 | header \"content-type\" == \"XXX\"\n | actual: string \n | expected: string \n |","success":false},{"line":5,"message":"Assert failure\n --> tests_failed/assert_value_error.hurl:5:0\n |\n | GET http://localhost:8000/error-assert-value\n | ...\n 5 | header \"content-type\" != \"text/html; charset=utf-8\"\n | actual: string \n | expected: string \n |","success":false},{"line":6,"message":"Assert failure\n --> tests_failed/assert_value_error.hurl:6:0\n |\n | GET http://localhost:8000/error-assert-value\n | ...\n 6 | jsonpath \"$.id\" == \"000001\"\n | actual: none\n | expected: string <000001>\n |","success":false},{"line":7,"message":"Assert failure\n --> tests_failed/assert_value_error.hurl:7:0\n |\n | GET http://localhost:8000/error-assert-value\n | ...\n 7 | jsonpath \"$.values\" includes 100\n | actual: [int <1>, int <2>, int <3>]\n | expected: includes int <100>\n |","success":false},{"line":8,"message":"Assert failure\n --> tests_failed/assert_value_error.hurl:8:0\n |\n | GET http://localhost:8000/error-assert-value\n | ...\n 8 | jsonpath \"$.values\" not contains \"Hello\"\n | actual: [int <1>, int <2>, int <3>]\n | expected: not contains string \n | >>> types between actual and expected are not consistent\n |","success":false},{"line":9,"message":"Assert failure\n --> tests_failed/assert_value_error.hurl:9:0\n |\n | GET http://localhost:8000/error-assert-value\n | ...\n 9 | jsonpath \"$.count\" > 5\n | actual: int <2>\n | expected: greater than int <5>\n |","success":false},{"line":10,"message":"Assert failure\n --> tests_failed/assert_value_error.hurl:10:0\n |\n | GET http://localhost:8000/error-assert-value\n | ...\n10 | jsonpath \"$.count\" isFloat\n | actual: int <2>\n | expected: float\n |","success":false},{"line":11,"message":"Assert failure\n --> tests_failed/assert_value_error.hurl:11:0\n |\n | GET http://localhost:8000/error-assert-value\n | ...\n11 | bytes contains hex,00;\n | actual: byte array <7b202276616c756573223a205b312c322c335d2c2022636f756e74223a20327d>\n | expected: contains byte array <00>\n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/error-assert-value"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"text/html; charset=utf-8"},{"name":"Content-Length","value":"32"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":1,"line":1,"time":~~~}],"filename":"tests_failed/assert_value_error.hurl","success":false,"time":~~~} diff --git a/integration/hurl/tests_failed/assert_variable.err b/integration/hurl/tests_failed/assert_variable.err index 8b239e2c4..5e117aebc 100644 --- a/integration/hurl/tests_failed/assert_variable.err +++ b/integration/hurl/tests_failed/assert_variable.err @@ -1,6 +1,8 @@ error: Assert failure --> tests_failed/assert_variable.hurl:8:0 | + | GET http://localhost:8000/error-assert-variable + | ... 8 | variable "toto" == "tata" | actual: none | expected: string @@ -9,6 +11,8 @@ error: Assert failure error: Undefined variable --> tests_failed/assert_variable.hurl:9:24 | + | GET http://localhost:8000/error-assert-variable + | ... 9 | variable "status" == {{unknown}} | ^^^^^^^ you must set the variable unknown | @@ -16,6 +20,8 @@ error: Undefined variable error: Assert failure --> tests_failed/assert_variable.hurl:10:0 | + | GET http://localhost:8000/error-assert-variable + | ... 10 | variable "status" == {{type}} | actual: int <200> | expected: string @@ -24,6 +30,8 @@ error: Assert failure error: Assert failure --> tests_failed/assert_variable.hurl:11:0 | + | GET http://localhost:8000/error-assert-variable + | ... 11 | variable "status" == {{length}} | actual: int <200> | expected: string <0> diff --git a/integration/hurl/tests_failed/body_json.err b/integration/hurl/tests_failed/body_json.err index f02057b38..a695d9ee5 100644 --- a/integration/hurl/tests_failed/body_json.err +++ b/integration/hurl/tests_failed/body_json.err @@ -1,6 +1,8 @@ error: Invalid JSON --> tests_failed/body_json.hurl:3:18 | + | POST https://unused + | ... 3 | "success": {{success}} | ^^^^^^^ actual value is | diff --git a/integration/hurl/tests_failed/continue_on_error.err b/integration/hurl/tests_failed/continue_on_error.err index 15a155414..acf5157ac 100644 --- a/integration/hurl/tests_failed/continue_on_error.err +++ b/integration/hurl/tests_failed/continue_on_error.err @@ -1,6 +1,7 @@ error: Assert status code --> tests_failed/continue_on_error.hurl:2:6 | + | GET http://localhost:8000/continue-on-error 2 | HTTP 400 | ^^^ actual value is <200> | @@ -8,6 +9,7 @@ error: Assert status code error: Assert status code --> tests_failed/continue_on_error.hurl:8:6 | + | GET http://localhost:8000/continue-on-error 8 | HTTP 400 | ^^^ actual value is <200> | diff --git a/integration/hurl/tests_failed/error_format_long.err.pattern b/integration/hurl/tests_failed/error_format_long.err.pattern index d5c80e491..138caa24a 100644 --- a/integration/hurl/tests_failed/error_format_long.err.pattern +++ b/integration/hurl/tests_failed/error_format_long.err.pattern @@ -11,6 +11,8 @@ Connection: close error: Assert header value --> tests_failed/error_format_long.hurl:7:15 | + | GET http://localhost:8000/error-format-long/html + | ... 7 | Content-Type: text/html | ^^^^^^^^^ actual value is | @@ -18,6 +20,8 @@ error: Assert header value error: Assert failure --> tests_failed/error_format_long.hurl:9:0 | + | GET http://localhost:8000/error-format-long/html + | ... 9 | xpath "string(//head/title)" == "Welcome!" | actual: string | expected: string @@ -26,6 +30,8 @@ error: Assert failure error: Assert failure --> tests_failed/error_format_long.hurl:11:0 | + | GET http://localhost:8000/error-format-long/html + | ... 11 | xpath "//title" count == 2 | actual: int <1> | expected: int <2> @@ -44,6 +50,8 @@ Connection: close error: Assert failure --> tests_failed/error_format_long.hurl:18:0 | + | GET http://localhost:8000/error-format-long/json + | ... 18 | jsonpath "$.books" count == 12 | actual: int <2> | expected: int <12> @@ -62,6 +70,8 @@ Connection: close error: Assert failure --> tests_failed/error_format_long.hurl:26:0 | + | GET http://localhost:8000/error-format-long/rfc-7807 + | ... 26 | jsonpath "$.title" == "You have enough credit." | actual: string | expected: string diff --git a/integration/hurl/tests_failed/fail_at_end.err b/integration/hurl/tests_failed/fail_at_end.err index 36ffb399e..42eb2daba 100644 --- a/integration/hurl/tests_failed/fail_at_end.err +++ b/integration/hurl/tests_failed/fail_at_end.err @@ -2,6 +2,7 @@ The option fail-at-end is deprecated. Use continue-on-error instead error: Assert status code --> tests_failed/fail_at_end.hurl:2:6 | + | GET http://localhost:8000/fail-at-end 2 | HTTP 400 | ^^^ actual value is <200> | @@ -9,6 +10,7 @@ error: Assert status code error: Assert status code --> tests_failed/fail_at_end.hurl:8:6 | + | GET http://localhost:8000/fail-at-end 8 | HTTP 400 | ^^^ actual value is <200> | diff --git a/integration/hurl/tests_failed/file_read_access.err b/integration/hurl/tests_failed/file_read_access.err index b89b17822..989a904b1 100644 --- a/integration/hurl/tests_failed/file_read_access.err +++ b/integration/hurl/tests_failed/file_read_access.err @@ -1,6 +1,7 @@ error: File read access --> tests_failed/file_read_access.hurl:2:6 | + | POST http://localhost:8000/error-file-read-access 2 | file,does_not_exist; | ^^^^^^^^^^^^^^ file does_not_exist can not be read | diff --git a/integration/hurl/tests_failed/file_unauthorized.err b/integration/hurl/tests_failed/file_unauthorized.err index bce750e4b..e98c552bf 100644 --- a/integration/hurl/tests_failed/file_unauthorized.err +++ b/integration/hurl/tests_failed/file_unauthorized.err @@ -1,6 +1,7 @@ error: Unauthorized file access --> tests_failed/file_unauthorized.hurl:2:6 | + | POST http://localhost:8000/post-file 2 | file,/secret.txt; | ^^^^^^^^^^^ unauthorized access to file /secret.txt, check --file-root option | @@ -8,6 +9,7 @@ error: Unauthorized file access error: Unauthorized file access --> tests_failed/file_unauthorized.hurl:7:6 | + | POST http://localhost:8000/post-file 7 | file,../secret.txt; | ^^^^^^^^^^^^^ unauthorized access to file ../secret.txt, check --file-root option | @@ -15,6 +17,8 @@ error: Unauthorized file access error: Unauthorized file access --> tests_failed/file_unauthorized.hurl:13:13 | + | POST http://localhost:8000/post-file + | ... 13 | file1: file,/secret.txt; | ^^^^^^^^^^^ unauthorized access to file /secret.txt, check --file-root option | @@ -22,6 +26,8 @@ error: Unauthorized file access error: Unauthorized file access --> tests_failed/file_unauthorized.hurl:19:13 | + | POST http://localhost:8000/post-file + | ... 19 | file1: file,../secret.txt; | ^^^^^^^^^^^^^ unauthorized access to file ../secret.txt, check --file-root option | diff --git a/integration/hurl/tests_failed/filter.err b/integration/hurl/tests_failed/filter.err index 54ad860b5..5917b06e8 100644 --- a/integration/hurl/tests_failed/filter.err +++ b/integration/hurl/tests_failed/filter.err @@ -1,6 +1,8 @@ error: Filter Error --> tests_failed/filter.hurl:4:17 | + | GET http://localhost:8000/error-filter + | ... 4 | jsonpath "$.id" toInt == 123 | ^^^^^ invalid filter input: string <123x> | @@ -8,6 +10,8 @@ error: Filter Error error: Filter Error --> tests_failed/filter.hurl:5:21 | + | GET http://localhost:8000/error-filter + | ... 5 | jsonpath "$.status" toInt == 0 | ^^^^^ invalid filter input: bool | @@ -15,6 +19,8 @@ error: Filter Error error: Filter Error --> tests_failed/filter.hurl:6:22 | + | GET http://localhost:8000/error-filter + | ... 6 | jsonpath "$.unknown" toInt == 1 | ^^^^^ missing value to apply filter | @@ -22,6 +28,8 @@ error: Filter Error error: Filter Error --> tests_failed/filter.hurl:7:19 | + | GET http://localhost:8000/error-filter + | ... 7 | jsonpath "$.list" nth 5 == 3 | ^^^^^ invalid filter input: Out of bound - size is 3 | @@ -29,6 +37,8 @@ error: Filter Error error: Filter Error --> tests_failed/filter.hurl:8:17 | + | GET http://localhost:8000/error-filter + | ... 8 | jsonpath "$.id" toDate "%a, %d %b %Y %H:%M:%S GMT" == "unused" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid filter input: string <123x> | diff --git a/integration/hurl/tests_failed/filter_decode.err b/integration/hurl/tests_failed/filter_decode.err index 4218b1b69..8dfec648d 100644 --- a/integration/hurl/tests_failed/filter_decode.err +++ b/integration/hurl/tests_failed/filter_decode.err @@ -1,6 +1,8 @@ error: Filter Error --> tests_failed/filter_decode.hurl:6:7 | + | GET http://localhost:8000/filter-decode + | ... 6 | bytes decode "unknown" == "café" # encoding is not supported | ^^^^^^^^^^^^^^^^ encoding is not supported | @@ -8,6 +10,8 @@ error: Filter Error error: Filter Error --> tests_failed/filter_decode.hurl:7:7 | + | GET http://localhost:8000/filter-decode + | ... 7 | bytes decode "arabic" == "café" # value can not be decoded with encoding | ^^^^^^^^^^^^^^^ value can not be decoded with encoding | @@ -15,6 +19,8 @@ error: Filter Error error: Assert failure --> tests_failed/filter_decode.hurl:8:0 | + | GET http://localhost:8000/filter-decode + | ... 8 | bytes decode "iso-8859-1" == "café" # value can be decoded but to an invalid string café | actual: string | expected: string diff --git a/integration/hurl/tests_failed/filter_in_capture.err b/integration/hurl/tests_failed/filter_in_capture.err index 5aa81d2cb..adb1c3fe6 100644 --- a/integration/hurl/tests_failed/filter_in_capture.err +++ b/integration/hurl/tests_failed/filter_in_capture.err @@ -1,6 +1,8 @@ error: Filter Error --> tests_failed/filter_in_capture.hurl:4:21 | + | GET http://localhost:8000/error-filter-in-capture + | ... 4 | id: jsonpath "$.id" toInt | ^^^^^ invalid filter input: string <123x> | diff --git a/integration/hurl/tests_failed/hello_gb2312_failed.err b/integration/hurl/tests_failed/hello_gb2312_failed.err index b02b6cfac..08c825473 100644 --- a/integration/hurl/tests_failed/hello_gb2312_failed.err +++ b/integration/hurl/tests_failed/hello_gb2312_failed.err @@ -1,6 +1,8 @@ error: Invalid decoding --> tests_failed/hello_gb2312_failed.hurl:10:1 | + | GET http://localhost:8000/hello_gb2312_failed + | ... 10 | xpath "string(//body)" == "你好世界" | ^^^^^^^^^^^^^^^^^^^^^^ the body can not be decoded with charset 'utf-8' | diff --git a/integration/hurl/tests_failed/invalid_jsonpath.err b/integration/hurl/tests_failed/invalid_jsonpath.err index ca2189021..ac5a48745 100644 --- a/integration/hurl/tests_failed/invalid_jsonpath.err +++ b/integration/hurl/tests_failed/invalid_jsonpath.err @@ -1,6 +1,8 @@ error: Invalid JSONPath --> tests_failed/invalid_jsonpath.hurl:5:10 | + | GET http://localhost:8000/error-invalid-jsonpath + | ... 5 | jsonpath "" == false | ^^ the JSONPath expression '' is not valid | @@ -8,6 +10,8 @@ error: Invalid JSONPath error: Invalid JSONPath --> tests_failed/invalid_jsonpath.hurl:6:10 | + | GET http://localhost:8000/error-invalid-jsonpath + | ... 6 | jsonpath "$.tags[0]x" == false | ^^^^^^^^^^^^ the JSONPath expression '$.tags[0]x' is not valid | @@ -15,6 +19,8 @@ error: Invalid JSONPath error: Invalid JSONPath --> tests_failed/invalid_jsonpath.hurl:7:10 | + | GET http://localhost:8000/error-invalid-jsonpath + | ... 7 | jsonpath "$.tags[0,A]" == false | ^^^^^^^^^^^^^ the JSONPath expression '$.tags[0,A]' is not valid | @@ -22,6 +28,8 @@ error: Invalid JSONPath error: Invalid JSONPath --> tests_failed/invalid_jsonpath.hurl:8:10 | + | GET http://localhost:8000/error-invalid-jsonpath + | ... 8 | jsonpath "$.tags[0:A]" == false | ^^^^^^^^^^^^^ the JSONPath expression '$.tags[0:A]' is not valid | @@ -29,6 +37,8 @@ error: Invalid JSONPath error: Invalid JSONPath --> tests_failed/invalid_jsonpath.hurl:9:10 | + | GET http://localhost:8000/error-invalid-jsonpath + | ... 9 | jsonpath "$.tags[]" == false | ^^^^^^^^^^ the JSONPath expression '$.tags[]' is not valid | @@ -36,6 +46,8 @@ error: Invalid JSONPath error: Invalid JSONPath --> tests_failed/invalid_jsonpath.hurl:10:10 | + | GET http://localhost:8000/error-invalid-jsonpath + | ... 10 | jsonpath "$." == false | ^^^^ the JSONPath expression '$.' is not valid | diff --git a/integration/hurl/tests_failed/invalid_xml.err b/integration/hurl/tests_failed/invalid_xml.err index d396dbad4..ec5dcf5e3 100644 --- a/integration/hurl/tests_failed/invalid_xml.err +++ b/integration/hurl/tests_failed/invalid_xml.err @@ -1,6 +1,8 @@ error: Invalid XML --> tests_failed/invalid_xml.hurl:4:1 | + | GET http://localhost:8000/error-invalid-xml + | ... 4 | xpath "xx" == 1 | ^^^^^^^^^^ the HTTP response is not a valid XML | diff --git a/integration/hurl/tests_failed/key_template.err b/integration/hurl/tests_failed/key_template.err index ebd829ef4..c1138cd83 100644 --- a/integration/hurl/tests_failed/key_template.err +++ b/integration/hurl/tests_failed/key_template.err @@ -1,6 +1,8 @@ error: Undefined variable --> tests_failed/key_template.hurl:4:3 | + | GET http://localhost:8000/error-key-template + | ... 4 | {{name}}: value | ^^^^ you must set the variable name | diff --git a/integration/hurl/tests_failed/multipart_form_data.err b/integration/hurl/tests_failed/multipart_form_data.err index 60f618904..a5bede77c 100644 --- a/integration/hurl/tests_failed/multipart_form_data.err +++ b/integration/hurl/tests_failed/multipart_form_data.err @@ -1,6 +1,8 @@ error: File read access --> tests_failed/multipart_form_data.hurl:4:15 | + | POST http://localhost:8000/unused + | ... 4 | upload1: file,unknown; | ^^^^^^^ file unknown can not be read | diff --git a/integration/hurl/tests_failed/options_template.err b/integration/hurl/tests_failed/options_template.err index a37f43782..9cf7c95ff 100644 --- a/integration/hurl/tests_failed/options_template.err +++ b/integration/hurl/tests_failed/options_template.err @@ -1,6 +1,8 @@ error: Invalid variable type --> tests_failed/options_template.hurl:6:13 | + | GET http://localhost:8000/unused + | ... 6 | location: {{redirect}} | ^^^^^^^^ expecting boolean, actual value is <10> | diff --git a/integration/hurl/tests_failed/predicate.err b/integration/hurl/tests_failed/predicate.err index f8cbf80c5..9cbcf6980 100644 --- a/integration/hurl/tests_failed/predicate.err +++ b/integration/hurl/tests_failed/predicate.err @@ -1,6 +1,8 @@ error: Assert failure --> tests_failed/predicate.hurl:4:0 | + | GET http://localhost:8000/predicate/error/type + | ... 4 | jsonpath "$.status" == "true" | actual: bool | expected: string @@ -9,6 +11,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:5:0 | + | GET http://localhost:8000/predicate/error/type + | ... 5 | jsonpath "$.count" == 0 | actual: int <1> | expected: int <0> @@ -17,6 +21,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:6:0 | + | GET http://localhost:8000/predicate/error/type + | ... 6 | jsonpath "$.message" == 0 | actual: string <0> | expected: int <0> @@ -25,6 +31,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:7:0 | + | GET http://localhost:8000/predicate/error/type + | ... 7 | jsonpath "$.empty" == 0 | actual: string <> | expected: int <0> @@ -33,6 +41,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:8:0 | + | GET http://localhost:8000/predicate/error/type + | ... 8 | jsonpath "$.number" == 1.1 | actual: float <1.0> | expected: float <1.1> @@ -41,6 +51,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:9:0 | + | GET http://localhost:8000/predicate/error/type + | ... 9 | jsonpath "$.count" startsWith "0" | actual: int <1> | expected: starts with string <0> @@ -50,6 +62,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:10:0 | + | GET http://localhost:8000/predicate/error/type + | ... 10 | jsonpath "$.count" endsWith "0" | actual: int <1> | expected: ends with string <0> @@ -59,6 +73,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:11:0 | + | GET http://localhost:8000/predicate/error/type + | ... 11 | jsonpath "$.count" matches "hi" | actual: int <1> | expected: matches regex @@ -68,6 +84,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:12:0 | + | GET http://localhost:8000/predicate/error/type + | ... 12 | jsonpath "$.count" isEmpty | actual: int <1> | expected: count equals to 0 @@ -77,6 +95,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:13:0 | + | GET http://localhost:8000/predicate/error/type + | ... 13 | jsonpath "$.count" includes "foo" | actual: int <1> | expected: includes string @@ -86,6 +106,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:14:0 | + | GET http://localhost:8000/predicate/error/type + | ... 14 | jsonpath "$.message" startsWith "hi" | actual: string <0> | expected: starts with string @@ -94,6 +116,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:15:0 | + | GET http://localhost:8000/predicate/error/type + | ... 15 | jsonpath "$.message" endsWith "hi" | actual: string <0> | expected: ends with string @@ -102,6 +126,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:16:0 | + | GET http://localhost:8000/predicate/error/type + | ... 16 | jsonpath "$.message" contains "hi" | actual: string <0> | expected: contains string @@ -110,6 +136,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:17:0 | + | GET http://localhost:8000/predicate/error/type + | ... 17 | jsonpath "$.message" matches "hi" | actual: string <0> | expected: matches regex @@ -118,6 +146,8 @@ error: Assert failure error: Invalid regex --> tests_failed/predicate.hurl:18:22 | + | GET http://localhost:8000/predicate/error/type + | ... 18 | jsonpath "$.message" matches "hi{" | ^^^^^^^^^^^^^ regex expression is not valid | @@ -125,6 +155,8 @@ error: Invalid regex error: Assert failure --> tests_failed/predicate.hurl:19:0 | + | GET http://localhost:8000/predicate/error/type + | ... 19 | jsonpath "$.message" isEmpty | actual: count equals to 1 | expected: count equals to 0 @@ -133,6 +165,8 @@ error: Assert failure error: Filter Error --> tests_failed/predicate.hurl:20:22 | + | GET http://localhost:8000/predicate/error/type + | ... 20 | jsonpath "$.message" count == 1 | ^^^^^ invalid filter input: string | @@ -140,6 +174,8 @@ error: Filter Error error: Assert failure --> tests_failed/predicate.hurl:21:0 | + | GET http://localhost:8000/predicate/error/type + | ... 21 | jsonpath "$.toto" exists | actual: none | expected: something @@ -148,6 +184,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:22:0 | + | GET http://localhost:8000/predicate/error/type + | ... 22 | jsonpath "$.message" not exists | actual: string <0> | expected: not something @@ -156,6 +194,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:23:0 | + | GET http://localhost:8000/predicate/error/type + | ... 23 | jsonpath "$.list" count == 2 | actual: int <3> | expected: int <2> @@ -164,6 +204,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:24:0 | + | GET http://localhost:8000/predicate/error/type + | ... 24 | jsonpath "$.not-exist" == 2 | actual: none | expected: integer <2> @@ -172,6 +214,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:25:0 | + | GET http://localhost:8000/predicate/error/type + | ... 25 | jsonpath "$.not-exist" > 3 | actual: none | expected: greater than > @@ -180,6 +224,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:26:0 | + | GET http://localhost:8000/predicate/error/type + | ... 26 | jsonpath "$.not-exist" >= 3 | actual: none | expected: greater than or equals to > @@ -188,6 +234,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:27:0 | + | GET http://localhost:8000/predicate/error/type + | ... 27 | jsonpath "$.not-exist" < 1 | actual: none | expected: less than > @@ -196,6 +244,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:28:0 | + | GET http://localhost:8000/predicate/error/type + | ... 28 | jsonpath "$.not-exist" <= 1 | actual: none | expected: less than or equals to > @@ -204,6 +254,8 @@ error: Assert failure error: Filter Error --> tests_failed/predicate.hurl:29:24 | + | GET http://localhost:8000/predicate/error/type + | ... 29 | jsonpath "$.not-exist" count == 1 | ^^^^^ missing value to apply filter | @@ -211,6 +263,8 @@ error: Filter Error error: Assert failure --> tests_failed/predicate.hurl:30:0 | + | GET http://localhost:8000/predicate/error/type + | ... 30 | jsonpath "$.not-exist" startsWith "foo" | actual: none | expected: starts with string @@ -219,6 +273,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:31:0 | + | GET http://localhost:8000/predicate/error/type + | ... 31 | jsonpath "$.not-exist" endsWith "foo" | actual: none | expected: ends with string @@ -227,6 +283,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:32:0 | + | GET http://localhost:8000/predicate/error/type + | ... 32 | jsonpath "$.not-exist" contains "foo" | actual: none | expected: contains string @@ -235,6 +293,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:33:0 | + | GET http://localhost:8000/predicate/error/type + | ... 33 | jsonpath "$.not-exist" includes "foo" | actual: none | expected: include string @@ -243,6 +303,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:34:0 | + | GET http://localhost:8000/predicate/error/type + | ... 34 | jsonpath "$.not-exist" matches /foo/ | actual: none | expected: matches regex @@ -251,6 +313,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:35:0 | + | GET http://localhost:8000/predicate/error/type + | ... 35 | jsonpath "$.not-exist" isInteger | actual: none | expected: integer @@ -259,6 +323,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:36:0 | + | GET http://localhost:8000/predicate/error/type + | ... 36 | jsonpath "$.not-exist" isFloat | actual: none | expected: float @@ -267,6 +333,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:37:0 | + | GET http://localhost:8000/predicate/error/type + | ... 37 | jsonpath "$.not-exist" isBoolean | actual: none | expected: boolean @@ -275,6 +343,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:38:0 | + | GET http://localhost:8000/predicate/error/type + | ... 38 | jsonpath "$.not-exist" isString | actual: none | expected: string @@ -283,6 +353,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:39:0 | + | GET http://localhost:8000/predicate/error/type + | ... 39 | jsonpath "$.not-exist" isCollection | actual: none | expected: collection @@ -291,6 +363,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:40:0 | + | GET http://localhost:8000/predicate/error/type + | ... 40 | jsonpath "$.not-exist" isDate | actual: none | expected: date @@ -299,6 +373,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:41:0 | + | GET http://localhost:8000/predicate/error/type + | ... 41 | jsonpath "$.not-exist" exists | actual: none | expected: something @@ -307,6 +383,8 @@ error: Assert failure error: Assert failure --> tests_failed/predicate.hurl:42:0 | + | GET http://localhost:8000/predicate/error/type + | ... 42 | jsonpath "$.not-exist" isEmpty | actual: none | expected: empty diff --git a/integration/hurl/tests_failed/query_header_not_found.err b/integration/hurl/tests_failed/query_header_not_found.err index faefe1c33..102a26555 100644 --- a/integration/hurl/tests_failed/query_header_not_found.err +++ b/integration/hurl/tests_failed/query_header_not_found.err @@ -1,6 +1,8 @@ error: Header not found --> tests_failed/query_header_not_found.hurl:3:1 | + | GET http://localhost:8000/error-query-header-not-found + | ... 3 | Custom: XXX | ^^^^^^ this header has not been found in the response | diff --git a/integration/hurl/tests_failed/query_header_not_found.out.pattern b/integration/hurl/tests_failed/query_header_not_found.out.pattern index 5dcdd7a5e..2b35f708e 100644 --- a/integration/hurl/tests_failed/query_header_not_found.out.pattern +++ b/integration/hurl/tests_failed/query_header_not_found.out.pattern @@ -1 +1 @@ -{"cookies":[],"entries":[{"asserts":[{"line":2,"success":true},{"line":2,"success":true},{"line":3,"message":"Header not found\n --> tests_failed/query_header_not_found.hurl:3:1\n |\n 3 | Custom: XXX\n | ^^^^^^ this header has not been found in the response\n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/error-query-header-not-found"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"text/html; charset=utf-8"},{"name":"Content-Length","value":"12"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":1,"line":1,"time":~~~}],"filename":"tests_failed/query_header_not_found.hurl","success":false,"time":~~~} +{"cookies":[],"entries":[{"asserts":[{"line":2,"success":true},{"line":2,"success":true},{"line":3,"message":"Header not found\n --> tests_failed/query_header_not_found.hurl:3:1\n |\n | GET http://localhost:8000/error-query-header-not-found\n | ...\n 3 | Custom: XXX\n | ^^^^^^ this header has not been found in the response\n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/error-query-header-not-found"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"text/html; charset=utf-8"},{"name":"Content-Length","value":"12"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":1,"line":1,"time":~~~}],"filename":"tests_failed/query_header_not_found.hurl","success":false,"time":~~~} diff --git a/integration/hurl/tests_failed/query_invalid_json.err b/integration/hurl/tests_failed/query_invalid_json.err index e4e3a77c1..276441fb7 100644 --- a/integration/hurl/tests_failed/query_invalid_json.err +++ b/integration/hurl/tests_failed/query_invalid_json.err @@ -1,6 +1,8 @@ error: Invalid JSON --> tests_failed/query_invalid_json.hurl:4:1 | + | GET http://localhost:8000/error-query-invalid-json + | ... 4 | jsonpath "$.errors" count == 2 | ^^^^^^^^^^^^^^^^^^^ the HTTP response is not a valid JSON | diff --git a/integration/hurl/tests_failed/query_invalid_utf8.err b/integration/hurl/tests_failed/query_invalid_utf8.err index c8c3263a8..126c2d23c 100644 --- a/integration/hurl/tests_failed/query_invalid_utf8.err +++ b/integration/hurl/tests_failed/query_invalid_utf8.err @@ -1,6 +1,8 @@ error: Invalid decoding --> tests_failed/query_invalid_utf8.hurl:4:1 | + | GET http://localhost:8000/error-query-invalid-utf8 + | ... 4 | jsonpath "$.errors" count == 2 | ^^^^^^^^^^^^^^^^^^^ the body can not be decoded with charset 'utf-8' | diff --git a/integration/hurl/tests_failed/query_match_none.err b/integration/hurl/tests_failed/query_match_none.err index b508da0ae..0926d9b7a 100644 --- a/integration/hurl/tests_failed/query_match_none.err +++ b/integration/hurl/tests_failed/query_match_none.err @@ -1,6 +1,8 @@ error: Assert failure --> tests_failed/query_match_none.hurl:4:0 | + | GET http://localhost:8000/query-match-none + | ... 4 | header "Location" matches /^foo$/ | actual: none | expected: matches regex <^foo$> diff --git a/integration/hurl/tests_failed/retry.err.pattern b/integration/hurl/tests_failed/retry.err.pattern index 922ee4d9a..b8c66cf18 100644 --- a/integration/hurl/tests_failed/retry.err.pattern +++ b/integration/hurl/tests_failed/retry.err.pattern @@ -30,6 +30,7 @@ * Assert status code * --> tests_failed/retry.hurl:2:6 * | +* | GET http://localhost:8000/not-found * 2 | HTTP 200 * | ^^^ actual value is <404> * | @@ -65,6 +66,7 @@ * Assert status code * --> tests_failed/retry.hurl:2:6 * | +* | GET http://localhost:8000/not-found * 2 | HTTP 200 * | ^^^ actual value is <404> * | @@ -100,6 +102,7 @@ * Assert status code * --> tests_failed/retry.hurl:2:6 * | +* | GET http://localhost:8000/not-found * 2 | HTTP 200 * | ^^^ actual value is <404> * | @@ -135,6 +138,7 @@ * Assert status code * --> tests_failed/retry.hurl:2:6 * | +* | GET http://localhost:8000/not-found * 2 | HTTP 200 * | ^^^ actual value is <404> * | @@ -170,6 +174,7 @@ * Assert status code * --> tests_failed/retry.hurl:2:6 * | +* | GET http://localhost:8000/not-found * 2 | HTTP 200 * | ^^^ actual value is <404> * | @@ -207,6 +212,7 @@ error: Assert status code --> tests_failed/retry.hurl:2:6 | + | GET http://localhost:8000/not-found 2 | HTTP 200 | ^^^ actual value is <404> | diff --git a/integration/hurl/tests_failed/retry_option.err.pattern b/integration/hurl/tests_failed/retry_option.err.pattern index 399aca28d..821bf7e36 100644 --- a/integration/hurl/tests_failed/retry_option.err.pattern +++ b/integration/hurl/tests_failed/retry_option.err.pattern @@ -32,6 +32,8 @@ * Assert status code * --> tests_failed/retry_option.hurl:5:6 * | +* | GET http://localhost:8000/not-found +* | ... * 5 | HTTP 200 * | ^^^ actual value is <404> * | @@ -71,6 +73,8 @@ * Assert status code * --> tests_failed/retry_option.hurl:5:6 * | +* | GET http://localhost:8000/not-found +* | ... * 5 | HTTP 200 * | ^^^ actual value is <404> * | @@ -112,6 +116,8 @@ error: Assert status code --> tests_failed/retry_option.hurl:5:6 | + | GET http://localhost:8000/not-found + | ... 5 | HTTP 200 | ^^^ actual value is <404> | diff --git a/integration/hurl/tests_failed/template_variable_not_renderable.err b/integration/hurl/tests_failed/template_variable_not_renderable.err index 576690234..16953cf18 100644 --- a/integration/hurl/tests_failed/template_variable_not_renderable.err +++ b/integration/hurl/tests_failed/template_variable_not_renderable.err @@ -1,6 +1,8 @@ error: Unrenderable variable --> tests_failed/template_variable_not_renderable.hurl:12:9 | + | GET http://localhost:8000/undefined + | ... 12 | list: {{list}} | ^^^^ variable with value [1,2,3] can not be rendered | @@ -8,6 +10,8 @@ error: Unrenderable variable error: Unrenderable variable --> tests_failed/template_variable_not_renderable.hurl:17:11 | + | GET http://localhost:8000/undefined + | ... 17 | object: {{object}} | ^^^^^^ variable with value Object() can not be rendered | @@ -15,6 +19,8 @@ error: Unrenderable variable error: Unrenderable variable --> tests_failed/template_variable_not_renderable.hurl:22:12 | + | GET http://localhost:8000/undefined + | ... 22 | nodeset: {{nodeset}} | ^^^^^^^ variable with value Nodeset1 can not be rendered | diff --git a/integration/hurl/tests_ok/junit.err.pattern b/integration/hurl/tests_ok/junit.err.pattern index b9983810f..330f17def 100755 --- a/integration/hurl/tests_ok/junit.err.pattern +++ b/integration/hurl/tests_ok/junit.err.pattern @@ -4,6 +4,8 @@ tests_ok/test.2.hurl: Running [2/2] error: Assert body value --> tests_ok/test.2.hurl:8:1 | + | GET http://localhost:8000/hello + | ... 8 | `Goodbye World!` | ^^^^^^^^^^^^^^^^ actual value is | diff --git a/integration/hurl/tests_ok/junit.out.pattern b/integration/hurl/tests_ok/junit.out.pattern index c75c4b3f7..4b29981b2 100644 --- a/integration/hurl/tests_ok/junit.out.pattern +++ b/integration/hurl/tests_ok/junit.out.pattern @@ -1,6 +1,8 @@ Assert body value --> tests_ok/test.2.hurl:8:1 | + | GET http://localhost:8000/hello + | ... 8 | `Goodbye World!` | ^^^^^^^^^^^^^^^^ actual value is <Hello World!> | \ No newline at end of file diff --git a/integration/hurl/tests_ok/retry.err.pattern b/integration/hurl/tests_ok/retry.err.pattern index ccd74e777..bbeb00da0 100644 --- a/integration/hurl/tests_ok/retry.err.pattern +++ b/integration/hurl/tests_ok/retry.err.pattern @@ -59,6 +59,8 @@ * Assert failure * --> tests_ok/retry.hurl:16:0 * | +* | GET http://localhost:8000/jobs/{{job_id}} +* | ... * 16 | jsonpath "$.state" == "COMPLETED" * | actual: string * | expected: string @@ -95,6 +97,8 @@ * Assert failure * --> tests_ok/retry.hurl:16:0 * | +* | GET http://localhost:8000/jobs/{{job_id}} +* | ... * 16 | jsonpath "$.state" == "COMPLETED" * | actual: string * | expected: string @@ -131,6 +135,8 @@ * Assert failure * --> tests_ok/retry.hurl:16:0 * | +* | GET http://localhost:8000/jobs/{{job_id}} +* | ... * 16 | jsonpath "$.state" == "COMPLETED" * | actual: string * | expected: string @@ -167,6 +173,8 @@ * Assert failure * --> tests_ok/retry.hurl:16:0 * | +* | GET http://localhost:8000/jobs/{{job_id}} +* | ... * 16 | jsonpath "$.state" == "COMPLETED" * | actual: string * | expected: string diff --git a/integration/hurl/tests_ok/retry.out.pattern b/integration/hurl/tests_ok/retry.out.pattern index e70712049..5bfd99a26 100644 --- a/integration/hurl/tests_ok/retry.out.pattern +++ b/integration/hurl/tests_ok/retry.out.pattern @@ -1 +1 @@ -{"cookies":[],"entries":[{"asserts":[{"line":4,"success":true},{"line":4,"success":true},{"line":8,"success":true}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"POST","queryString":[],"url":"http://localhost:8000/jobs"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":201},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[{"name":"job_id","value":"~~~"}],"index":1,"line":2,"time":~~~},{"asserts":[{"line":14,"success":true},{"line":14,"success":true},{"line":16,"message":"Assert failure\n --> tests_ok/retry.hurl:16:0\n |\n16 | jsonpath \"$.state\" == \"COMPLETED\"\n | actual: string \n | expected: string \n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":14,"success":true},{"line":14,"success":true},{"line":16,"message":"Assert failure\n --> tests_ok/retry.hurl:16:0\n |\n16 | jsonpath \"$.state\" == \"COMPLETED\"\n | actual: string \n | expected: string \n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":14,"success":true},{"line":14,"success":true},{"line":16,"message":"Assert failure\n --> tests_ok/retry.hurl:16:0\n |\n16 | jsonpath \"$.state\" == \"COMPLETED\"\n | actual: string \n | expected: string \n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":14,"success":true},{"line":14,"success":true},{"line":16,"message":"Assert failure\n --> tests_ok/retry.hurl:16:0\n |\n16 | jsonpath \"$.state\" == \"COMPLETED\"\n | actual: string \n | expected: string \n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":14,"success":true},{"line":14,"success":true},{"line":16,"success":true}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"62"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":21,"success":true},{"line":21,"success":true}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"DELETE","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Server","value":"Flask Server"},{"name":"Content-Length","value":"0"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":3,"line":20,"time":~~~},{"asserts":[{"line":24,"success":true},{"line":24,"success":true}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"42"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":404},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":4,"line":23,"time":~~~}],"filename":"tests_ok/retry.hurl","success":true,"time":~~~} +{"cookies":[],"entries":[{"asserts":[{"line":4,"success":true},{"line":4,"success":true},{"line":8,"success":true}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"POST","queryString":[],"url":"http://localhost:8000/jobs"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":201},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[{"name":"job_id","value":"~~~"}],"index":1,"line":2,"time":~~~},{"asserts":[{"line":14,"success":true},{"line":14,"success":true},{"line":16,"message":"Assert failure\n --> tests_ok/retry.hurl:16:0\n |\n | GET http://localhost:8000/jobs/{{job_id}}\n | ...\n16 | jsonpath \"$.state\" == \"COMPLETED\"\n | actual: string \n | expected: string \n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":14,"success":true},{"line":14,"success":true},{"line":16,"message":"Assert failure\n --> tests_ok/retry.hurl:16:0\n |\n | GET http://localhost:8000/jobs/{{job_id}}\n | ...\n16 | jsonpath \"$.state\" == \"COMPLETED\"\n | actual: string \n | expected: string \n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":14,"success":true},{"line":14,"success":true},{"line":16,"message":"Assert failure\n --> tests_ok/retry.hurl:16:0\n |\n | GET http://localhost:8000/jobs/{{job_id}}\n | ...\n16 | jsonpath \"$.state\" == \"COMPLETED\"\n | actual: string \n | expected: string \n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":14,"success":true},{"line":14,"success":true},{"line":16,"message":"Assert failure\n --> tests_ok/retry.hurl:16:0\n |\n | GET http://localhost:8000/jobs/{{job_id}}\n | ...\n16 | jsonpath \"$.state\" == \"COMPLETED\"\n | actual: string \n | expected: string \n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":14,"success":true},{"line":14,"success":true},{"line":16,"success":true}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"62"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":21,"success":true},{"line":21,"success":true}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"DELETE","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Server","value":"Flask Server"},{"name":"Content-Length","value":"0"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":3,"line":20,"time":~~~},{"asserts":[{"line":24,"success":true},{"line":24,"success":true}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"42"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":404},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":4,"line":23,"time":~~~}],"filename":"tests_ok/retry.hurl","success":true,"time":~~~} diff --git a/integration/hurl/tests_ok/retry_option.err.pattern b/integration/hurl/tests_ok/retry_option.err.pattern index 6e3163b1b..69868467a 100644 --- a/integration/hurl/tests_ok/retry_option.err.pattern +++ b/integration/hurl/tests_ok/retry_option.err.pattern @@ -61,6 +61,8 @@ * Assert failure * --> tests_ok/retry_option.hurl:19:0 * | +* | GET http://localhost:8000/jobs/{{job_id}} +* | ... * 19 | jsonpath "$.state" == "COMPLETED" * | actual: string * | expected: string @@ -101,6 +103,8 @@ * Assert failure * --> tests_ok/retry_option.hurl:19:0 * | +* | GET http://localhost:8000/jobs/{{job_id}} +* | ... * 19 | jsonpath "$.state" == "COMPLETED" * | actual: string * | expected: string @@ -141,6 +145,8 @@ * Assert failure * --> tests_ok/retry_option.hurl:19:0 * | +* | GET http://localhost:8000/jobs/{{job_id}} +* | ... * 19 | jsonpath "$.state" == "COMPLETED" * | actual: string * | expected: string @@ -181,6 +187,8 @@ * Assert failure * --> tests_ok/retry_option.hurl:19:0 * | +* | GET http://localhost:8000/jobs/{{job_id}} +* | ... * 19 | jsonpath "$.state" == "COMPLETED" * | actual: string * | expected: string diff --git a/integration/hurl/tests_ok/retry_option.out.pattern b/integration/hurl/tests_ok/retry_option.out.pattern index 7863449e3..d783906c6 100644 --- a/integration/hurl/tests_ok/retry_option.out.pattern +++ b/integration/hurl/tests_ok/retry_option.out.pattern @@ -1 +1 @@ -{"cookies":[],"entries":[{"asserts":[{"line":4,"success":true},{"line":4,"success":true},{"line":8,"success":true}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"POST","queryString":[],"url":"http://localhost:8000/jobs"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":201},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[{"name":"job_id","value":"~~~"}],"index":1,"line":2,"time":~~~},{"asserts":[{"line":17,"success":true},{"line":17,"success":true},{"line":19,"message":"Assert failure\n --> tests_ok/retry_option.hurl:19:0\n |\n19 | jsonpath \"$.state\" == \"COMPLETED\"\n | actual: string \n | expected: string \n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":17,"success":true},{"line":17,"success":true},{"line":19,"message":"Assert failure\n --> tests_ok/retry_option.hurl:19:0\n |\n19 | jsonpath \"$.state\" == \"COMPLETED\"\n | actual: string \n | expected: string \n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":17,"success":true},{"line":17,"success":true},{"line":19,"message":"Assert failure\n --> tests_ok/retry_option.hurl:19:0\n |\n19 | jsonpath \"$.state\" == \"COMPLETED\"\n | actual: string \n | expected: string \n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":17,"success":true},{"line":17,"success":true},{"line":19,"message":"Assert failure\n --> tests_ok/retry_option.hurl:19:0\n |\n19 | jsonpath \"$.state\" == \"COMPLETED\"\n | actual: string \n | expected: string \n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":17,"success":true},{"line":17,"success":true},{"line":19,"success":true}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"62"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":24,"success":true},{"line":24,"success":true}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"DELETE","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Server","value":"Flask Server"},{"name":"Content-Length","value":"0"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":3,"line":23,"time":~~~},{"asserts":[{"line":27,"success":true},{"line":27,"success":true}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"42"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":404},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":4,"line":26,"time":~~~}],"filename":"tests_ok/retry_option.hurl","success":true,"time":~~~} +{"cookies":[],"entries":[{"asserts":[{"line":4,"success":true},{"line":4,"success":true},{"line":8,"success":true}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"POST","queryString":[],"url":"http://localhost:8000/jobs"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":201},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[{"name":"job_id","value":"~~~"}],"index":1,"line":2,"time":~~~},{"asserts":[{"line":17,"success":true},{"line":17,"success":true},{"line":19,"message":"Assert failure\n --> tests_ok/retry_option.hurl:19:0\n |\n | GET http://localhost:8000/jobs/{{job_id}}\n | ...\n19 | jsonpath \"$.state\" == \"COMPLETED\"\n | actual: string \n | expected: string \n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":17,"success":true},{"line":17,"success":true},{"line":19,"message":"Assert failure\n --> tests_ok/retry_option.hurl:19:0\n |\n | GET http://localhost:8000/jobs/{{job_id}}\n | ...\n19 | jsonpath \"$.state\" == \"COMPLETED\"\n | actual: string \n | expected: string \n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":17,"success":true},{"line":17,"success":true},{"line":19,"message":"Assert failure\n --> tests_ok/retry_option.hurl:19:0\n |\n | GET http://localhost:8000/jobs/{{job_id}}\n | ...\n19 | jsonpath \"$.state\" == \"COMPLETED\"\n | actual: string \n | expected: string \n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":17,"success":true},{"line":17,"success":true},{"line":19,"message":"Assert failure\n --> tests_ok/retry_option.hurl:19:0\n |\n | GET http://localhost:8000/jobs/{{job_id}}\n | ...\n19 | jsonpath \"$.state\" == \"COMPLETED\"\n | actual: string \n | expected: string \n |","success":false}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"60"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":17,"success":true},{"line":17,"success":true},{"line":19,"success":true}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"62"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":2,"line":12,"time":~~~},{"asserts":[{"line":24,"success":true},{"line":24,"success":true}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"DELETE","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Server","value":"Flask Server"},{"name":"Content-Length","value":"0"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":200},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":3,"line":23,"time":~~~},{"asserts":[{"line":27,"success":true},{"line":27,"success":true}],"calls":[{"request":{"cookies":[],"headers":[{"name":"Host","value":"localhost:8000"},{"name":"Accept","value":"*/*"},{"name":"User-Agent","value":"hurl/~~~"}],"method":"GET","queryString":[],"url":"http://localhost:8000/jobs/~~~"},"response":{"cookies":[],"headers":[{"name":"Server","value":"Werkzeug/~~~ Python/~~~"},{"name":"Date","value":"~~~"},{"name":"Content-Type","value":"application/json"},{"name":"Content-Length","value":"42"},{"name":"Server","value":"Flask Server"},{"name":"Connection","value":"close"}],"httpVersion":"HTTP/1.1","status":404},"timings":{"app_connect":~~~,"begin_call":"~~~","connect":~~~,"end_call":"~~~","name_lookup":~~~,"pre_transfer":~~~,"start_transfer":~~~,"total":~~~}}],"captures":[],"index":4,"line":26,"time":~~~}],"filename":"tests_ok/retry_option.hurl","success":true,"time":~~~} diff --git a/integration/hurl/tests_ok/test.err.pattern b/integration/hurl/tests_ok/test.err.pattern index 1ee1657e0..d07723cda 100644 --- a/integration/hurl/tests_ok/test.err.pattern +++ b/integration/hurl/tests_ok/test.err.pattern @@ -4,6 +4,8 @@ tests_ok~test.2.hurl: Running [2/3] error: Assert body value --> tests_ok~test.2.hurl:8:1 | + | GET http://localhost:8000/hello + | ... 8 | `Goodbye World!` | ^^^^^^^^^^^^^^^^ actual value is ~ | diff --git a/packages/hurl/src/json/result.rs b/packages/hurl/src/json/result.rs index e3ab1fff7..b8144812f 100644 --- a/packages/hurl/src/json/result.rs +++ b/packages/hurl/src/json/result.rs @@ -16,6 +16,7 @@ * */ use chrono::{DateTime, Utc}; +use hurl_core::ast::SourceInfo; use serde_json::Number; use crate::http::{ @@ -73,7 +74,7 @@ impl EntryResult { let asserts = self .asserts .iter() - .map(|a| a.to_json(filename, content)) + .map(|a| a.to_json(filename, content, self.source_info)) .collect(); map.insert("asserts".to_string(), asserts); map.insert( @@ -329,14 +330,20 @@ impl CaptureResult { } impl AssertResult { - fn to_json(&self, filename: &str, content: &str) -> serde_json::Value { + fn to_json( + &self, + filename: &str, + content: &str, + entry_src_info: SourceInfo, + ) -> serde_json::Value { let mut map = serde_json::Map::new(); let success = self.error().is_none(); map.insert("success".to_string(), serde_json::Value::Bool(success)); if let Some(err) = self.error() { - let message = logger::error_string(filename, content, &err, false); + let message = + logger::error_string(filename, content, &err, Some(entry_src_info), false); map.insert("message".to_string(), serde_json::Value::String(message)); } map.insert( diff --git a/packages/hurl/src/main.rs b/packages/hurl/src/main.rs index ee6614fbc..f3b4ba6f5 100644 --- a/packages/hurl/src/main.rs +++ b/packages/hurl/src/main.rs @@ -259,7 +259,7 @@ fn exit_code(runs: &[HurlRun]) -> i32 { for run in runs.iter() { let errors = run.hurl_result.errors(); if errors.is_empty() { - } else if errors.iter().filter(|e| !e.assert).count() == 0 { + } else if errors.iter().filter(|(error, _)| !error.assert).count() == 0 { count_errors_assert += 1; } else { count_errors_runner += 1; diff --git a/packages/hurl/src/report/html/nav.rs b/packages/hurl/src/report/html/nav.rs index 507f14a79..83ae54143 100644 --- a/packages/hurl/src/report/html/nav.rs +++ b/packages/hurl/src/report/html/nav.rs @@ -60,7 +60,8 @@ impl Testcase { let line = e.source_info.start.line; let column = e.source_info.start.column; let filename = &self.filename; - let message = logger::error_string(filename, content, e, false); + let message = + logger::error_string(filename, content, e, Some(e.source_info), false); // We override the first part of the error string to add an anchor to // the error context. let old = format!("{filename}:{line}:{column}"); diff --git a/packages/hurl/src/report/html/testcase.rs b/packages/hurl/src/report/html/testcase.rs index a5fa73a3b..e9bb1757b 100644 --- a/packages/hurl/src/report/html/testcase.rs +++ b/packages/hurl/src/report/html/testcase.rs @@ -38,7 +38,11 @@ impl Testcase { /// Creates an HTML testcase. pub fn from(hurl_result: &HurlResult, filename: &str) -> Testcase { let id = Uuid::new_v4(); - let errors = hurl_result.errors().into_iter().cloned().collect(); + let errors = hurl_result + .errors() + .into_iter() + .map(|(e, _)| e.clone()) + .collect(); Testcase { id: id.to_string(), filename: filename.to_string(), diff --git a/packages/hurl/src/report/junit/mod.rs b/packages/hurl/src/report/junit/mod.rs index ac63629ff..b1fcfcad9 100644 --- a/packages/hurl/src/report/junit/mod.rs +++ b/packages/hurl/src/report/junit/mod.rs @@ -208,7 +208,8 @@ mod tests { \ Assert status code\n \ --> -:2:10\n \ - |\n \ + |\n \ + | GET http://localhost:8000/not_found\n \ 2 | HTTP/1.0 200\n \ | ^^^ actual value is <404>\n \ |\ diff --git a/packages/hurl/src/report/junit/testcase.rs b/packages/hurl/src/report/junit/testcase.rs index b730a9a64..e932cfbaf 100644 --- a/packages/hurl/src/report/junit/testcase.rs +++ b/packages/hurl/src/report/junit/testcase.rs @@ -37,8 +37,9 @@ impl Testcase { let mut failures = vec![]; let mut errors = vec![]; - for error in hurl_result.errors() { - let message = logger::error_string(filename, content, error, false); + for (error, entry_src_info) in hurl_result.errors() { + let message = + logger::error_string(filename, content, error, Some(entry_src_info), false); if error.assert { failures.push(message); } else { @@ -146,6 +147,7 @@ HTTP/1.0 200 r#"Assert status code --> test.hurl:2:10 | + | GET http://localhost:8000/not_found 2 | HTTP/1.0 200 | ^^^ actual value is <404> |"# diff --git a/packages/hurl/src/runner/hurl_file.rs b/packages/hurl/src/runner/hurl_file.rs index 5fc729c24..3622497a6 100644 --- a/packages/hurl/src/runner/hurl_file.rs +++ b/packages/hurl/src/runner/hurl_file.rs @@ -83,7 +83,7 @@ pub fn run( let hurl_file = match hurl_file { Ok(h) => h, Err(e) => { - logger.error_rich(content, &e); + logger.error_parsing_rich(content, &e); return Err(e.description()); } }; @@ -460,7 +460,7 @@ fn log_errors(entry_result: &EntryResult, content: &str, retry: bool, logger: &L entry_result .errors .iter() - .for_each(|e| logger.debug_error(content, e)); + .for_each(|e| logger.debug_error(content, e, entry_result.source_info)); return; } @@ -475,7 +475,7 @@ fn log_errors(entry_result: &EntryResult, content: &str, retry: bool, logger: &L entry_result .errors .iter() - .for_each(|e| logger.error_rich(content, e)); + .for_each(|error| logger.error_runtime_rich(content, error, entry_result.source_info)); } /// Creates a new logger for this entry. diff --git a/packages/hurl/src/runner/result.rs b/packages/hurl/src/runner/result.rs index c87aedd04..3fa69cde8 100644 --- a/packages/hurl/src/runner/result.rs +++ b/packages/hurl/src/runner/result.rs @@ -32,19 +32,25 @@ pub struct HurlResult { } impl HurlResult { - /// Returns all the effective errors of this `HurlResult`. + /// Returns all the effective errors of this `HurlResult`, with the source information + /// of the entry where the error happens. /// /// The errors are only the "effective" ones: those that are due to retry are /// ignored. - pub fn errors(&self) -> Vec<&Error> { + pub fn errors(&self) -> Vec<(&Error, SourceInfo)> { let mut errors = vec![]; let mut next_entries = self.entries.iter().skip(1); for entry in self.entries.iter() { match next_entries.next() { - None => errors.extend(&entry.errors), + None => { + let new_errors = entry.errors.iter().map(|error| (error, entry.source_info)); + errors.extend(new_errors); + } Some(next) => { if next.entry_index != entry.entry_index { - errors.extend(&entry.errors) + let new_errors = + entry.errors.iter().map(|error| (error, entry.source_info)); + errors.extend(new_errors) } } } diff --git a/packages/hurl/src/util/logger.rs b/packages/hurl/src/util/logger.rs index a3d95b826..877b7d4ff 100644 --- a/packages/hurl/src/util/logger.rs +++ b/packages/hurl/src/util/logger.rs @@ -18,6 +18,7 @@ use std::cmp::max; use colored::*; +use hurl_core::ast::SourceInfo; use hurl_core::error::Error; use crate::runner::{HurlResult, Value}; @@ -227,14 +228,14 @@ impl Logger { } } - pub fn debug_error(&self, content: &str, error: &E) { + pub fn debug_error(&self, content: &str, error: &E, entry_src_info: SourceInfo) { if self.verbosity.is_none() { return; } if self.color { - log_debug_error(&self.filename, content, error) + log_debug_error(&self.filename, content, error, entry_src_info) } else { - log_debug_error_no_color(&self.filename, content, error) + log_debug_error_no_color(&self.filename, content, error, entry_src_info) } } @@ -298,11 +299,24 @@ impl Logger { } } - pub fn error_rich(&self, content: &str, error: &E) { + pub fn error_parsing_rich(&self, content: &str, error: &E) { if self.color { - log_error_rich(&self.filename, content, error) + log_error_rich(&self.filename, content, error, None) } else { - log_error_rich_no_color(&self.filename, content, error) + log_error_rich_no_color(&self.filename, content, error, None) + } + } + + pub fn error_runtime_rich( + &self, + content: &str, + error: &E, + entry_src_info: SourceInfo, + ) { + if self.color { + log_error_rich(&self.filename, content, error, Some(entry_src_info)) + } else { + log_error_rich_no_color(&self.filename, content, error, Some(entry_src_info)) } } @@ -412,13 +426,18 @@ fn log_debug_important(message: &str) { } } -fn log_debug_error(filename: &str, content: &str, error: &E) { - let message = error_string(filename, content, error, true); +fn log_debug_error(filename: &str, content: &str, error: &E, entry_src_info: SourceInfo) { + let message = error_string(filename, content, error, Some(entry_src_info), true); split_lines(&message).iter().for_each(|l| log_debug(l)); } -fn log_debug_error_no_color(filename: &str, content: &str, error: &E) { - let message = error_string(filename, content, error, false); +fn log_debug_error_no_color( + filename: &str, + content: &str, + error: &E, + entry_src_info: SourceInfo, +) { + let message = error_string(filename, content, error, Some(entry_src_info), false); split_lines(&message) .iter() .for_each(|l| log_debug_no_color(l)); @@ -472,13 +491,23 @@ fn log_error_no_color(message: &str) { eprintln!("error: {message}"); } -fn log_error_rich(filename: &str, content: &str, error: &E) { - let message = error_string(filename, content, error, true); +fn log_error_rich( + filename: &str, + content: &str, + error: &E, + entry_src_info: Option, +) { + let message = error_string(filename, content, error, entry_src_info, true); eprintln!("{}: {}\n", "error".red().bold(), &message) } -fn log_error_rich_no_color(filename: &str, content: &str, error: &E) { - let message = error_string(filename, content, error, false); +fn log_error_rich_no_color( + filename: &str, + content: &str, + error: &E, + entry_src_info: Option, +) { + let message = error_string(filename, content, error, entry_src_info, false); eprintln!("error: {}\n", &message) } @@ -551,6 +580,8 @@ fn log_test_completed_no_color(result: &HurlResult, filename: &str) { /// Returns the string representation of an `error`, given `lines` of content and a `filename`. /// +/// The source information where the error occurred can be retrieved in `error`; optionally, +/// `entry_src_info` is the optional source information for the entry where the error happened. /// If `colored` is true, the string use ANSI escape codes to add color and improve the readability /// of the representation. /// @@ -568,20 +599,23 @@ pub(crate) fn error_string( filename: &str, content: &str, error: &E, + entry_src_info: Option, colored: bool, ) -> String { let mut text = String::new(); let lines = split_lines(content); + let entry_line = entry_src_info.map(|e| e.start.line); let error_line = error.source_info().start.line; let error_column = error.source_info().start.column; // The number of digits of the lines count. - let line_number_size = max(lines.len().to_string().len(), 2); + let loc_max_width = max(lines.len().to_string().len(), 2); + let separator = "|"; let separator = if colored { - "|".blue().bold().to_string() + separator.blue().bold().to_string() } else { - "|".to_string() + separator.to_string() }; - let spaces = " ".repeat(line_number_size); + let spaces = " ".repeat(loc_max_width); let prefix = format!("{spaces} {separator}"); // 1. First line is the description, ex. `Assert status code`. @@ -594,38 +628,53 @@ pub(crate) fn error_string( text.push('\n'); // 2. Second line is the filename info, ex. ` --> test.hurl:2:10` + let arrow = "-->"; let arrow = if colored { - "-->".blue().bold().to_string() + arrow.blue().bold().to_string() } else { - "-->".to_string() + arrow.to_string() }; - let file_line = format!("{spaces}{arrow} {filename}:{error_line}:{error_column}"); - text.push_str(&file_line); + let line = format!("{spaces}{arrow} {filename}:{error_line}:{error_column}"); + text.push_str(&line); text.push('\n'); // 3. Appends line separator. text.push_str(&prefix); text.push('\n'); - // 4. Then, we build error line (whitespace is uniformized) - // ex. ` 2 | HTTP/1.0 200` - let line_raw = lines.get(error_line - 1).unwrap(); - let line = line_raw.replace('\t', " "); - let width = line_number_size; - let mut line_number = format!("{error_line:>width$}"); - if colored { - line_number = line_number.blue().bold().to_string(); + // 4. Appends the optional entry line. + if let Some(entry_line) = entry_line { + if entry_line != error_line { + let line = lines.get(entry_line - 1).unwrap(); + let line = if colored { + line.bright_black().to_string() + } else { + line.to_string() + }; + text.push_str(&prefix); + text.push(' '); + text.push_str(&line); + text.push('\n'); + } + if error_line - entry_line > 1 { + text.push_str(&prefix); + let dots = " ...\n"; + let dots = if colored { + dots.bright_black().to_string() + } else { + dots.to_string() + }; + text.push_str(&dots); + } } - text.push_str(&line_number); - text.push(' '); - text.push_str(&separator); - if !line.is_empty() { - text.push(' '); - text.push_str(&line); - }; + + // 5. Then, we build error line (whitespace is uniformized) + // ex. ` 2 | HTTP/1.0 200` + let line = line_with_loc(&lines, error_line, &separator, colored); + text.push_str(&line); text.push('\n'); - // 5. Then, we append the error detailed message: + // 6. Then, we append the error detailed message: // ``` // | actual: byte array // | expected: byte array <00> @@ -645,6 +694,7 @@ pub(crate) fn error_string( // tabs with 4 spaces. // TODO: add a unit test with tabs in source info. let mut tab_shift = 0; + let line_raw = lines.get(error_line - 1).unwrap(); for (i, c) in line_raw.chars().enumerate() { if i >= error_column - 1 { break; @@ -681,6 +731,27 @@ pub(crate) fn error_string( text } +/// Returns the `line` count prefix. +/// Example: ` 45 ` +fn line_with_loc(lines: &[&str], loc: usize, separator: &str, colored: bool) -> String { + let mut text = String::new(); + let loc_max_width = max(lines.len().to_string().len(), 2); + let line = lines.get(loc - 1).unwrap(); + let line = line.replace('\t', " "); + let mut line_number = format!("{loc:>loc_max_width$}"); + if colored { + line_number = line_number.blue().bold().to_string(); + } + text.push_str(&line_number); + text.push(' '); + text.push_str(separator); + if !line.is_empty() { + text.push(' '); + text.push_str(&line); + } + text +} + /// Prefixes each line of the string `s` with a `prefix` and returns the new string. /// If `colored` is true, each line is colored with ANSI escape codes. fn add_line_prefix(s: &str, prefix: &str, colored: bool) -> String { @@ -717,6 +788,26 @@ pub mod tests { ) } + #[test] + fn test_error_timeout() { + let content = "GET http://unknown"; + let filename = "test.hurl"; + let inner = + runner::RunnerError::HttpConnection("(6) Could not resolve host: unknown".to_string()); + let error_source_info = SourceInfo::new(Pos::new(1, 5), Pos::new(1, 19)); + let entry_source_info = SourceInfo::new(Pos::new(1, 1), Pos::new(1, 19)); + let error = runner::Error::new(error_source_info, inner, true); + assert_eq!( + error_string(filename, content, &error, Some(entry_source_info), false), + r#"HTTP connection + --> test.hurl:1:5 + | + 1 | GET http://unknown + | ^^^^^^^^^^^^^^ (6) Could not resolve host: unknown + |"# + ) + } + #[test] fn test_assert_error_status() { let content = r#"GET http://unknown @@ -726,16 +817,15 @@ HTTP/1.0 200 let inner = runner::RunnerError::AssertStatus { actual: "404".to_string(), }; - let error = runner::Error::new( - SourceInfo::new(Pos::new(2, 10), Pos::new(2, 13)), - inner, - true, - ); + let error_source_info = SourceInfo::new(Pos::new(2, 10), Pos::new(2, 13)); + let entry_source_info = SourceInfo::new(Pos::new(1, 1), Pos::new(1, 18)); + let error = runner::Error::new(error_source_info, inner, true); assert_eq!( - error_string(filename, content, &error, false), + error_string(filename, content, &error, Some(entry_source_info), false), r#"Assert status code --> test.hurl:2:10 | + | GET http://unknown 2 | HTTP/1.0 200 | ^^^ actual value is <404> |"# @@ -750,16 +840,20 @@ HTTP/1.0 200 xpath "strong(//head/title)" == "Hello" "#; let filename = "test.hurl"; + let error_source_info = SourceInfo::new(Pos::new(4, 7), Pos::new(4, 29)); + let entry_source_info = SourceInfo::new(Pos::new(1, 1), Pos::new(1, 22)); let error = runner::Error::new( - SourceInfo::new(Pos::new(4, 7), Pos::new(4, 29)), + error_source_info, runner::RunnerError::QueryInvalidXpathEval, true, ); assert_eq!( - error_string(filename, content, &error, false), + error_string(filename, content, &error, Some(entry_source_info), false), r#"Invalid XPath expression --> test.hurl:4:7 | + | GET http://example.com + | ... 4 | xpath "strong(//head/title)" == "Hello" | ^^^^^^^^^^^^^^^^^^^^^^ the XPath expression is not valid |"# @@ -774,8 +868,10 @@ HTTP/1.0 200 jsonpath "$.count" >= 5 "#; let filename = "test.hurl"; + let error_source_info = SourceInfo::new(Pos::new(4, 0), Pos::new(4, 0)); + let entry_source_info = SourceInfo::new(Pos::new(1, 1), Pos::new(1, 14)); let error = runner::Error { - source_info: SourceInfo::new(Pos::new(4, 0), Pos::new(4, 0)), + source_info: error_source_info, inner: runner::RunnerError::AssertFailure { actual: "int <2>".to_string(), expected: "greater than int <5>".to_string(), @@ -784,10 +880,12 @@ jsonpath "$.count" >= 5 assert: true, }; assert_eq!( - error_string(filename, content, &error, false), + error_string(filename, content, &error, Some(entry_source_info), false), r#"Assert failure --> test.hurl:4:0 | + | GET http://api + | ... 4 | jsonpath "$.count" >= 5 | actual: int <2> | expected: greater than int <5> @@ -807,17 +905,40 @@ HTTP/1.0 200 actual: "

Hello

\n\n".to_string(), expected: "

Hello

\n".to_string(), }; - let error = - runner::Error::new(SourceInfo::new(Pos::new(3, 4), Pos::new(4, 1)), inner, true); + let error_source_info = SourceInfo::new(Pos::new(3, 4), Pos::new(4, 1)); + let entry_source_info = SourceInfo::new(Pos::new(1, 1), Pos::new(1, 20)); + let error = runner::Error::new(error_source_info, inner, true); assert_eq!( - error_string(filename, content, &error, false), + error_string(filename, content, &error, Some(entry_source_info), false), r#"Assert body value --> test.hurl:3:4 | + | GET http://localhost + | ... 3 | ```

Hello

| ^ actual value is <

Hello

> + |"# + ) + } + + #[test] + fn test_parsing_error() { + let content = "GET abc"; + let filename = "test.hurl"; + let error = hurl_core::parser::Error { + pos: Pos::new(1, 5), + recoverable: false, + inner: hurl_core::parser::ParseError::UrlInvalidStart, + }; + assert_eq!( + error_string(filename, content, &error, None, false), + r#"Parsing URL + --> test.hurl:1:5 + | + 1 | GET abc + | ^ expecting http://, https:// or {{ |"# ) }