Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[docs] Describe request hooks #2309

Merged
merged 34 commits into from
May 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
0f5b3ad
Describe request hooks
VasilyStrelyaev Apr 11, 2018
d47a22c
Address Helen's remarks
VasilyStrelyaev Apr 12, 2018
1c4c8dd
Revert an example
VasilyStrelyaev Apr 12, 2018
dc72750
Specify the body type - Buffer
VasilyStrelyaev Apr 12, 2018
accf85d
Change structure and address remarks
VasilyStrelyaev Apr 26, 2018
0118cd1
Add real-life examples
VasilyStrelyaev Apr 27, 2018
bb73c9b
Update TOC
VasilyStrelyaev May 4, 2018
1458509
Fix broken links
VasilyStrelyaev May 4, 2018
e89d007
Update README.md
dirk-pieterse May 10, 2018
2f84503
Update README.md
dirk-pieterse May 10, 2018
1f6b185
Update README.md
dirk-pieterse May 10, 2018
bbe1b18
Update attaching-hooks-to-tests-and-fixtures.md
dirk-pieterse May 10, 2018
aa554fa
Update creating-a-custom-http-request-hook.md
dirk-pieterse May 10, 2018
56221fc
Update logging-http-requests.md
dirk-pieterse May 10, 2018
d300ec8
Update mocking-http-responses.md
dirk-pieterse May 10, 2018
ea36a7f
Update specifying-which-requests-are-handled-by-the-hook.md
dirk-pieterse May 10, 2018
02d7cfa
fix Mikhail's remark
MargaritaLoseva May 10, 2018
0b66070
fix Mikhail's remarks
MargaritaLoseva May 10, 2018
daef822
attaching hooks - fix Mikhail's remarks
MargaritaLoseva May 10, 2018
7dff4e5
specifying-which-requests-are-handled -Fix remarks
MargaritaLoseva May 10, 2018
dc8d8b2
creating-a-custom-http-request-hook - Fix remarks
MargaritaLoseva May 10, 2018
90e7823
logging-http-requests -- fix Mikhail's remark
MargaritaLoseva May 10, 2018
a157230
remove Mocking from header
MargaritaLoseva May 11, 2018
82f1fee
Remove Mocking from header
MargaritaLoseva May 11, 2018
4d023dd
creating-a-custom-http-request-hook Fix remarks
MargaritaLoseva May 11, 2018
b40ff58
mocking-http-responses Fix Mikhail's remarks
MargaritaLoseva May 11, 2018
4fb0c47
formatting added
MargaritaLoseva May 11, 2018
a52a9b2
remove trailing-spaces
MargaritaLoseva May 11, 2018
bf3f3f7
Remove trailing spaces
MargaritaLoseva May 11, 2018
b667a44
mocking-http-responses.md Fix Mikhail's remarks
MargaritaLoseva May 11, 2018
6efaa50
Remove trailing spaces
MargaritaLoseva May 11, 2018
56e10f7
return previous permalink for Readme.md
MargaritaLoseva May 11, 2018
2c80769
return previous permalink for request hooks main topic
MargaritaLoseva May 11, 2018
cabbda8
fix broken link
MargaritaLoseva May 11, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Documentation

