[docs] Describe request hooks#2309
Conversation
|
Not quite polished. just the first try, please review |
|
oh, and I forgot @miherlosev |
| test | ||
| .requestHooks(logger) | ||
| ('test', async t => { | ||
| const r = logger.requests[0]; |
There was a problem hiding this comment.
Meaningful name for this const is const request = logger.requests[0];. But in this case you have to write ugly code
console.log(request.request.url); . Thus, an array of requests contains no request but logs, otherwise e.g. id would be in request.request.id. Don't you think so? @VasilyStrelyaev @churkin @AlexanderMoskovkin Could we find more suitable name?
There was a problem hiding this comment.
I've changed the variable name to logRecord
There was a problem hiding this comment.
You can use all power of es6 and write
const { request } = logger.requests[0];logRecord is ok for me too.
| Property | Type | Description | ||
| -------- | ---- | ----------- | ||
| `id` | String | The ID of the request (generated by the logger). | ||
| `testRunId` | String | The ID of the test run that sent the request. Use it to identify the test in which the request originated. |
There was a problem hiding this comment.
I think we should give an example of using testRunId
There was a problem hiding this comment.
I doubt we should expose testRunId. Do you know any cases when a user need it? /cc @miherlosev @VasilyStrelyaev
There was a problem hiding this comment.
@miherlosev once said that grouping requests by the origin test is a use case
There was a problem hiding this comment.
What's the real world case?
await t
.expect(logRecord.id).eql('UnqLnm189')
.expect(logRecord.testRunId).eql('IwQA12J12')It does not make any sense. It will be always failed
There was a problem hiding this comment.
ehm, I used to have console.log here instead of assertions, I guess I will go back to them.
There was a problem hiding this comment.
I used to have console.log here instead of assertions
At first please describe why someone need it.
| ------ | ---- | ------------- | --------- | ||
| `logRequestHeaders` | Boolean | Specifies whether the request headers should be logged. | `false` | ||
| `logRequestBody` | Boolean | Specifies whether the request body should be logged. | `false` | ||
| `stringifyRequestBody` | Boolean | Specifies whether the request body should be stored as a string or an object. | `false` |
There was a problem hiding this comment.
or an object
which kind of object?
There was a problem hiding this comment.
I thought the body is just some custom object and that we don't know anything about it (i.e. can't give more details).
So you are saying that we can give more info here?
There was a problem hiding this comment.
it should be Buffer
| Property | Type | Description | ||
| -------- | ---- | ----------- | ||
| `id` | String | The ID of the request (generated by the logger). | ||
| `testRunId` | String | The ID of the test run that sent the request. Use it to identify the test in which the request originated. |
There was a problem hiding this comment.
What's the real world case?
await t
.expect(logRecord.id).eql('UnqLnm189')
.expect(logRecord.testRunId).eql('IwQA12J12')It does not make any sense. It will be always failed
kirovboris
left a comment
There was a problem hiding this comment.
/r-
I think we need to add some simple example(s) to take a look at the feature before the digging into details.
| * All TestCafe request hooks descend from the `RequestHook` class. | ||
|
|
||
| ```js | ||
| class MyRequestHook extends RequestHook { |
There was a problem hiding this comment.
Add import statement for RequestHook.
| * To determine which requests the hook handles, the base class constructor receives an array of [filtering rules](#specifying-which-requests-are-handled-by-the-hook) as the first parameter. If no rules are passed, all requests are handled. | ||
|
|
||
| ```js | ||
| export default class RequestHook { |
There was a problem hiding this comment.
export default is an extra noise for this example, just class RequestHook... Also you forgot to close }
| constructor (requestFilterRules, responseEventConfigureOpts) { | ||
| console.log(responseEventConfigureOpts.includeHeaders); // false | ||
| console.log(responseEventConfigureOpts.includeBody); // false | ||
| } |
| * To determine which requests the hook handles, the base class constructor receives an array of [filtering rules](#specifying-which-requests-are-handled-by-the-hook) as the first parameter. If no rules are passed, all requests are handled. | ||
|
|
||
| ```js | ||
| export default class RequestHook { |
There was a problem hiding this comment.
We need to describe class interface before detail explanation.
class RequestHook {
constructor (requestFilterRules, responseEventConfigureOpts) {
...
}
onRequest (event) {
...
}
onResponse (event) {
...
}
}|
|
||
| Property | Type | Description | ||
| -------- | ---- | ------------ | ||
| `headers` | Object | The request headers in the property-value form. |
There was a problem hiding this comment.
These option tables contain a lot of stuff, let's add new item to the table of contents. It should be done for other huge option tables as well.
| `port` | Number | The destination port. | ||
| `path` | String | The destination path. | ||
| `method` | String | The request method. | ||
| `credentials` | Object | Credentials that were used to authenticate in the current session using NTLM or Basic authentication. For HTTP Basic authentication, these are `username` and `password`. NTLM authentication additionally specifies `workstation` and `domain`. |
There was a problem hiding this comment.
It would be great to describe credentials option in detail or to add a link if it's possible.
| * The request's HTTP method. | ||
| * The status code received in the response. | ||
| * The user agent that sent the request. | ||
| * The ID of the test run that sent the request. |
There was a problem hiding this comment.
It needs only for customers which will create an own hook. I think we should not describe it.
|
|
||
| Property | Type | Description | ||
| -------- | ---- | ----------- | ||
| `id` | String | The ID of the request (generated by the logger). |
| Property | Type | Description | ||
| -------- | ---- | ----------- | ||
| `id` | String | The ID of the request (generated by the logger). | ||
| `testRunId` | String | The ID of the test run that sent the request. Use it to identify the test in which the request originated. |
| ### respond | ||
|
|
||
| ```text | ||
| respond(body [, statusCode] [, headers]) |
There was a problem hiding this comment.
body is an optional parameter too.
.onRequestTo(...).respond() returns an empty html page.
|
|
||
| Property | Type | Description | ||
| -------- | ---- | -------------- | ||
| `requestId` | String | TestCafe internal request ID. |
| `isAjax` | Boolean | Specifies whether this is an AJAX request. | ||
| `headers` | Object | The request headers in the property-value form. | ||
| `body` | String | A stringified request body. | ||
| `testRunId` | String | TestCafe internal ID of the test run that sent the request. |
|
|
||
| ### Understanding How TestCafe Request Hooks Operate | ||
|
|
||
| * All TestCafe request hooks descend from the `RequestHook` class. |
| .onRequestTo(/*...*/) | ||
| .respond('<html></html>') // an HTML response | ||
| .onRequestTo(/*...*/) | ||
| .respond(null, 204) // an empty response with a status code |
There was a problem hiding this comment.
One more case - respond with binary data
.onRequestTo(/*...*/)
.respond(Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]))|
@dirk-pieterse @miherlosev please review |
| * [Assertion API](articles/documentation/test-api/assertions/assertion-api.md) | ||
| * [Obtaining Data from the Client](articles/documentation/test-api/obtaining-data-from-the-client/README.md) | ||
| * [Examples of Using Client Functions](articles/documentation/test-api/obtaining-data-from-the-client/examples-of-using-client-functions.md) | ||
| * [Intercepting and Mocking HTTP Requests](articles/documentation/test-api/intercepting-and-mocking-http-requests/README.md) |
There was a problem hiding this comment.
Intercepting and Mocking HTTP Requests -> Intercepting HTTP Requests
Mocking is a intercepting too.
|
|
||
| If you need to handle HTTP requests in a custom way, you can create your own request hook. | ||
|
|
||
| The example below shows a custom hook that adds the `Authorization` header for JWT bearer authorization. |
|
|
||
| Parameter | Type | Description | ||
| --------- | ---- | ------------ | ||
| `hook` | RequestHook | A request logger, mock or custom hook. |
There was a problem hiding this comment.
Should be RequestHook subclass. The build-in: RequestLogger or RequestMock or custom RequestHook written by customer.
So, I propose to change the line as:
hook | RequestHook subclass | A RequestLogger, RequestMock or custom user-defined hook.
| --------- | ---- | ------------ | ||
| `hook` | RequestHook | A request logger, mock or custom hook. | ||
|
|
||
| The `requestHooks` methods use the rest operator, which allows you to pass multiple hooks as parameters or arrays of hooks. |
There was a problem hiding this comment.
This sentence presents twice.
I think we should rewrite as:
The 'hook' parameter of fixture.requestHooks, test.requestHooks, t.addRequestHooks and t.removeRequestHooks is the rest operator.
It allows to pass multiple hooks or arrays of hooks as parameter.
Example
fixture.requestHooks(logger1, logger2, logger3, mock);
test.requestHooks([logger1, logger2, logger3, mock])|
|
||
| The request logger, mock and custom request hooks require that you specify which requests should be handled by them and which should be skipped. | ||
|
|
||
| You can perform this filtering by passing the *request filtering rules* to the hook. Note that you can pass a single rule or an array of those. |
There was a problem hiding this comment.
You can setup or You can specify
| .respond(responseMock2); | ||
| ``` | ||
|
|
||
| To enable the hook to mock the requests, [attach it to a test or fixture](attaching-hooks-to-tests-and-fixtures.md). |
There was a problem hiding this comment.
To enable the hook to mock the requests - it's unnecessary phrase.
Simplify to 'Then attach it to a test or fixture.' Or something like that.
The common request hook working scheme: firstly - configure, secondary - attach to fixture or test.
|
|
||
| Parameter | Type | Description | Default | ||
| --------- | ---- | ------------- | ----- | ||
| `body` *(optional)* | Object | String | Function | A mocked response body. Pass an object for a JSON response, a string for an HTML response or a function to build a custom response. | An empty HTML page is returned with the response. |
There was a problem hiding this comment.
Add Buffer type for body too.
| --------- | ---- | ------------- | ----- | ||
| `body` *(optional)* | Object | String | Function | A mocked response body. Pass an object for a JSON response, a string for an HTML response or a function to build a custom response. | An empty HTML page is returned with the response. | ||
| `statusCode` *(optional)* | Number | The response status code. | `200` | ||
| `headers` *(optional)* | Object | Custom headers added to the response in the property-value form.| The `content-type` header is provided. |
There was a problem hiding this comment.
Extend this:
If content-type is specified then its value will be used.
If content-type header is not specified then it will be calculated according the body type.
If body is object then content-type will be application/json.
if body has another type then content-type will be text/html; charset=utf-8.
|
|
||
| Parameter | Type | Description | ||
| --------- | ---- | --------------- | ||
| `req` | Object | A request to be mocked. |
There was a problem hiding this comment.
This is request options from https://github.com/DevExpress/testcafe/pull/2309/files#diff-10e0cabf319ff29f01739d995e6ad73aR121.
Maybe need to place in separate paragraph or page?
|
|
||
| Method | Description | ||
| ------ | --------------- | ||
| `setBody(value)` | Sets the `value` as the response body. No newline at end of file |
There was a problem hiding this comment.
value parameter should be String.
|
|
||
| Parameters | Type | Description | Default | ||
| ---------- | ---- | ----------- | ----- | ||
| `filter` *(optional)* | String | RegExp | Object | Predicate | Specifies which requests should be mocked with a response that follows in the `respond` method. See [Specifying Which Requests are Handled by the Hook](specifying-which-requests-are-handled-by-the-hook.md). | All requests are mocked. |
There was a problem hiding this comment.
filter is required parameter
|
|
||
| Parameter | Type | Description | Default | ||
| --------- | ---- | ------------- | ----- | ||
| `body` *(optional)* | Object | String | Function | Buffer | A mocked response body. Pass an object for a JSON response, a string for an HTML response or a function to build a custom response. | An empty HTML page is returned with the response. |
There was a problem hiding this comment.
Add link to the Buffer type
| * [Assertion API](articles/documentation/test-api/assertions/assertion-api.md) | ||
| * [Obtaining Data from the Client](articles/documentation/test-api/obtaining-data-from-the-client/README.md) | ||
| * [Examples of Using Client Functions](articles/documentation/test-api/obtaining-data-from-the-client/examples-of-using-client-functions.md) | ||
| * [Intercepting HTTP Requests](articles/documentation/test-api/intercepting-and-mocking-http-requests/README.md) |
There was a problem hiding this comment.
Rename the filename too
articles/documentation/test-api/intercepting-http-requests/README.md
There was a problem hiding this comment.
It isn't convenient to perform this from Vasily's fork.
I'll rename this topic and fix links to it from my fork in a separate PR after merging this PR.
* Describe request hooks * Address Helen's remarks * Revert an example * Specify the body type - Buffer * Change structure and address remarks * Add real-life examples * Update TOC * Fix broken links * Update README.md * Update README.md * Update README.md * Update attaching-hooks-to-tests-and-fixtures.md * Update creating-a-custom-http-request-hook.md * Update logging-http-requests.md * Update mocking-http-responses.md * Update specifying-which-requests-are-handled-by-the-hook.md * fix Mikhail's remark * fix Mikhail's remarks * attaching hooks - fix Mikhail's remarks * specifying-which-requests-are-handled -Fix remarks * creating-a-custom-http-request-hook - Fix remarks * logging-http-requests -- fix Mikhail's remark * remove Mocking from header * Remove Mocking from header * creating-a-custom-http-request-hook Fix remarks * mocking-http-responses Fix Mikhail's remarks * formatting added * remove trailing-spaces * Remove trailing spaces * mocking-http-responses.md Fix Mikhail's remarks * Remove trailing spaces * return previous permalink for Readme.md * return previous permalink for request hooks main topic * fix broken link
\cc @DevExpress/testcafe-docs