diff --git a/README.md b/README.md
index a2b8b811e38..171ec372cc0 100644
--- a/README.md
+++ b/README.md
@@ -183,6 +183,7 @@ Table of Contents
* [HTTP Headers](#http-headers)
* [Query Params](#query-params)
* [Basic Authentication](#basic-authentication)
+ * [Passing Data between Requests ](#passing-data-between-requests)
* [Sending Data](#sending-data)
* [Sending HTML Form Data](#sending-html-form-data)
* [Sending Multipart Form Data](#sending-multipart-form-data)
@@ -191,12 +192,19 @@ Table of Contents
* [Templating a XML Body](#templating-a-xml-body)
* [Using GraphQL Query](#using-graphql-query)
* [Testing Response](#testing-response)
+ * [Testing Status Code](#testing-status-code)
* [Testing Response Headers](#testing-response-headers)
* [Testing REST APIs](#testing-rest-apis)
* [Testing HTML Response](#testing-html-response)
* [Testing Set-Cookie Attributes](#testing-set-cookie-attributes)
* [Testing Bytes Content](#testing-bytes-content)
* [SSL Certificate](#ssl-certificate)
+ * [Checking Full Body](#checking-full-body)
+ * [Reports](#reports)
+ * [HTML Report](#html-report)
+ * [JUnit Report](#junit-report)
+ * [TAP Report](#tap-report)
+ * [JSON Output](#json-output)
* [Others](#others)
* [HTTP Version](#http-version)
* [Polling and Retry](#polling-and-retry)
@@ -267,6 +275,18 @@ oriented output, you can use [`--test` option]:
$ hurl --test sample.hurl
```
+A particular response can be saved with [`[Options] section`][option]:
+
+```hurl
+GET https://example.ord/cats/123
+[Options]
+output: cat123.txt # use - to output to stdout
+HTTP 200
+
+GET https://example.ord/dogs/567
+HTTP 200
+```
+
You can check [Hurl tests suite] for more samples.
@@ -278,6 +298,15 @@ A simple GET:
GET https://example.org
```
+Requests can be chained:
+
+```hurl
+GET https://example.org/a
+GET https://example.org/b
+HEAD https://example.org/c
+GET https://example.org/c
+```
+
[Doc](https://hurl.dev/docs/request.html#method)
### HTTP Headers
@@ -311,6 +340,8 @@ Or:
GET https://example.org/news?order=newest&search=something%20to%20search&count=100
```
+> With `[QueryStringParams]` section, params don't need to be URL escaped.
+
[Doc](https://hurl.dev/docs/request.html#query-parameters)
### Basic Authentication
@@ -331,9 +362,42 @@ GET https://example.org/protected
Authorization: Basic Ym9iOnNlY3JldA==
```
-Basic authentication allows per request authentication.
-If you want to add basic authentication to all the requests of a Hurl file
-you could use [`-u/--user` option].
+Basic authentication section allows per request authentication. If you want to add basic authentication to all the
+requests of a Hurl file you could use [`-u/--user` option]:
+
+```shell
+$ hurl --user bob=secret login.hurl
+```
+
+[`--user`] option can also be set per request:
+
+```hurl
+GET https://example.org/login
+[Options]
+user: bob:secret
+HTTP 200
+
+GET https://example.org/login
+[Options]
+user: alice:secret
+HTTP 200
+```
+
+### Passing Data between Requests
+
+[Captures] can be used to pass data from one request to another:
+
+```hurl
+POST https://sample.org/orders
+HTTP 201
+[Captures]
+order_id: jsonpath "$.order.id"
+
+GET https://sample.org/orders/{{order_id}}
+HTTP 200
+```
+
+[Doc](https://hurl.dev/docs/capturing-response.html)
## Sending Data
@@ -514,6 +578,44 @@ GraphQL queries can also use [Hurl templates].
## Testing Response
+Responses are optional, everything after `HTTP` is part of the response asserts.
+
+```hurl
+# A request with (almost) no check:
+GET https://foo.com
+
+# A status code check:
+GET https://foo.com
+HTTP 200
+
+# A test on response body
+GET https://foo.com
+HTTP 200
+[Asserts]
+jsonpath "$.state" == "running"
+```
+
+### Testing Status Code
+
+```hurl
+GET https://example.org/order/435
+HTTP 200
+```
+
+[Doc](https://hurl.dev/docs/asserting-response.html#version-status)
+
+```hurl
+GET https://example.org/order/435
+# Testing status code is in a 200-300 range
+HTTP *
+[Asserts]
+status >= 200
+status < 300
+```
+
+[Doc](https://hurl.dev/docs/asserting-response.html#status-assert)
+
+
### Testing Response Headers
Use implicit response asserts to test header values:
@@ -539,6 +641,16 @@ header "Location" contains "www.example.net"
[Doc](https://hurl.dev/docs/asserting-response.html#header-assert)
+Implicit and explicit asserts can be combined:
+
+```hurl
+GET https://example.org/index.html
+HTTP 200
+Set-Cookie: theme=light
+Set-Cookie: sessionToken=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT
+[Asserts]
+header "Location" contains "www.example.net"
+```
### Testing REST APIs
@@ -563,27 +675,6 @@ jsonpath "$.created" isIsoDate
[Doc](https://hurl.dev/docs/asserting-response.html#jsonpath-assert)
-Testing status code:
-
-```hurl
-GET https://example.org/order/435
-HTTP 200
-```
-
-[Doc](https://hurl.dev/docs/asserting-response.html#version-status)
-
-```hurl
-GET https://example.org/order/435
-# Testing status code is in a 200-300 range
-HTTP *
-[Asserts]
-status >= 200
-status < 300
-```
-
-[Doc](https://hurl.dev/docs/asserting-response.html#status-assert)
-
-
### Testing HTML Response
```hurl
@@ -646,16 +737,141 @@ certificate "Serial-Number" matches /[\da-f]+/
[Doc](https://hurl.dev/docs/asserting-response.html#ssl-certificate-assert)
+### Checking Full Body
+
+Use implicit body to test an exact JSON body match:
+
+```hurl
+GET https://example.org/api/cats/123
+HTTP 200
+{
+ "name" : "Purrsloud",
+ "species" : "Cat",
+ "favFoods" : ["wet food", "dry food", "any food"],
+ "birthYear" : 2016,
+ "photo" : "https://learnwebcode.github.io/json-example/images/cat-2.jpg"
+}
+```
+
+[Doc](https://hurl.dev/docs/asserting-response.html#json-body)
+
+Or an explicit assert file:
+
+```hurl
+GET https://example.org/index.html
+HTTP 200
+[Asserts]
+body == file,cat.json;
+```
+
+[Doc](https://hurl.dev/docs/asserting-response.html#body-assert)
+
+Implicit asserts supports XML body:
+
+```hurl
+GET https://example.org/api/catalog
+HTTP 200
+
+
+
+ Gambardella, Matthew
+ XML Developer's Guide
+ Computer
+ 44.95
+ 2000-10-01
+ An in-depth look at creating applications with XML.
+
+
+```
+
+[Doc](https://hurl.dev/docs/asserting-response.html#xml-body)
+
+Plain text:
+
+~~~hurl
+GET https://example.org/models
+HTTP 200
+```
+Year,Make,Model,Description,Price
+1997,Ford,E350,"ac, abs, moon",3000.00
+1999,Chevy,"Venture ""Extended Edition""","",4900.00
+1999,Chevy,"Venture ""Extended Edition, Very Large""",,5000.00
+1996,Jeep,Grand Cherokee,"MUST SELL! air, moon roof, loaded",4799.00
+```
+~~~
+
+[Doc](https://hurl.dev/docs/asserting-response.html#multiline-string-body)
+
+
+One line:
+
+```hurl
+POST https://example.org/helloworld
+HTTP 200
+`Hello world!`
+```
+
+[Doc](https://hurl.dev/docs/asserting-response.html#oneline-string-body)
+
+File:
+
+```hurl
+GET https://example.org
+HTTP 200
+file,data.bin;
+```
+
+[Doc](https://hurl.dev/docs/asserting-response.html#file-body)
+
+
+## Reports
+
+### HTML Report
+
+```shell
+$ hurl --test --report-html build/report/ *.hurl
+```
+
+[Doc](https://hurl.dev/docs/running-tests.html#generating-report)
+
+### JUnit Report
+
+```shell
+$ hurl --test --report-junit build/report.xml *.hurl
+```
+
+[Doc](https://hurl.dev/docs/running-tests.html#generating-report)
+
+### TAP Report
+
+```shell
+$ hurl --test --report-tap build/report.txt *.hurl
+```
+
+[Doc](https://hurl.dev/docs/running-tests.html#generating-report)
+
+### JSON Output
+
+A structured output of running Hurl files can be obtained with [`--json` option]. Each file will produce a JSON export of the run.
+
+
+```shell
+$ hurl --json *.hurl
+```
+
## Others
### HTTP Version
-Testing HTTP version (1.0, 1.1, 2 or 3):
+Testing HTTP version (HTTP/1.0, HTTP/1.1, HTTP/2 or HTTP/3):
```hurl
-GET https://example.org/order/435
+GET https://foo.com
HTTP/3 200
+
+GET https://bar.com
+HTTP/2 200
```
[Doc](https://hurl.dev/docs/asserting-response.html#version-status)
@@ -706,7 +922,7 @@ HTTP 200
### Skipping Requests
```hurl
-# a, b, d are runner, c is skipped
+# a, c, d are run, b is skipped
GET https://example.org/a
GET https://example.org/b
@@ -792,7 +1008,17 @@ Action: GetCallerIdentity
Version: 2011-06-15
```
-The Access Key is given per [`--user`].
+The Access Key is given per [`--user`], either with command line option or within the [`[Options]`][option] section:
+
+```hurl
+POST https://sts.eu-central-1.amazonaws.com/
+[Options]
+aws-sigv4: aws:amz:eu-central-1:sts
+user: bob=secret
+[FormParams]
+Action: GetCallerIdentity
+Version: 2011-06-15
+```
[Doc](https://hurl.dev/docs/manual.html#aws-sigv4)
@@ -1252,6 +1478,9 @@ Please follow the [contrib on Windows section].
[`--user`]: https://hurl.dev/docs/manual.html#user
[Hurl templates]: https://hurl.dev/docs/templates.html
[AWS Signature Version 4]: https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html
+[Captures]: https://hurl.dev/docs/capturing-response.html
+[option]: https://hurl.dev/docs/request.html#options
+[`--json` option]: https://hurl.dev/docs/manual.html#json
[GitHub]: https://github.com/Orange-OpenSource/hurl
[Hurl latest GitHub release]: https://github.com/Orange-OpenSource/hurl/releases/latest
[AUR]: https://wiki.archlinux.org/index.php/Arch_User_Repository
diff --git a/docs/frequently-asked-questions.md b/docs/frequently-asked-questions.md
index 984695f6fc3..aa0df200743 100644
--- a/docs/frequently-asked-questions.md
+++ b/docs/frequently-asked-questions.md
@@ -182,10 +182,9 @@ For example, the Hurl file
```hurl
GET https://example.org/api/users/1
User-Agent: Custom
-
-HTTP/1.1 200
+HTTP 200
[Asserts]
-jsonpath "$.name" equals "Bob"
+jsonpath "$.name" == "Bob"
```
will be converted to JSON with the following command:
@@ -206,7 +205,7 @@ $ hurlfmt test.hurl --out json | jq
]
},
"response": {
- "version": "HTTP/1.1",
+ "version": "HTTP",
"status": 200,
"asserts": [
{
@@ -215,7 +214,7 @@ $ hurlfmt test.hurl --out json | jq
"expr": "$.name"
},
"predicate": {
- "type": "equal",
+ "type": "==",
"value": "Bob"
}
}
diff --git a/docs/manual/hurl.1 b/docs/manual/hurl.1
index 99a6a381555..edc9b4b0132 100644
--- a/docs/manual/hurl.1
+++ b/docs/manual/hurl.1
@@ -1,4 +1,4 @@
-.TH hurl 1 "01 Apr 2024" "hurl 4.3.0-SNAPSHOT" " Hurl Manual"
+.TH hurl 1 "04 Apr 2024" "hurl 4.3.0-SNAPSHOT" " Hurl Manual"
.SH NAME
hurl - run and test HTTP requests.
diff --git a/docs/manual/hurlfmt.1 b/docs/manual/hurlfmt.1
index e9f528efb5e..80c4e7d6c7a 100644
--- a/docs/manual/hurlfmt.1
+++ b/docs/manual/hurlfmt.1
@@ -1,4 +1,4 @@
-.TH hurl 1 "01 Apr 2024" "hurl 4.3.0-SNAPSHOT" " Hurl Manual"
+.TH hurl 1 "04 Apr 2024" "hurl 4.3.0-SNAPSHOT" " Hurl Manual"
.SH NAME
hurlfmt - format Hurl files
diff --git a/docs/request.md b/docs/request.md
index 506eed603df..ca99557e3ce 100644
--- a/docs/request.md
+++ b/docs/request.md
@@ -650,6 +650,7 @@ output: out.html # dump the response to this file
path-as-is: true # do not handle sequences of /../ or /./ in URL path
skip: false # skip this request
unix-socket: sock # use Unix socket for transfer
+user: bob=secret # use basic authentication
variable: country=Italy # define variable country
variable: planet=Earth # define variable planet
verbose: true # allow verbose output
diff --git a/docs/samples.md b/docs/samples.md
index 83476374418..717e388b769 100644
--- a/docs/samples.md
+++ b/docs/samples.md
@@ -17,6 +17,18 @@ oriented output, you can use [`--test` option]:
$ hurl --test sample.hurl
```
+A particular response can be saved with [`[Options] section`][option]:
+
+```hurl
+GET https://example.ord/cats/123
+[Options]
+output: cat123.txt # use - to output to stdout
+HTTP 200
+
+GET https://example.ord/dogs/567
+HTTP 200
+```
+
You can check [Hurl tests suite] for more samples.
@@ -28,6 +40,15 @@ A simple GET:
GET https://example.org
```
+Requests can be chained:
+
+```hurl
+GET https://example.org/a
+GET https://example.org/b
+HEAD https://example.org/c
+GET https://example.org/c
+```
+
[Doc](/docs/request.md#method)
### HTTP Headers
@@ -61,6 +82,8 @@ Or:
GET https://example.org/news?order=newest&search=something%20to%20search&count=100
```
+> With `[QueryStringParams]` section, params don't need to be URL escaped.
+
[Doc](/docs/request.md#query-parameters)
### Basic Authentication
@@ -81,9 +104,42 @@ GET https://example.org/protected
Authorization: Basic Ym9iOnNlY3JldA==
```
-Basic authentication allows per request authentication.
-If you want to add basic authentication to all the requests of a Hurl file
-you could use [`-u/--user` option].
+Basic authentication section allows per request authentication. If you want to add basic authentication to all the
+requests of a Hurl file you could use [`-u/--user` option]:
+
+```shell
+$ hurl --user bob=secret login.hurl
+```
+
+[`--user`] option can also be set per request:
+
+```hurl
+GET https://example.org/login
+[Options]
+user: bob:secret
+HTTP 200
+
+GET https://example.org/login
+[Options]
+user: alice:secret
+HTTP 200
+```
+
+### Passing Data between Requests
+
+[Captures] can be used to pass data from one request to another:
+
+```hurl
+POST https://sample.org/orders
+HTTP 201
+[Captures]
+order_id: jsonpath "$.order.id"
+
+GET https://sample.org/orders/{{order_id}}
+HTTP 200
+```
+
+[Doc](/docs/capturing-response.md)
## Sending Data
@@ -264,6 +320,44 @@ GraphQL queries can also use [Hurl templates].
## Testing Response
+Responses are optional, everything after `HTTP` is part of the response asserts.
+
+```hurl
+# A request with (almost) no check:
+GET https://foo.com
+
+# A status code check:
+GET https://foo.com
+HTTP 200
+
+# A test on response body
+GET https://foo.com
+HTTP 200
+[Asserts]
+jsonpath "$.state" == "running"
+```
+
+### Testing Status Code
+
+```hurl
+GET https://example.org/order/435
+HTTP 200
+```
+
+[Doc](/docs/asserting-response.md#version-status)
+
+```hurl
+GET https://example.org/order/435
+# Testing status code is in a 200-300 range
+HTTP *
+[Asserts]
+status >= 200
+status < 300
+```
+
+[Doc](/docs/asserting-response.md#status-assert)
+
+
### Testing Response Headers
Use implicit response asserts to test header values:
@@ -289,6 +383,16 @@ header "Location" contains "www.example.net"
[Doc](/docs/asserting-response.md#header-assert)
+Implicit and explicit asserts can be combined:
+
+```hurl
+GET https://example.org/index.html
+HTTP 200
+Set-Cookie: theme=light
+Set-Cookie: sessionToken=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT
+[Asserts]
+header "Location" contains "www.example.net"
+```
### Testing REST APIs
@@ -313,27 +417,6 @@ jsonpath "$.created" isIsoDate
[Doc](/docs/asserting-response.md#jsonpath-assert)
-Testing status code:
-
-```hurl
-GET https://example.org/order/435
-HTTP 200
-```
-
-[Doc](/docs/asserting-response.md#version-status)
-
-```hurl
-GET https://example.org/order/435
-# Testing status code is in a 200-300 range
-HTTP *
-[Asserts]
-status >= 200
-status < 300
-```
-
-[Doc](/docs/asserting-response.md#status-assert)
-
-
### Testing HTML Response
```hurl
@@ -396,16 +479,141 @@ certificate "Serial-Number" matches /[\da-f]+/
[Doc](/docs/asserting-response.md#ssl-certificate-assert)
+### Checking Full Body
+
+Use implicit body to test an exact JSON body match:
+
+```hurl
+GET https://example.org/api/cats/123
+HTTP 200
+{
+ "name" : "Purrsloud",
+ "species" : "Cat",
+ "favFoods" : ["wet food", "dry food", "any food"],
+ "birthYear" : 2016,
+ "photo" : "https://learnwebcode.github.io/json-example/images/cat-2.jpg"
+}
+```
+
+[Doc](/docs/asserting-response.md#json-body)
+
+Or an explicit assert file:
+
+```hurl
+GET https://example.org/index.html
+HTTP 200
+[Asserts]
+body == file,cat.json;
+```
+
+[Doc](/docs/asserting-response.md#body-assert)
+
+Implicit asserts supports XML body:
+
+```hurl
+GET https://example.org/api/catalog
+HTTP 200
+
+
+
+ Gambardella, Matthew
+ XML Developer's Guide
+ Computer
+ 44.95
+ 2000-10-01
+ An in-depth look at creating applications with XML.
+
+
+```
+
+[Doc](/docs/asserting-response.md#xml-body)
+
+Plain text:
+
+~~~hurl
+GET https://example.org/models
+HTTP 200
+```
+Year,Make,Model,Description,Price
+1997,Ford,E350,"ac, abs, moon",3000.00
+1999,Chevy,"Venture ""Extended Edition""","",4900.00
+1999,Chevy,"Venture ""Extended Edition, Very Large""",,5000.00
+1996,Jeep,Grand Cherokee,"MUST SELL! air, moon roof, loaded",4799.00
+```
+~~~
+
+[Doc](/docs/asserting-response.md#multiline-string-body)
+
+
+One line:
+
+```hurl
+POST https://example.org/helloworld
+HTTP 200
+`Hello world!`
+```
+
+[Doc](/docs/asserting-response.md#oneline-string-body)
+
+File:
+
+```hurl
+GET https://example.org
+HTTP 200
+file,data.bin;
+```
+
+[Doc](/docs/asserting-response.md#file-body)
+
+
+## Reports
+
+### HTML Report
+
+```shell
+$ hurl --test --report-html build/report/ *.hurl
+```
+
+[Doc](/docs/running-tests.md#generating-report)
+
+### JUnit Report
+
+```shell
+$ hurl --test --report-junit build/report.xml *.hurl
+```
+
+[Doc](/docs/running-tests.md#generating-report)
+
+### TAP Report
+
+```shell
+$ hurl --test --report-tap build/report.txt *.hurl
+```
+
+[Doc](/docs/running-tests.md#generating-report)
+
+### JSON Output
+
+A structured output of running Hurl files can be obtained with [`--json` option]. Each file will produce a JSON export of the run.
+
+
+```shell
+$ hurl --json *.hurl
+```
+
## Others
### HTTP Version
-Testing HTTP version (1.0, 1.1, 2 or 3):
+Testing HTTP version (HTTP/1.0, HTTP/1.1, HTTP/2 or HTTP/3):
```hurl
-GET https://example.org/order/435
+GET https://foo.com
HTTP/3 200
+
+GET https://bar.com
+HTTP/2 200
```
[Doc](/docs/asserting-response.md#version-status)
@@ -456,7 +664,7 @@ HTTP 200
### Skipping Requests
```hurl
-# a, b, d are runner, c is skipped
+# a, c, d are run, b is skipped
GET https://example.org/a
GET https://example.org/b
@@ -542,7 +750,17 @@ Action: GetCallerIdentity
Version: 2011-06-15
```
-The Access Key is given per [`--user`].
+The Access Key is given per [`--user`], either with command line option or within the [`[Options]`][option] section:
+
+```hurl
+POST https://sts.eu-central-1.amazonaws.com/
+[Options]
+aws-sigv4: aws:amz:eu-central-1:sts
+user: bob=secret
+[FormParams]
+Action: GetCallerIdentity
+Version: 2011-06-15
+```
[Doc](/docs/manual.md#aws-sigv4)
@@ -564,3 +782,6 @@ The Access Key is given per [`--user`].
[`--user`]: /docs/manual.md#user
[Hurl templates]: /docs/templates.md
[AWS Signature Version 4]: https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html
+[Captures]: /docs/capturing-response.md
+[option]: /docs/request.md#options
+[`--json` option]: /docs/manual.md#json
diff --git a/docs/tutorial/debug-tips.md b/docs/tutorial/debug-tips.md
index f293e5bd06d..6957c9ae7ca 100644
--- a/docs/tutorial/debug-tips.md
+++ b/docs/tutorial/debug-tips.md
@@ -77,6 +77,16 @@ $ hurl --verbose --no-output basic.hurl
Lines beginning with `*` are debug info, lines that begin with `>` are HTTP request headers and lines that begin with
`<` are HTTP response headers.
+In each run request, we can also see a curl command line to replay this particular request:
+
+```shell
+...
+[1;34m*[0m Request can be run with the following curl command:
+[1;34m*[0m curl --cookie 'x-session-id=s%3AEE3wsnrgUPSyAkgJZGa3jMWk7xmOtv4E.kXQpkmNBXnFOqmeSssqXnecF4qqv1D7bKu3rpbEJxmQ' 'http://localhost:3000/not-found'
+...
+```
+
+
In verbose mode, HTTP request and response bodies are not displayed in the debug logs. If you need to inspect the
request or response body, you can display more logs with [`--very-verbose`] option:
diff --git a/packages/hurl/README.md b/packages/hurl/README.md
index 4b9d5d89276..b9d0205c877 100644
--- a/packages/hurl/README.md
+++ b/packages/hurl/README.md
@@ -175,6 +175,7 @@ Table of Contents
* [HTTP Headers](#http-headers)
* [Query Params](#query-params)
* [Basic Authentication](#basic-authentication)
+ * [Passing Data between Requests ](#passing-data-between-requests)
* [Sending Data](#sending-data)
* [Sending HTML Form Data](#sending-html-form-data)
* [Sending Multipart Form Data](#sending-multipart-form-data)
@@ -183,12 +184,19 @@ Table of Contents
* [Templating a XML Body](#templating-a-xml-body)
* [Using GraphQL Query](#using-graphql-query)
* [Testing Response](#testing-response)
+ * [Testing Status Code](#testing-status-code)
* [Testing Response Headers](#testing-response-headers)
* [Testing REST APIs](#testing-rest-apis)
* [Testing HTML Response](#testing-html-response)
* [Testing Set-Cookie Attributes](#testing-set-cookie-attributes)
* [Testing Bytes Content](#testing-bytes-content)
* [SSL Certificate](#ssl-certificate)
+ * [Checking Full Body](#checking-full-body)
+ * [Reports](#reports)
+ * [HTML Report](#html-report)
+ * [JUnit Report](#junit-report)
+ * [TAP Report](#tap-report)
+ * [JSON Output](#json-output)
* [Others](#others)
* [HTTP Version](#http-version)
* [Polling and Retry](#polling-and-retry)
@@ -259,6 +267,18 @@ oriented output, you can use [`--test` option]:
$ hurl --test sample.hurl
```
+A particular response can be saved with [`[Options] section`][option]:
+
+```hurl
+GET https://example.ord/cats/123
+[Options]
+output: cat123.txt # use - to output to stdout
+HTTP 200
+
+GET https://example.ord/dogs/567
+HTTP 200
+```
+
You can check [Hurl tests suite] for more samples.
@@ -270,6 +290,15 @@ A simple GET:
GET https://example.org
```
+Requests can be chained:
+
+```hurl
+GET https://example.org/a
+GET https://example.org/b
+HEAD https://example.org/c
+GET https://example.org/c
+```
+
[Doc](https://hurl.dev/docs/request.html#method)
### HTTP Headers
@@ -303,6 +332,8 @@ Or:
GET https://example.org/news?order=newest&search=something%20to%20search&count=100
```
+> With `[QueryStringParams]` section, params don't need to be URL escaped.
+
[Doc](https://hurl.dev/docs/request.html#query-parameters)
### Basic Authentication
@@ -323,9 +354,42 @@ GET https://example.org/protected
Authorization: Basic Ym9iOnNlY3JldA==
```
-Basic authentication allows per request authentication.
-If you want to add basic authentication to all the requests of a Hurl file
-you could use [`-u/--user` option].
+Basic authentication section allows per request authentication. If you want to add basic authentication to all the
+requests of a Hurl file you could use [`-u/--user` option]:
+
+```shell
+$ hurl --user bob=secret login.hurl
+```
+
+[`--user`] option can also be set per request:
+
+```hurl
+GET https://example.org/login
+[Options]
+user: bob:secret
+HTTP 200
+
+GET https://example.org/login
+[Options]
+user: alice:secret
+HTTP 200
+```
+
+### Passing Data between Requests
+
+[Captures] can be used to pass data from one request to another:
+
+```hurl
+POST https://sample.org/orders
+HTTP 201
+[Captures]
+order_id: jsonpath "$.order.id"
+
+GET https://sample.org/orders/{{order_id}}
+HTTP 200
+```
+
+[Doc](https://hurl.dev/docs/capturing-response.html)
## Sending Data
@@ -506,6 +570,44 @@ GraphQL queries can also use [Hurl templates].
## Testing Response
+Responses are optional, everything after `HTTP` is part of the response asserts.
+
+```hurl
+# A request with (almost) no check:
+GET https://foo.com
+
+# A status code check:
+GET https://foo.com
+HTTP 200
+
+# A test on response body
+GET https://foo.com
+HTTP 200
+[Asserts]
+jsonpath "$.state" == "running"
+```
+
+### Testing Status Code
+
+```hurl
+GET https://example.org/order/435
+HTTP 200
+```
+
+[Doc](https://hurl.dev/docs/asserting-response.html#version-status)
+
+```hurl
+GET https://example.org/order/435
+# Testing status code is in a 200-300 range
+HTTP *
+[Asserts]
+status >= 200
+status < 300
+```
+
+[Doc](https://hurl.dev/docs/asserting-response.html#status-assert)
+
+
### Testing Response Headers
Use implicit response asserts to test header values:
@@ -531,6 +633,16 @@ header "Location" contains "www.example.net"
[Doc](https://hurl.dev/docs/asserting-response.html#header-assert)
+Implicit and explicit asserts can be combined:
+
+```hurl
+GET https://example.org/index.html
+HTTP 200
+Set-Cookie: theme=light
+Set-Cookie: sessionToken=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT
+[Asserts]
+header "Location" contains "www.example.net"
+```
### Testing REST APIs
@@ -555,27 +667,6 @@ jsonpath "$.created" isIsoDate
[Doc](https://hurl.dev/docs/asserting-response.html#jsonpath-assert)
-Testing status code:
-
-```hurl
-GET https://example.org/order/435
-HTTP 200
-```
-
-[Doc](https://hurl.dev/docs/asserting-response.html#version-status)
-
-```hurl
-GET https://example.org/order/435
-# Testing status code is in a 200-300 range
-HTTP *
-[Asserts]
-status >= 200
-status < 300
-```
-
-[Doc](https://hurl.dev/docs/asserting-response.html#status-assert)
-
-
### Testing HTML Response
```hurl
@@ -638,16 +729,141 @@ certificate "Serial-Number" matches /[\da-f]+/
[Doc](https://hurl.dev/docs/asserting-response.html#ssl-certificate-assert)
+### Checking Full Body
+
+Use implicit body to test an exact JSON body match:
+
+```hurl
+GET https://example.org/api/cats/123
+HTTP 200
+{
+ "name" : "Purrsloud",
+ "species" : "Cat",
+ "favFoods" : ["wet food", "dry food", "any food"],
+ "birthYear" : 2016,
+ "photo" : "https://learnwebcode.github.io/json-example/images/cat-2.jpg"
+}
+```
+
+[Doc](https://hurl.dev/docs/asserting-response.html#json-body)
+
+Or an explicit assert file:
+
+```hurl
+GET https://example.org/index.html
+HTTP 200
+[Asserts]
+body == file,cat.json;
+```
+
+[Doc](https://hurl.dev/docs/asserting-response.html#body-assert)
+
+Implicit asserts supports XML body:
+
+```hurl
+GET https://example.org/api/catalog
+HTTP 200
+
+
+
+ Gambardella, Matthew
+ XML Developer's Guide
+ Computer
+ 44.95
+ 2000-10-01
+ An in-depth look at creating applications with XML.
+
+
+```
+
+[Doc](https://hurl.dev/docs/asserting-response.html#xml-body)
+
+Plain text:
+
+~~~hurl
+GET https://example.org/models
+HTTP 200
+```
+Year,Make,Model,Description,Price
+1997,Ford,E350,"ac, abs, moon",3000.00
+1999,Chevy,"Venture ""Extended Edition""","",4900.00
+1999,Chevy,"Venture ""Extended Edition, Very Large""",,5000.00
+1996,Jeep,Grand Cherokee,"MUST SELL! air, moon roof, loaded",4799.00
+```
+~~~
+
+[Doc](https://hurl.dev/docs/asserting-response.html#multiline-string-body)
+
+
+One line:
+
+```hurl
+POST https://example.org/helloworld
+HTTP 200
+`Hello world!`
+```
+
+[Doc](https://hurl.dev/docs/asserting-response.html#oneline-string-body)
+
+File:
+
+```hurl
+GET https://example.org
+HTTP 200
+file,data.bin;
+```
+
+[Doc](https://hurl.dev/docs/asserting-response.html#file-body)
+
+
+## Reports
+
+### HTML Report
+
+```shell
+$ hurl --test --report-html build/report/ *.hurl
+```
+
+[Doc](https://hurl.dev/docs/running-tests.html#generating-report)
+
+### JUnit Report
+
+```shell
+$ hurl --test --report-junit build/report.xml *.hurl
+```
+
+[Doc](https://hurl.dev/docs/running-tests.html#generating-report)
+
+### TAP Report
+
+```shell
+$ hurl --test --report-tap build/report.txt *.hurl
+```
+
+[Doc](https://hurl.dev/docs/running-tests.html#generating-report)
+
+### JSON Output
+
+A structured output of running Hurl files can be obtained with [`--json` option]. Each file will produce a JSON export of the run.
+
+
+```shell
+$ hurl --json *.hurl
+```
+
## Others
### HTTP Version
-Testing HTTP version (1.0, 1.1, 2 or 3):
+Testing HTTP version (HTTP/1.0, HTTP/1.1, HTTP/2 or HTTP/3):
```hurl
-GET https://example.org/order/435
+GET https://foo.com
HTTP/3 200
+
+GET https://bar.com
+HTTP/2 200
```
[Doc](https://hurl.dev/docs/asserting-response.html#version-status)
@@ -698,7 +914,7 @@ HTTP 200
### Skipping Requests
```hurl
-# a, b, d are runner, c is skipped
+# a, c, d are run, b is skipped
GET https://example.org/a
GET https://example.org/b
@@ -784,7 +1000,17 @@ Action: GetCallerIdentity
Version: 2011-06-15
```
-The Access Key is given per [`--user`].
+The Access Key is given per [`--user`], either with command line option or within the [`[Options]`][option] section:
+
+```hurl
+POST https://sts.eu-central-1.amazonaws.com/
+[Options]
+aws-sigv4: aws:amz:eu-central-1:sts
+user: bob=secret
+[FormParams]
+Action: GetCallerIdentity
+Version: 2011-06-15
+```
[Doc](https://hurl.dev/docs/manual.html#aws-sigv4)
@@ -1244,6 +1470,9 @@ Please follow the [contrib on Windows section].
[`--user`]: https://hurl.dev/docs/manual.html#user
[Hurl templates]: https://hurl.dev/docs/templates.html
[AWS Signature Version 4]: https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html
+[Captures]: https://hurl.dev/docs/capturing-response.html
+[option]: https://hurl.dev/docs/request.html#options
+[`--json` option]: https://hurl.dev/docs/manual.html#json
[GitHub]: https://github.com/Orange-OpenSource/hurl
[Hurl latest GitHub release]: https://github.com/Orange-OpenSource/hurl/releases/latest
[AUR]: https://wiki.archlinux.org/index.php/Arch_User_Repository