> This is a development version of the documentation. The functionality described here may not be included in the current release version. Unreleased functionality may change or be dropped before the next release. Documentation for the release version is available at the [TestCafe website](https://devexpress.github.io/testcafe/documentation/getting-started/).
> This is the documentation's development version. The functionality described here may not be included in the current release version. Unreleased functionality may change or be dropped before the next release. The release version's documentation is available on the [TestCafe website](https://devexpress.github.io/testcafe/documentation/getting-started/).

* [GETTING STARTED](articles/documentation/getting-started/README.md)
* [USING TESTCAFE](articles/documentation/using-testcafe/README.md)
Expand Down Expand Up @@ -60,6 +60,12 @@
* [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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename the filename too
articles/documentation/test-api/intercepting-http-requests/README.md

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

* [Logging HTTP Requests](articles/documentation/test-api/intercepting-and-mocking-http-requests/logging-http-requests.md)
* [Mocking HTTP Responses](articles/documentation/test-api/intercepting-and-mocking-http-requests/mocking-http-responses.md)
* [Creating a Custom HTTP Request Hook](articles/documentation/test-api/intercepting-and-mocking-http-requests/creating-a-custom-http-request-hook.md)
* [Specifying Which Requests are Handled by the Hook](articles/documentation/test-api/intercepting-and-mocking-http-requests/specifying-which-requests-are-handled-by-the-hook.md)
* [Attaching Hooks to Tests and Fixtures](articles/documentation/test-api/intercepting-and-mocking-http-requests/attaching-hooks-to-tests-and-fixtures.md)
* [Waiting for Page Elements to Appear](articles/documentation/test-api/waiting-for-page-elements-to-appear.md)
* [Authentication](articles/documentation/test-api/authentication/README.md)
* [User Roles](articles/documentation/test-api/authentication/user-roles.md)
Expand Down
4 changes: 2 additions & 2 deletions docs/articles/documentation/test-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ checked: true
---
# Test API

TestCafe allows you to write tests using both JavaScript and TypeScript.
For more information about writing tests in TypeScript, see [TypeScript Support](typescript-support.md).
TestCafe allows you to write tests using JavaScript and TypeScript (see [TypeScript Support](typescript-support.md) for more information about writing tests in TypeScript).

The following topics demonstrate how to organize test code:

Expand All @@ -20,6 +19,7 @@ The following topics describe the API used to manipulate the webpage and check i
* [Selecting Page Elements](selecting-page-elements/README.md)
* [Assertions](assertions/README.md)
* [Obtaining Data From the Client](obtaining-data-from-the-client/README.md)
* [Intercepting HTTP Requests](intercepting-and-mocking-http-requests/README.md)
* [Waiting for Page Elements to Appear](waiting-for-page-elements-to-appear.md)
* [Authentication](authentication/README.md)
* [Pausing the Test](pausing-the-test.md)
Expand Down
12 changes: 12 additions & 0 deletions docs/articles/documentation/test-api/a-z-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,16 @@ This topic lists test API members in alphabetical order.
* [httpAuth](authentication/http-authentication.md)
* [only](test-code-structure.md#skipping-tests)
* [page](test-code-structure.md#specifying-the-start-webpage)
* [requestHooks](intercepting-and-mocking-http-requests/attaching-hooks-to-tests-and-fixtures.md)
* [skip](test-code-structure.md#skipping-tests)
* [RequestLogger](intercepting-and-mocking-http-requests/logging-http-requests.md)
* [contains](intercepting-and-mocking-http-requests/logging-http-requests.md#logger-methods)
* [count](intercepting-and-mocking-http-requests/logging-http-requests.md#logger-methods)
* [clear](intercepting-and-mocking-http-requests/logging-http-requests.md#logger-methods)
* [requests](intercepting-and-mocking-http-requests/logging-http-requests.md#logger-properties)
* [RequestMock](intercepting-and-mocking-http-requests/mocking-http-responses.md)
* [onRequestTo](intercepting-and-mocking-http-requests/mocking-http-responses.md#the-onrequestto-method)
* [respond](intercepting-and-mocking-http-requests/mocking-http-responses.md#the-respond-method)
* [Role](authentication/user-roles.md)
* [anonymous](authentication/user-roles.md#anonymous-role)
* [Selector](selecting-page-elements/selectors/creating-selectors.md)
Expand Down Expand Up @@ -47,8 +56,10 @@ This topic lists test API members in alphabetical order.
* [httpAuth](authentication/http-authentication.md)
* [only](test-code-structure.md#skipping-tests)
* [page](test-code-structure.md#specifying-the-start-webpage)
* [requestHooks](intercepting-and-mocking-http-requests/attaching-hooks-to-tests-and-fixtures.md)
* [skip](test-code-structure.md#skipping-tests)
* [Test Controller](test-code-structure.md#test-controller)
* [addRequestHooks](intercepting-and-mocking-http-requests/attaching-hooks-to-tests-and-fixtures.md)
* [clearUpload](actions/upload.md#clear-file-upload-input)
* [click](actions/click.md)
* [ctx](test-code-structure.md#sharing-variables-between-test-hooks-and-test-code)
Expand Down Expand Up @@ -81,6 +92,7 @@ This topic lists test API members in alphabetical order.
* [maximizeWindow](actions/resize-window.md#maximizing-the-window)
* [navigate](actions/navigate.md)
* [pressKey](actions/press-key.md)
* [removeRequestHooks](intercepting-and-mocking-http-requests/attaching-hooks-to-tests-and-fixtures.md)
* [resizeWindow](actions/resize-window.md#setting-the-window-size)
* [resizeWindowToFitDevice](actions/resize-window.md#fitting-the-window-into-a-particular-device)
* [rightClick](actions/right-click.md)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
---
layout: docs
title: Intercepting HTTP Requests
permalink: /documentation/test-api/intercepting-and-mocking-http-requests/
checked: true
---
# Intercepting HTTP Requests

This section describes how to handle HTTP requests in your tests. TestCafe allows you to log them and mock the responses out of the box. You can also create a custom HTTP request hook, which allows you, for instance, to emulate authentications like **Kerberos** or **Client Certificate Authentication**.

* [Logging HTTP Requests](logging-http-requests.md)
* [Mocking HTTP Responses](mocking-http-responses.md)
* [Creating a Custom HTTP Request Hook](creating-a-custom-http-request-hook.md)
* [Specifying Which Requests are Handled by the Hook](specifying-which-requests-are-handled-by-the-hook.md)
* [Attaching Hooks to Tests and Fixtures](attaching-hooks-to-tests-and-fixtures.md)

## Logging HTTP Requests

You can use the request logger to record HTTP requests the tested web app sends and responses it receives. For instance, you may want to make sure that the data from a remote service is correct. In this example, the test checks the DevExpress grid control's data.

```js
import { Selector, RequestLogger } from 'testcafe';
import fs from 'fs';
import path from 'path';

const url = 'https://demos.devexpress.com/ASPxGridViewDemos/Exporting/Exporting.aspx';

const logger = RequestLogger({ url, method: 'post' }, {
logResponseHeaders: true,
logResponseBody: true
});

fixture `Export`
.page(url)
.requestHooks(logger);

test('export to csv', async t => {
const exportToCSVButton = Selector('span').withText('Export to CSV');

await t
.click(exportToCSVButton)
.expect(logger.contains(r => r.response.statusCode === 200)).ok();

// After clicking 'Export', the response comes as a gziped CSV.
// The browser unpacks the archive and gives you the file that was inside.
// The test receives the archive as is.
const filePath = path.join(__dirname, 'exported-grid.zip');

console.log(filePath);
console.log(logger.requests[0].response.headers);

fs.writeFileSync(filePath, logger.requests[0].response.body);

// Here you can use 3rd party modules to
// unpack the archive, parse CSV and check the data.
// Or you can just manually verify the file.
});
```

See [Logging HTTP Requests](logging-http-requests.md) for more information.

## Mocking HTTP Responses

Use TestCafe request mocker to substitute infrastructure that is difficult to deploy or that you do not want to use when testing. This can be a third-party service that charges you per pageview or an analytics service that should not log page views tests generate.

```js
import { Selector, RequestMock } from 'testcafe';

// A URL to which Google Analytics sends data.
const collectDataGoogleAnalyticsRegExp = new RegExp('https://www.google-analytics.com/collect');

// Technically, Google Analytics sends an XHR request for a GIF image.
// So, we prepare a mocked response with binary data.
const mockedResponse = Buffer.from([0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01]);

const mock = RequestMock()
.onRequestTo(collectDataGoogleAnalyticsRegExp)

// We respond to Analytics requests with the prepared data
// represented as a GIF image and change the status code to 202.
.respond(mockedResponse, 202, {
'content-length': mockedResponse.length,
'content-type': 'image/gif'
});

fixture `Fixture`
.page('https://devexpress.github.io/testcafe/')
.requestHooks(mock);

test('basic', async t => {
await t
.setTestSpeed(0.01)
.click('.get-started-button')

// During the pause, you can open DevTools and
// find the request sent to Analytics
// and the mocked response received.
.wait(100000);
});
```

See [Mocking HTTP Responses](mocking-http-responses.md) for more information.

## Creating a Custom HTTP Request Hook

You can create your own request hook to handle HTTP requests.

The example below shows a custom hook that adds the `Authorization` header for [JWT](https://tools.ietf.org/html/rfc7519) bearer authorization.

```js
import { Selector, RequestHook } from 'testcafe';

class JwtBearerAuthorization extends RequestHook {
constructor () {
// No URL filtering applied to this hook
// so it will be used for all requests.
super();
}

onRequest (e) {
e.requestOptions.headers['Authorization'] = 'generate token here';
}
}

const jwtBearerAuthorization = new JwtBearerAuthorization();

fixture `Fixture`
.page('<website URL>')
.requestHooks(jwtBearerAuthorization);

test('basic', async t => {
/* some actions */
});
```

See [Creating a Custom HTTP Request Hook](creating-a-custom-http-request-hook.md) for more information.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
layout: docs
title: Attaching Hooks to Tests and Fixtures
permalink: /documentation/test-api/intercepting-and-mocking-http-requests/attaching-hooks-to-tests-and-fixtures.html
checked: false
---
# Attaching Hooks to Tests and Fixtures

To attach a hook to a test or fixture, use the `fixture.requestHooks` and `test.requestHooks` methods. A hook attached to a fixture handles requests from all tests in the fixture.

```text
fixture.requestHooks(...hook)
test.requestHooks(...hook)
```

You can also attach and detach hooks during test run using the `t.addRequestHooks` and `t.removeRequestHooks` methods.

```text
t.addRequestHooks(...hook)
t.removeRequestHooks(...hooks)
```

Parameter | Type | Description
--------- | ---- | ------------
`hook` | RequestHook subclass | A `RequestLogger`, `RequestMock` or custom user-defined hook.

The `fixture.requestHooks`, `test.requestHooks` `t.addRequestHooks` and `t.removeRequestHooks` methods use the rest operator which allows you to pass multiple hooks as parameters or arrays of hooks.

```js
import { RequestLogger, RequestMock } from 'testcafe';

const logger = RequestLogger('http://example.com');
const mock = RequestMock()
.onRequestTo('http://external-service.com/api/')
.respond({ data: 'value' });

fixture `My fixture`
.page('http://example.com')
.requestHooks(logger);

test
.requestHooks(mock)
('My test', async t => {
await t
.click('#send-logged-request')
.expect(logger.count(() => true)).eql(1)
.removeRequestHooks(logger)
.click('#send-unlogged-request')
.expect(logger.count(() => true)).eql(1)
.addRequestHooks(logger)
.click('#send-logged-request')
.expect(logger.count(() => true)).eql(2);
})
```
Loading