docs(fetch): clarify cookie handling (#12892)

This commit is contained in:
Yury Semikhatsky 2022-03-21 13:20:17 -07:00 committed by GitHub
parent e8fbe97211
commit 0adf5536af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 123 additions and 15 deletions

View File

@ -1,10 +1,10 @@
# class: APIRequest
* langs: js, java, python
Exposes API that can be used for the Web API testing. Each Playwright browser context
has a APIRequestContext instance attached which shares cookies with the page context.
Its also possible to create a new APIRequestContext instance manually. For more information
see [here](./class-apirequestcontext).
Exposes API that can be used for the Web API testing. This class is used for creating
[APIRequestContext] instance which in turn can be used for sending web requests. An instance
of this class can be obtained via [`property: Playwright.request`]. For more information
see [APIRequestContext].
## async method: APIRequest.newContext
* langs: js, java, python

View File

@ -2,9 +2,23 @@
* langs: js, java, python
This API is used for the Web API testing. You can use it to trigger API endpoints, configure micro-services, prepare
environment or the service to your e2e test. When used on [Page] or a [BrowserContext], this API will automatically use
the cookies from the corresponding [BrowserContext]. This means that if you log in using this API, your e2e test
will be logged in and vice versa.
environment or the service to your e2e test.
Each Playwright browser context has associated with it [APIRequestContext] instance which shares cookie storage with
the browser context and can be accessed via [`property: BrowserContext.request`] or [`property: Page.request`].
It is also possible to create a new APIRequestContext instance manually by calling [`method: APIRequest.newContext`].
**Cookie management**
[APIRequestContext] retuned by [`property: BrowserContext.request`] and [`property: Page.request`] shares cookie
storage with the corresponding [BrowserContext]. Each API request will have `Cookie` header populated with the
values from the browser context. If the API response contains `Set-Cookie` header it will automatically update
[BrowserContext] cookies and requests made from the page will pick them up. This means that if you log in using
this API, your e2e test will be logged in and vice versa.
If you want API requests to not interfere with the browser cookies you shoud create a new [APIRequestContext] by
calling [`method: APIRequest.newContext`]. Such `APIRequestContext` object will have its own isolated cookie
storage.
```python async
import os

View File

@ -2558,7 +2558,8 @@ last redirect.
* langs: js, java, python
- type: <[APIRequestContext]>
API testing helper associated with this page. Requests made with this API will use page cookies.
API testing helper associated with this page. This method returns the same instance as
[`property: BrowserContext.request`] on the page's context. See [`property: BrowserContext.request`] for more details.
## async method: Page.route

View File

@ -387,3 +387,73 @@ await requestContext.storageState({ path: 'state.json' });
// Create a new context with the saved storage state.
const context = await browser.newContext({ storageState: 'state.json' });
```
## Context request vs global request
There are two types of [APIRequestContext]:
* associated with a [BrowserContext]
* isolated instance, created via [`method: APIRequest.newContext`]
The main difference is that [APIRequestConxtext] accessible via [`property: BrowserContext.request`] and
[`property: Page.request`] will populate request's `Cookie` header from the browser context and will
automatically update browser cookies if [APIResponse] has `Set-Cookie` header:
```js
test('context request will share cookie storage with its browser context', async ({ page, context }) => {
await context.route('https://www.github.com/', async (route) => {
// Send an API request that shares cookie storage with the browser context.
const response = await context.request.fetch(route.request());
const responseHeaders = response.headers();
// The response will have 'Set-Cookie' header.
const responseCookies = new Map(responseHeaders['set-cookie'].split('\n').map(c => c.split(';', 2)[0].split('=')));
// The response will have 3 cookies in 'Set-Cookie' header.
expect(responseCookies.size).toBe(3);
const contextCookies = await context.cookies();
// The browser context will already contain all the cookies from the API response.
expect(new Map(contextCookies.map(({name, value}) => [name, value]))).toEqual(responseCookies);
route.fulfill({
response,
headers: {...responseHeaders, foo: 'bar'},
});
});
await page.goto('https://www.github.com/');
});
```
If you don't want [APIRequestContext] to use and update cookies from the browser context, you can manually
create a new instance of [APIRequestContext] which will have its own isolated cookies:
```js
test('global context request has isolated cookie storage', async ({ page, context, browser, playwright }) => {
// Create a new instance of APIRequestContext with isolated cookie storage.
const request = await playwright.request.newContext();
await context.route('https://www.github.com/', async (route) => {
const response = await request.fetch(route.request());
const responseHeaders = response.headers();
const responseCookies = new Map(responseHeaders['set-cookie'].split('\n').map(c => c.split(';', 2)[0].split('=')));
// The response will have 3 cookies in 'Set-Cookie' header.
expect(responseCookies.size).toBe(3);
const contextCookies = await context.cookies();
// The browser context will not have any cookies from the isolated API request.
expect(contextCookies.length).toBe(0);
// Manually export cookie storage.
const storageState = await request.storageState();
// Create a new context and initialize it with the cookies from the global request.
const browserContext2 = await browser.newContext({ storageState });
const contextCookies2 = await browserContext2.cookies();
// The new browser context will already contain all the cookies from the API response.
expect(new Map(contextCookies2.map(({name, value}) => [name, value]))).toEqual(responseCookies);
route.fulfill({
response,
headers: {...responseHeaders, foo: 'bar'},
});
});
await page.goto('https://www.github.com/');
await request.dispose();
});
```

View File

@ -2891,7 +2891,10 @@ export interface Page {
}): Promise<null|Response>;
/**
* API testing helper associated with this page. Requests made with this API will use page cookies.
* API testing helper associated with this page. This method returns the same instance as
* [browserContext.request](https://playwright.dev/docs/api/class-browsercontext#browser-context-request) on the page's
* context. See [browserContext.request](https://playwright.dev/docs/api/class-browsercontext#browser-context-request) for
* more details.
*/
request: APIRequestContext;
@ -11910,9 +11913,10 @@ export interface AndroidWebView {
}
/**
* Exposes API that can be used for the Web API testing. Each Playwright browser context has a APIRequestContext instance
* attached which shares cookies with the page context. Its also possible to create a new APIRequestContext instance
* manually. For more information see [here](https://playwright.dev/docs/class-apirequestcontext).
* Exposes API that can be used for the Web API testing. This class is used for creating [APIRequestContext] instance which
* in turn can be used for sending web requests. An instance of this class can be obtained via
* [playwright.request](https://playwright.dev/docs/api/class-playwright#playwright-request). For more information see
* [APIRequestContext].
*/
export interface APIRequest {
/**
@ -12037,9 +12041,28 @@ export interface APIRequest {
/**
* This API is used for the Web API testing. You can use it to trigger API endpoints, configure micro-services, prepare
* environment or the service to your e2e test. When used on [Page] or a [BrowserContext], this API will automatically use
* the cookies from the corresponding [BrowserContext]. This means that if you log in using this API, your e2e test will be
* logged in and vice versa.
* environment or the service to your e2e test.
*
* Each Playwright browser context has associated with it [APIRequestContext] instance which shares cookie storage with the
* browser context and can be accessed via
* [browserContext.request](https://playwright.dev/docs/api/class-browsercontext#browser-context-request) or
* [page.request](https://playwright.dev/docs/api/class-page#page-request). It is also possible to create a new
* APIRequestContext instance manually by calling
* [apiRequest.newContext([options])](https://playwright.dev/docs/api/class-apirequest#api-request-new-context).
*
* **Cookie management**
*
* [APIRequestContext] retuned by
* [browserContext.request](https://playwright.dev/docs/api/class-browsercontext#browser-context-request) and
* [page.request](https://playwright.dev/docs/api/class-page#page-request) shares cookie storage with the corresponding
* [BrowserContext]. Each API request will have `Cookie` header populated with the values from the browser context. If the
* API response contains `Set-Cookie` header it will automatically update [BrowserContext] cookies and requests made from
* the page will pick them up. This means that if you log in using this API, your e2e test will be logged in and vice
* versa.
*
* If you want API requests to not interfere with the browser cookies you shoud create a new [APIRequestContext] by calling
* [apiRequest.newContext([options])](https://playwright.dev/docs/api/class-apirequest#api-request-new-context). Such
* `APIRequestContext` object will have its own isolated cookie storage.
*
*/
export interface APIRequestContext {