orange-opensource / hurl Goto Github PK
View Code? Open in Web Editor NEWHurl, run and test HTTP requests with plain text.
Home Page: https://hurl.dev
License: Apache License 2.0
Hurl, run and test HTTP requests with plain text.
Home Page: https://hurl.dev
License: Apache License 2.0
Add an option (with hurlfmt
?) to export an Hurl file (the last) to json, to provide an agnostic file format.
The current query cookie return the cookie value (and ignores the other attributes such as path, domain, ...)
cookie "theme" equals "light"
It would be interesting to fully support cookies as defined in the http spec.
the query cookie could return a Cookie Object instead of a simple string.
This object would include a mandatory string value, an optional domain, an option value, ...
The predicate equals (and matches?) could then be applied on this query taking a String value.
There are several options for the semantic of this String value.
For example
cookie "sessionToken" equals "abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT"
the path and domain must not be defined in the response cookie
cookie "LSID" equals "DQAAAK…Eaem_vYg; Path=/accounts; Expires=Wed, 13 Jan 2021 22:23:01 GMT; Secure; HttpOnly"
the order of attributes does not matter
cookie "LSID" matches "DQAAAK…Eaem_vYg; Path=/accounts; Expires=.*; Secure; HttpOnly"
when you need to use a regex you explicitly use the matched predicate
instead it could be easier to omit the attribute to ignore the attribute.
cookie "LSID" equals "DQAAAK…Eaem_vYg; Path=/accounts; Secure; HttpOnly"
you don't check the Expires attribute at all. It does not matter whether it is present on not.
But then, how do you check whether a cookie is a session cookie?
Another option: ´cookie´ could be extended as a query expression like jsonpath/xpath:
Check value:
cookie "toto" equals "tata"
Check expires:
cookie "toto[expires]" equals "Wed, 09 Jun 2021 10:18:14 GMT"
cookie "toto[expires]" exist
Check Path:
cookie "toto[path]" matches "/test.*"
We can borrow XPath syntax for attribute:
cookie "toto[@path]" equals "/domain"
Or we can create another type of query ´cookiepath’ and keep the actual ´cookie´ query.
Possible query syntax:
cookie "toto[expires]" exist
cookie "toto[@expires]" exist
cookie "toto.expires" exist
cookie "toto@expires" exist
=> cookie "toto[Expires]" exist
is accepted as the syntax
Possible attributes:
Expires=
Max-Age=
Domain=
Path=
Secure
HttpOnly
SameSite=Strict
SameSite=Lax
SameSite=None
cookie "toto[max-age]" exist
cookie "toto[Max-Age]" exist
equivalent
Template variable should probably also be supported for the cookie name.
cookie "{{cookie_name}}[Expired]"
Definition of queries in the grammar
xpath-query = "xpath" sp sp* quoted-string
cookie-query = "cookie" sp sp* quoted-string
contrary to xpath, the cookie-query is both specific to hurl and very easy.
it could be fully described as follow
cookie-query = "cookie" sp sp* """ cookie-query-expr """
cookie-query-expr = cookie-query-name ( "[" sp* cookie-query-attribute sp* "]" )
cookie-query-name = <[a-zA-Z0-9{}]+>
cookie-query-attribute = Value | value
| Expires | expires
| Max-Age | max-age
| Domain | domain
| Path | path
| Secure | secure
| HttpOnly | httponly
| SameSite | samesite
The parsing implementation can choose to be a bit stricter than the grammar
for example,
rejecting escape character
cookie "toto\u{5B}Expires]"
accepting variable only for the cookie name
cookie "toto[{{field}}]"
by default, curl might add the Expect: 100-continue
header automatically, for example for a PUT request.
In Hurl, the header will never be sent implicitly.
It would have to be added explicitly in the request header.
When exporting an Hurl file containing a cookie query with Expires
attributes, the serialized attribute is Expire
:
GET http://localhost
HTTP/1.1 200
[Asserts]
cookie "Session[Expires]" exists
$ hurlfmt --format json /tmp/test.hurl
{
"entries": [
{
"request": {
"method": "GET",
"url": "http://localhost"
},
"response": {
"version": "HTTP/1.1",
"status": 200,
"asserts": [
{
"query": {
"type": "cookie",
"expr": "Session[Expire]"
},
"predicate": {
"type": "exist"
}
}
]
}
}
]
}
Hi guys 😄
In the context of our project we see two huge advantages using hurl :
customer paths
on our web application. This allows us to guarantee the non-regression between versions.However, we cannot "yet" use hurl for our metrology
tests, forcing us to duplicate all our scenarios in other tools that are less accessible to non-developers... 😢
Currently when I launch this command
hurl a.hurl b.hurl c.hurl
hurl runs each *.hurl
file one time, first a.hurl, then b.hurl, then c.hurl.
─ BEGIN
├─ a.hurl
├─ b.hurl
├─ c.hurl
─ END
I propose you to add the --concurrency
option allowing hurl to launch multiple runs of each *.hurl file at a time, for example:
hurl --concurrency 3 a.hurl b.hurl c.hurl
─ BEGIN
├─ a.hurl ├─ a.hurl ├─ a.hurl
├─ b.hurl ├─ b.hurl ├─ b.hurl
├─ c.hurl ├─ c.hurl ├─ c.hurl
─ END
What do you think about it ?
Currently only cargo build is used in the CI to build hurl executable
Update your Cargo.toml so that you can also run cargo install
$ cargo install
error: found a virtual manifest at `...hurl/Cargo.toml` instead of a package manifest
When performing a GET on localhost:8000, Hurl set the Host
request header to localhost
whereas curl set this header to localhost:8000
.
Hurl should be aligned with curl and set the Host
header to localhost:8000
.
There is an integration test on the subject:
hurl/integration/tests/headers.py
Line 9 in 3d2d9e3
the jsonpath query $.[0].name
should be valid
though this is probably better written as $[0].name
With the following json response body
[
{ "id": 1, "name": "Bob"},
{ "id": 2, "name": "Bill"}
]
it should return "Bob"
Here is a typical assert error in hurl.
error: Assert Failure
--> tests/error_assert_value_error.hurl:8:0
|
8 | jsonpath "$.count" greaterThan 5
| actual: int <2>
| expected: greater than int <5>
|
This error is quite clear, but for string comparison, it might not be as clear.
For example, for multiline string, you may receive the following error
error: Assert Failure
--> test.hurl:4:0
|
4 | body equals "one\ntwo\nthree"
| actual: string <one
| to
| three>
| expected: string <one
| two
| three>
|
It could be better to display both the actual and expected strings on one line.
Converting the newline character to \n
The previous error would become:
error: Assert Failure
--> test.hurl:4:0
|
4 | body equals "one\ntwo\nthree"
| actual: string <one\nto\nthree>
| expected: string <one\ntwo\nthree>
|
To go one step further, the different characters could be highlighted (for example in red)
one\ntwo\nthree
When exporting "greater than" and "less than" predicates, the value for type
in the JSON export should reflect the grammar naming;
For example:
"less than" predicate is defined as less-predicate in Hurl grammar and should be export as {"type":"less"...}
use --output option with value (text, json, html)
instead of dedicated option --json and --html
Add curl option --compressed:
Note that the body of all the other responses won't be decompressed.
add the 4 comparison predicates:
They can all take an Integer or a float param as defined in the grammar
Currently, regex patterns are used in :
GET http://localhost:8000/assert-regex
HTTP/1.0 200
[Asserts]
regex "Hello ([0-9]+)!" not exists
regex "Hello ([a-zA-Z]+)!" equals "World"
body matches "Hello [a-zA-Z]+!"
Pattern in Hurl grammar use quoted-string
: the problem is that backslash in quoted-string
should be escaped. So to use special character in pattern (like \d
, \s
), backslash should be escaped, degrading the readability of the pattern:
regex "Hello (\\d)!" not exists
In Rust, Python, Kotlin, raw strings are used to improve the regex readability. In Rust, for instance:
use regex::Regex;
let re = Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
assert!(re.is_match("2014-01-01"));
In the Hurl grammar, we already have raw string (```something\ntutu``` is literally the string "something\ntutu" without a newline between something and tutu). We could reuse this syntax when using regex query or matches predicates:
Before:
GET http://localhost:8000/assert-regex
HTTP/1.0 200
[Asserts]
regex "abc(\\d+)!" exists
jsonpath "$.date1" matches "\\d{4}-\\d{2}-\\d{2}"
After:
GET http://localhost:8000/assert-regex
HTTP/1.0 200
[Asserts]
regex ```abc(\d+)!``` exists
jsonpath "$.date1" matches ```\d{4}-\d{2}-\d{2}```
We could also introduce another syntax, like Python raw string and Rust raw string and keep ``` for body raw string:
GET http://localhost:8000/assert-regex
HTTP/1.0 200
[Asserts]
regex r"abc(\d+)!" exists
jsonpath "$.date1" matches r"\d{4}-\d{2}-\d{2}"
raw-string like r"abcd" could be used anywhere a quoted-string is used (not limited to regex capture and matches predicate)
The server might send several response status lines in one HTTP exchange
for example
HTTP/1.1 100 Continue
HTTP/1.1 200 OK
The response status line defined in the Hurl file should match the last status line received.
It looks like when using body assertions there is no simple way to compare actual and expected values.
E.g. : I make a request that returns body
{
"id": 0,
"name": "Frieda",
"picture": "images/scottish-terrier.jpeg",
"age": 3,
"breed": "Scottish Terrier",
"location": "Lisco, Alabama"
}
In my hurl file is as follows :
# Get a doggy thing:
GET https://example.net/api/dogs/
HTTP/1.1 200
{
"id": 0,
"name": "Julien",
"picture": "images/scottish-terrier.jpeg",
"age": 3,
"breed": "Scottish Terrier",
"location": "Lisco, Alabama"
}
<img width="1033" alt="Capture d’écran 2020-11-20 à 14 55 40" src="https://user-images.githubusercontent.com/113336/99807944-77a2ee80-2b40-11eb-8855-ce559a130fcf.png">
The output is
error: Assert Body Value
--> ./integration/test-files/nominal/edito/accessory-orange.hurl:36:1
|
36 | {
| ^ actual value is < {
"id": 0,
"name": "Frieda",
"picture": "images/scottish-terrier.jpeg",
"age": 3,
"breed": "Scottish Terrier",
"location": "Lisco, Alabama"
} >
Would it be possible to have a simple way to diff the actual and expected ? Like what is possible with JUnit failed string comparisons.
The not
qualifier in the predicate negates most of the time the predicate result.
But there are a few cases, for which it does not invert a predicate failure.
Hurl detects some inconsistencies between the predicate and the value to which it is applied and prefer to make the assert fail.
All the following predicates fail:
equals 2
equals null
contains "toto"
Negating the predicate does not necessarily make the predicate succeeds.
not equals 2
not equals null
not contains "toto" => failure
The last one fails because the contains predicate only apply to String value, and thus it does not make sense to apply it to a integer value.
This is equivalent to a type error.
All the following predicates fail:
exist
equals 1
contains "toto"
all these predicates will success if there are negated
not exist
not equals 1
not contains "toto"
There can't be any "type checking" when no value is returned.
for example, the Secure cookie attribute, it is present or not
but it does not have a value
All the following predicates fail:
equals true
equals false
equals 1
contains "toto"
All these predicates will fail even if they are negated.
not equals true
not equals false
not equals 1
not contains "toto"
They must be applied to a value.
exist
is the only predicate that can be applied.
Hurl should support a user defined within a url for basic authentication
$ echo GET http://bob:secret@localhost:8000/basic-authentication | hurl
error: Parsing literal
--> -:1:22
|
1 | GET http://bob:secret@localhost:8000/basic-authentication
| ^ expecting 'line_terminator'
|
Response body can be tested directly without explicit asserts as follow:
test.hurl
1 GET http://example.com/text
2 HTTP/1.1 200
3 ```
4 one
5 two
6 three
7 ```
If the server returns the following response
one
to
three
the following error will be produced:
error: Assert Body Value
--> test.hurl:4:1
|
4 | one
| ^ actual value is <one
| to
| three>
Instead of taking into account the full multiline body, we could focus on the first line that differs.
The previous errors would become:
error: Assert Body Value
--> test.hurl:5:1
|
5 | two
| ^ actual value is <to>
|
This fits quite well with the line-oriented structure of hurl files.
Testing json output can also be a good example.
test.hurl
1 GET http://example.com/json
2 HTTP/1.1 200
3 {
4 "name": "Bob",
5 "age": 32
6 }
If the server returns the following response
{
"name": "Bob",
"age": 30
}
The following error will be produced:
error: Assert Body Value
--> test.hurl:3:1
|
3 | {
| ^ actual value is <{
| "user": "Bob"
| "age": "30"
| }>
Taking into account only the first line in error, we get the following error instead:
error: Assert Body Value
--> test.hurl:5:1
|
5 | "age": 32
| ^ actual value is < "age": 30>
|
We could even position the error at the exact different chracter
error: Assert Body Value
--> test.hurl:5:12
|
5 | "age": 32
| ^ actual value is <0>
|
Cookies defined the request Cookies section should just add cookies in the request but should not change cookie storage.
This is consistent with curl.
For example: Send cookie1 in the request and cookie2 set from server endpoind
$ curl \
--cookie cookie1=value1 \
--cookie-jar /tmp/cookies \
http://httpbin.org/cookies/set/name2/value2
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>Redirecting...</title>
<h1>Redirecting...</h1>
<p>You should be redirected automatically to target URL: <a href="/cookies">/cookies</a>. ..
$ cat /tmp/cookies
# Netscape HTTP Cookie File
# https://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
httpbin.org FALSE / FALSE 0 name2 value2
with the current hurl
$ cat <<END | hurl --cookie-jar /tmp/cookies
GET http://httpbin.org/cookies/set/cookie2/value2
[Cookies]
cookie1: value1
END
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>Redirecting...</title>
<h1>Redirecting...</h1>
<p>You should be redirected automatically to target URL: <a href="/cookies">/cookies</a>...
$ cat /tmp/cookies
# Netscape HTTP Cookie File
# This file was generated by hurl
httpbin.org FALSE / FALSE 0 cookie1 value1
httpbin.org FALSE / FALSE 0 cookie2 value2
--include
options seems to print only the last entry headers.
Should it print all the entry headers or only the last entry ones ? In any case, man/documentation should explicit what it does.
travis.org is closing down
Currently, setting a cookie via the cookie section updates the cookiejar
in order to send a cookie without updated the cookiejar, an explicit header 'Cookie' must be used
In the future, we should be able to interact with the runner in a hurl file with predefined directives
(such as clear cookie storage)
Values used in Hurl in Captures/Assert are typed (integer, boolean, string,...)
On the opposite, the input variables (from the option --variable) are all strings.
sample.hurl
1 GET http://localhost:8000/hello
2 HTTP/* 200
3 [Asserts]
4 variable "count" equals "1"
5 variable "count" equals 1
$ hurl --variable count=1 sample.hurl
error: Assert Failure
--> /tmp/sample.hurl:5:0
|
5 | variable "count" equals 1
| actual: string <1>
| expected: int <1>
|
It will be interesting to type the input variable implicitly.
The string <1> should be treated as integer, therefore the first assert should fail rather than the second.
Similarly, the value should be treated as bool.
To force a string value, the value can be quoted.
This is consistent with the predicate value.
For example, the id <123> is passed as string as follow:
hurl --variable id='"123"' sample.hurl
Add the predicates isInteger, isFloat, isBoolean, isString, isCollection
for example, for the following json response
{
"count": 4,
}
The following asserts fails
jsonpath "$.count" isString
jsonpath "$.count" isFloat
while the following assert is successful
jsonpath "$.count" isInteger
Get the duration in ms of the HTTP exchange.
MultipartFormData is not present in json export.
With this file:
POST http://localhost:8000/multipart-form-data
[MultipartFormData]
key1: value1
upload1: file,hello.txt;
upload2: file,hello.html;
upload3: file,hello.txt; text/html
HTTP/1.0 200
and
hurl --json /tmp/test.json -v integration/tests/multipart_form_data.hurl
The report is :
[
{
"filename": "integration/tests/multipart_form_data.hurl",
"entries": [
{
"request": {
"method": "POST",
"url": "http://localhost:8000/multipart-form-data",
"queryString": [],
"headers": [],
"cookies": [],
"body": ""
},
"response": {
"httpVersion": "HTTP/1.0",
"status": 200,
"cookies": [],
"headers": [
{
"name": "Content-Type",
"value": "text/html; charset=utf-8"
},
{
"name": "Content-Length",
"value": "0"
},
{
"name": "Server",
"value": "Werkzeug/1.0.1 Python/3.8.5"
},
{
"name": "Date",
"value": "Mon, 02 Nov 2020 13:00:52 GMT"
}
]
},
"captures": [],
"asserts": [
{
"actual": "1.0",
"expected": "1.0"
},
{}
],
"time": 9
}
],
"success": true,
"time": 9,
"cookies": []
}
]
It is possible to have multiple Content-Encoding in the order in which they were applied
Content-Encoding: gzip, identity
Content-Encoding: deflate, gzip
When typing hurl
+ enter, Hurl's usage is shown. It should end with a newline.
Actual:
~/Documents/Dev/hurl-jvm $ hurl
hurl 0.99.13
Run hurl FILE(s) or standard input
USAGE:
hurl [OPTIONS] [--] [INPUT]...
OPTIONS:
--append Append sessions to json output
--color Colorize Output
--compressed Request compressed response (using deflate or gzip)
--connect-timeout <SECONDS> Maximum time allowed for connection
-b, --cookie <FILE> Read cookies from FILE
-c, --cookie-jar <FILE> Write cookies to FILE after running the session (only for one session)
...
--variable <NAME=VALUE>... Define a variable
-v, --verbose Turn on verbose output
-h, --help Prints help information
-V, --version Prints version information
ARGS:
<INPUT>... Sets the input file to use~/Documents/Dev/hurl-jvm $
Expected:
~/Documents/Dev/hurl-jvm $ hurl
hurl 0.99.13
Run hurl FILE(s) or standard input
USAGE:
hurl [OPTIONS] [--] [INPUT]...
OPTIONS:
--append Append sessions to json output
--color Colorize Output
--compressed Request compressed response (using deflate or gzip)
--connect-timeout <SECONDS> Maximum time allowed for connection
-b, --cookie <FILE> Read cookies from FILE
-c, --cookie-jar <FILE> Write cookies to FILE after running the session (only for one session)
...
--variable <NAME=VALUE>... Define a variable
-v, --verbose Turn on verbose output
-h, --help Prints help information
-V, --version Prints version information
ARGS:
<INPUT>... Sets the input file to use
~/Documents/Dev/hurl-jvm $
When exporting greater and less predicates in JSON, value is exported as string.
integration/tests/assert_json.hurl :
GET http://localhost:8000/assert-json
HTTP/1.0 200
[Asserts]
...
jsonpath "$.count" greaterThan 1
In integration/tests/assert_json.json:
{
"query": {
"type": "jsonpath",
"expr": "$.count"
},
"predicate": {
"type": "greater-than",
"value": "1"
}
}
Currently, variables can be set at the command-line with the option --variable <name=value>
It can become a bit tedious when the number of variables increases.
Hurl could also read variables from an input properties file with an option like --variables-file <FILE>
The values defined in the properties will be exactly the same as the one define din the command-line.
Predicates with numbers such as (equals, greaterThan, ...) are "arithmetic".
For example:
for the following json response
{
"count": 5,
"total": 50.0
}
All the following asserts are valid
jsonpath "$.count" equals 5
jsonpath "$.count" equals 5.0
jsonpath "$.count" greaterThan 1
jsonpath "$.count" greaterThan 1.0
jsonpath "$.total" equals 50
jsonpath "$.total" equals 50.0
jsonpath "$.total" greaterThan 0.2
jsonpath "$.total" greaterThan 0
The value type can be checked with an additional predicate
jsonpath "$.count" isInteger
jsonpath "$.total" isFloat
Additional:
The intent for the following assert might not be clear:
jsonpath "$.count" equals 5.0
Do we expect a float value?
In this case, Hurl could emit a warning like:
"You expected value should be replaced by an integer value"
Stop between each request.
Map commands to keys.
Start by implemented the following commands:
Let's say we have file1.hurl, file2.hurl file3.hurl.
To get a json view of all files:
hurl --json /tmp/files.json file1.hurl file2.hurl file3.hurl
=> /tmp/files.json does represent the 3 files
hurl --json /tmp/files.json --append file1.hurl
hurl --json /tmp/files.json --append file2.hurl
hurl --json /tmp/files.json --append file3.hurl
=> /tmp/files.json does represent the 3 files
To get a html view of all files:
hurl --html /tmp/ file1.hurl file2.hurl file3.hurl
=> /tmp/*.html does represent the 3 files
hurl --json /tmp/files.json --append --html /tmp/ file1.hurl
hurl --json /tmp/files.json --append --html /tmp/ file2.hurl
hurl --json /tmp/files.json --append --html /tmp/ file3.hurl
=> /tmp/*.html does represent the 3 files
Textual queries such as xpath and jsonpath assume that the response body is text.
If the response body has been compressed (protocol given in response header Content-Encoding), it must be decompressed automatically.
Hurl seems to add a default content type for file form datas:
POST http://localhost:8000/multipart-form-data
[MultipartFormData]
key1: value1
upload1: file,hello.txt;
upload2: file,hello.html; text/html
upload3: file,hello.txt; text/plain
HTTP/1.0 200
upload1 file is sent with content type "text/plain" whereas no content type has been specified.
There are two options:
Each part MAY have an (optional) "Content-Type" header field, which
defaults to "text/plain". If the contents of a file are to be sent,
the file data SHOULD be labeled with an appropriate media type, if
known, or "application/octet-stream".
So in this case, upload1 content type should be "application/octet-stream"
Curl seems to use option 2:
const char *Curl_mime_contenttype(const char *filename)
{
/*
* If no content type was specified, we scan through a few well-known
* extensions and pick the first we match!
*/
struct ContentType {
const char *extension;
const char *type;
};
static const struct ContentType ctts[] = {
{".gif", "image/gif"},
{".jpg", "image/jpeg"},
{".jpeg", "image/jpeg"},
{".png", "image/png"},
{".svg", "image/svg+xml"},
{".txt", "text/plain"},
{".htm", "text/html"},
{".html", "text/html"},
{".pdf", "application/pdf"},
{".xml", "application/xml"}
};
But I prefer option1 => no implicit.
In any case, we should update the doc to explain the behaviour.
First of all: thanks for building this! I really like the general idea.
A great feature would be imports to reuse requests (e.g. login flows) and to be able to scale larger test suites.
Add the -user option from curl
in order to specify the user name and password to use for server authentication.
This is useful when querying an API for which you need to provide an Authorization header for each request.
The following assert jsonpath "$.id" not equals null
should succeed when the type returned by the query $.id
is dfferent from null.
for example for the body {"id": 10}
How to use environment variables in hurl files?
Explicitly by prefixing your variables with env
for example
GET {{env.url}}
It's common to provide a checksum for HTTP resources to be verified.
It could be useful to add a checksum body query in asserts section.
A possible syntax:
GET https://sample.net/toto.tar.bz2
HTTP/1.1 200
[Asserts]
checksum "md5" "4b6fb79adc54152a9e5dc6aa3222b306"
GET https://github.com/Orange-OpenSource/hurl/releases/download/0.99.14/hurl-0.99.14-x86_64-osx.tar.gz
HTTP/1.1 200
[Asserts]
checksum "sha256" equals "b63e2a825d21a3f71f6eeaa439a0b6c8b5126d85c42efc14155b7ff943107f66"
Maybe hash
(vs checksum
) could be a better query name :
GET https://github.com/Orange-OpenSource/hurl/releases/download/0.99.14/hurl-0.99.14-x86_64-osx.tar.gz
HTTP/1.1 200
[Asserts]
hash "sha256" equals "b63e2a825d21a3f71f6eeaa439a0b6c8b5126d85c42efc14155b7ff943107f66"
A third possible syntax: just use the hash algo type
GET https://github.com/Orange-OpenSource/hurl/releases/download/0.99.14/hurl-0.99.14-x86_64-osx.tar.gz
HTTP/1.1 200
[Asserts]
sha256 equals "b63e2a825d21a3f71f6eeaa439a0b6c8b5126d85c42efc14155b7ff943107f66"
So the possible syntax for the query:
checksum
where can be "sha1", "sha256", "md5"hash
where can be "sha1", "sha256", "md5"The two first has the advantage to be flexible for future algo, the last being more static and more succinct.
Note: the return type of the hash should be a string (lowercase, only 0-9, a-f), as there is no binary type in Hurl (for the moment).
So, while this asserts is syntactically correct, it could never be true: sha256 equals "zzz"
Hi,
I have a test with :
GET http://someUrl
Accept-Encoding: gzip
HTTP/1.1 200
Content-Encoding: gzip
My server actually returns :
Content-Encoding: gzip
Content-Encoding: gzip
Which is a bug, but that's another story...
The assertion passes, and maybe it's OK.
But when I change the assertion to :
GET http://someUrl
Accept-Encoding: gzip
HTTP/1.1 200
Content-Encoding: "gzip"
It fails with
|
21 | Content-Encoding: "gzip"
| ^^^^^^ actual value is <["gzip", "gzip"]>
Do you think that it is logical ? There is no mention of Header: "expectedValue"
, only Header: expectedValue
. I mean is the Header: expectedValue
syntax just a contains()
?
Maybe just a clarification could be added...
Thanks
Wildcard *
can be used in HTTP version to disable any check on the HTTP version:
GET http://localhost:8000/timeout
HTTP/* 200
It could be useful to also support wildcard for status code.
For instance:
GET http://localhost:8000/timeout
HTTP/* *
[Asserts]
status not equals 200
Status code is explicitly tested not to be equals to 200
Hi guys 😄
Currently when I launch this command
hurl a.hurl b.hurl c.hurl
hurl runs each *.hurl
file sequentially, first a.hurl, then b.hurl, then c.hurl.
# tests started sequentially
hurl a.hurl b.hurl c.hurl
─ BEGIN
├─ a.hurl
├─ b.hurl
├─ c.hurl
─ END
I propose you to add the --parallel
option allowing hurl to run *.hurl
files in parallel:
# all tests started at same time
hurl --parallel a.hurl b.hurl c.hurl
─ BEGIN
├─ a.hurl ├─ b.hurl ├─ c.hurl
─ END
# tests started two at a time
hurl --parallel 2 a.hurl b.hurl c.hurl
─ BEGIN
├─ a.hurl ├─ b.hurl
├─ c.hurl
─ END
What do you think about it?
For some use-cases we would like to check that the http response has been returned within x milliseconds, do you think it has a chance to be implemented ? Maybe we could think about the response payload size also (if Content-Length
header is not set correctly)
What are your thoughts ?
Currently, templates in json body is supported only for string
{
"name": "{{name}}",
"age": 30
}
the following file is not supported
{
"name": "{{name}}",
"age": {{age}}
}
Note that It is still possible to send this json body with a raw string.
But the content is not validated as json.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.