mirror of
https://github.com/microsoft/playwright.git
synced 2025-01-03 17:09:01 +03:00
feat(cookies): move cookie management to BrowserContext (#82)
This commit is contained in:
parent
3decf1f996
commit
a4e24c718b
87
docs/api.md
87
docs/api.md
@ -50,11 +50,14 @@
|
||||
* [event: 'targetcreated'](#event-targetcreated-1)
|
||||
* [event: 'targetdestroyed'](#event-targetdestroyed-1)
|
||||
* [browserContext.browser()](#browsercontextbrowser)
|
||||
* [browserContext.clearCookies()](#browsercontextclearcookies)
|
||||
* [browserContext.close()](#browsercontextclose)
|
||||
* [browserContext.cookies([...urls])](#browsercontextcookiesurls)
|
||||
* [browserContext.isIncognito()](#browsercontextisincognito)
|
||||
* [browserContext.newPage()](#browsercontextnewpage)
|
||||
* [browserContext.pages()](#browsercontextpages)
|
||||
* [browserContext.permissions](#browsercontextpermissions)
|
||||
* [browserContext.setCookies(cookies)](#browsercontextsetcookiescookies)
|
||||
* [browserContext.targets()](#browsercontexttargets)
|
||||
* [browserContext.waitForTarget(predicate[, options])](#browsercontextwaitfortargetpredicate-options)
|
||||
- [class: Geolocation](#class-geolocation)
|
||||
@ -91,10 +94,8 @@
|
||||
* [page.click(selector[, options])](#pageclickselector-options)
|
||||
* [page.close([options])](#pagecloseoptions)
|
||||
* [page.content()](#pagecontent)
|
||||
* [page.cookies([...urls])](#pagecookiesurls)
|
||||
* [page.coverage](#pagecoverage)
|
||||
* [page.dblclick(selector[, options])](#pagedblclickselector-options)
|
||||
* [page.deleteCookie(...cookies)](#pagedeletecookiecookies)
|
||||
* [page.emulate(options)](#pageemulateoptions)
|
||||
* [page.emulateMedia(options)](#pageemulatemediaoptions)
|
||||
* [page.emulateTimezone(timezoneId)](#pageemulatetimezonetimezoneid)
|
||||
@ -122,7 +123,6 @@
|
||||
* [page.setBypassCSP(enabled)](#pagesetbypasscspenabled)
|
||||
* [page.setCacheEnabled([enabled])](#pagesetcacheenabledenabled)
|
||||
* [page.setContent(html[, options])](#pagesetcontenthtml-options)
|
||||
* [page.setCookie(...cookies)](#pagesetcookiecookies)
|
||||
* [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout)
|
||||
* [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout)
|
||||
* [page.setExtraHTTPHeaders(headers)](#pagesetextrahttpheadersheaders)
|
||||
@ -757,6 +757,11 @@ Emitted when a target inside the browser context is destroyed, for example when
|
||||
|
||||
The browser this browser context belongs to.
|
||||
|
||||
#### browserContext.clearCookies()
|
||||
- returns: <[Promise]>
|
||||
|
||||
Clears context bookies.
|
||||
|
||||
#### browserContext.close()
|
||||
- returns: <[Promise]>
|
||||
|
||||
@ -765,6 +770,23 @@ will be closed.
|
||||
|
||||
> **NOTE** only incognito browser contexts can be closed.
|
||||
|
||||
#### browserContext.cookies([...urls])
|
||||
- `...urls` <...[string]>
|
||||
- returns: <[Promise]<[Array]<[Object]>>>
|
||||
- `name` <[string]>
|
||||
- `value` <[string]>
|
||||
- `domain` <[string]>
|
||||
- `path` <[string]>
|
||||
- `expires` <[number]> Unix time in seconds.
|
||||
- `size` <[number]>
|
||||
- `httpOnly` <[boolean]>
|
||||
- `secure` <[boolean]>
|
||||
- `session` <[boolean]>
|
||||
- `sameSite` <"Strict"|"Lax"|"None">
|
||||
|
||||
If no URLs are specified, this method returns all cookies.
|
||||
If URLs are specified, only cookies that affect those URLs are returned.
|
||||
|
||||
#### browserContext.isIncognito()
|
||||
- returns: <[boolean]>
|
||||
|
||||
@ -786,6 +808,23 @@ An array of all pages inside the browser context.
|
||||
#### browserContext.permissions
|
||||
- returns: <[Permissions]>
|
||||
|
||||
#### browserContext.setCookies(cookies)
|
||||
- `cookies` <[Array]<[Object]>>
|
||||
- `name` <[string]> **required**
|
||||
- `value` <[string]> **required**
|
||||
- `url` <[string]> either url or domain / path are **required**
|
||||
- `domain` <[string]> either url or domain / path are **required**
|
||||
- `path` <[string]> either url or domain / path are **required**
|
||||
- `expires` <[number]> Unix time in seconds.
|
||||
- `httpOnly` <[boolean]>
|
||||
- `secure` <[boolean]>
|
||||
- `sameSite` <"Strict"|"Lax"|"None">
|
||||
- returns: <[Promise]>
|
||||
|
||||
```js
|
||||
await browserContext.setCookies([cookieObject1, cookieObject2]);
|
||||
```
|
||||
|
||||
#### browserContext.targets()
|
||||
- returns: <[Array]<[Target]>>
|
||||
|
||||
@ -1145,23 +1184,6 @@ By default, `page.close()` **does not** run beforeunload handlers.
|
||||
|
||||
Gets the full HTML contents of the page, including the doctype.
|
||||
|
||||
#### page.cookies([...urls])
|
||||
- `...urls` <...[string]>
|
||||
- returns: <[Promise]<[Array]<[Object]>>>
|
||||
- `name` <[string]>
|
||||
- `value` <[string]>
|
||||
- `domain` <[string]>
|
||||
- `path` <[string]>
|
||||
- `expires` <[number]> Unix time in seconds.
|
||||
- `size` <[number]>
|
||||
- `httpOnly` <[boolean]>
|
||||
- `secure` <[boolean]>
|
||||
- `session` <[boolean]>
|
||||
- `sameSite` <"Strict"|"Lax"|"Extended"|"None">
|
||||
|
||||
If no URLs are specified, this method returns cookies for the current page URL.
|
||||
If URLs are specified, only cookies for those URLs are returned.
|
||||
|
||||
#### page.coverage
|
||||
|
||||
- returns: <[Coverage]>
|
||||
@ -1186,14 +1208,6 @@ Bear in mind that if the first click of the `dblclick()` triggers a navigation e
|
||||
|
||||
Shortcut for [page.mainFrame().dblclick(selector[, options])](#framedblclickselector-options).
|
||||
|
||||
#### page.deleteCookie(...cookies)
|
||||
- `...cookies` <...[Object]>
|
||||
- `name` <[string]> **required**
|
||||
- `url` <[string]>
|
||||
- `domain` <[string]>
|
||||
- `path` <[string]>
|
||||
- returns: <[Promise]>
|
||||
|
||||
#### page.emulate(options)
|
||||
- `options` <[Object]>
|
||||
- `viewport` <[Object]>
|
||||
@ -1614,23 +1628,6 @@ Toggles ignoring cache for each request based on the enabled state. By default,
|
||||
- `networkidle2` - consider setting content to be finished when there are no more than 2 network connections for at least `500` ms.
|
||||
- returns: <[Promise]>
|
||||
|
||||
#### page.setCookie(...cookies)
|
||||
- `...cookies` <...[Object]>
|
||||
- `name` <[string]> **required**
|
||||
- `value` <[string]> **required**
|
||||
- `url` <[string]>
|
||||
- `domain` <[string]>
|
||||
- `path` <[string]>
|
||||
- `expires` <[number]> Unix time in seconds.
|
||||
- `httpOnly` <[boolean]>
|
||||
- `secure` <[boolean]>
|
||||
- `sameSite` <"Strict"|"Lax">
|
||||
- returns: <[Promise]>
|
||||
|
||||
```js
|
||||
await page.setCookie(cookieObject1, cookieObject2);
|
||||
```
|
||||
|
||||
#### page.setDefaultNavigationTimeout(timeout)
|
||||
- `timeout` <[number]> Maximum navigation time in milliseconds
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
},
|
||||
"playwright": {
|
||||
"chromium_revision": "718525",
|
||||
"firefox_revision": "1003",
|
||||
"firefox_revision": "1004",
|
||||
"webkit_revision": "2"
|
||||
},
|
||||
"scripts": {
|
||||
|
@ -33,7 +33,7 @@ export class Browser extends EventEmitter {
|
||||
private _process: childProcess.ChildProcess;
|
||||
private _screenshotTaskQueue = new TaskQueue();
|
||||
private _connection: Connection;
|
||||
private _client: CDPSession;
|
||||
_client: CDPSession;
|
||||
private _closeCallback: () => Promise<void>;
|
||||
private _defaultContext: BrowserContext;
|
||||
private _contexts = new Map<string, BrowserContext>();
|
||||
@ -146,7 +146,7 @@ export class Browser extends EventEmitter {
|
||||
|
||||
async _createPageInContext(contextId: string | null): Promise<Page> {
|
||||
const { targetId } = await this._client.send('Target.createTarget', { url: 'about:blank', browserContextId: contextId || undefined });
|
||||
const target = await this._targets.get(targetId);
|
||||
const target = this._targets.get(targetId);
|
||||
assert(await target._initializedPromise, 'Failed to create target for page');
|
||||
const page = await target.page();
|
||||
return page;
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
import { EventEmitter } from 'events';
|
||||
import { assert } from '../helper';
|
||||
import { NetworkCookie, SetNetworkCookieParam, filterCookies } from '../network';
|
||||
import { Browser } from './Browser';
|
||||
import { CDPSession } from './Connection';
|
||||
import { Permissions } from './features/permissions';
|
||||
@ -65,6 +66,25 @@ export class BrowserContext extends EventEmitter {
|
||||
return this._browser;
|
||||
}
|
||||
|
||||
async cookies(...urls: string[]): Promise<NetworkCookie[]> {
|
||||
const { cookies } = await this._browser._client.send('Storage.getCookies', { browserContextId: this._id || undefined });
|
||||
return filterCookies(cookies.map(c => ({ sameSite: 'None', ...c })), urls);
|
||||
}
|
||||
|
||||
async clearCookies() {
|
||||
await this._browser._client.send('Storage.clearCookies', { browserContextId: this._id || undefined });
|
||||
}
|
||||
|
||||
async setCookies(cookies: SetNetworkCookieParam[]) {
|
||||
const items = cookies.map(cookie => {
|
||||
const item = Object.assign({}, cookie);
|
||||
assert(item.url !== 'about:blank', `Blank page can not have cookie "${item.name}"`);
|
||||
assert(!String.prototype.startsWith.call(item.url || '', 'data:'), `Data URL page can not have cookie "${item.name}"`);
|
||||
return item;
|
||||
});
|
||||
await this._browser._client.send('Storage.setCookies', { cookies: items, browserContextId: this._id || undefined });
|
||||
}
|
||||
|
||||
async close() {
|
||||
assert(this._id, 'Non-incognito profiles cannot be closed!');
|
||||
await this._browser._disposeContext(this._id);
|
||||
|
@ -254,40 +254,6 @@ export class Page extends EventEmitter {
|
||||
return this.mainFrame().$x(expression);
|
||||
}
|
||||
|
||||
async cookies(...urls: string[]): Promise<NetworkCookie[]> {
|
||||
const {cookies} = await this._client.send('Network.getCookies', {
|
||||
urls: urls.length ? urls : [this.url()]
|
||||
});
|
||||
// Chromiums's cookies are missing sameSite when it is 'None'
|
||||
return cookies.map(cookie => ({sameSite: 'None', ...cookie}));
|
||||
}
|
||||
|
||||
async deleteCookie(...cookies: Protocol.Network.deleteCookiesParameters[]) {
|
||||
const pageURL = this.url();
|
||||
for (const cookie of cookies) {
|
||||
const item = Object.assign({}, cookie);
|
||||
if (!cookie.url && pageURL.startsWith('http'))
|
||||
item.url = pageURL;
|
||||
await this._client.send('Network.deleteCookies', item);
|
||||
}
|
||||
}
|
||||
|
||||
async setCookie(...cookies: NetworkCookieParam[]) {
|
||||
const pageURL = this.url();
|
||||
const startsWithHTTP = pageURL.startsWith('http');
|
||||
const items = cookies.map(cookie => {
|
||||
const item = Object.assign({}, cookie);
|
||||
if (!item.url && startsWithHTTP)
|
||||
item.url = pageURL;
|
||||
assert(item.url !== 'about:blank', `Blank page can not have cookie "${item.name}"`);
|
||||
assert(!String.prototype.startsWith.call(item.url || '', 'data:'), `Data URL page can not have cookie "${item.name}"`);
|
||||
return item;
|
||||
});
|
||||
await this.deleteCookie(...items);
|
||||
if (items.length)
|
||||
await this._client.send('Network.setCookies', { cookies: items });
|
||||
}
|
||||
|
||||
async addScriptTag(options: { url?: string; path?: string; content?: string; type?: string; }): Promise<ElementHandle> {
|
||||
return this.mainFrame().addScriptTag(options);
|
||||
}
|
||||
@ -747,31 +713,6 @@ type MediaFeature = {
|
||||
value: string
|
||||
}
|
||||
|
||||
type NetworkCookie = {
|
||||
name: string,
|
||||
value: string,
|
||||
domain: string,
|
||||
path: string,
|
||||
expires: number,
|
||||
size: number,
|
||||
httpOnly: boolean,
|
||||
secure: boolean,
|
||||
session: boolean,
|
||||
sameSite: 'Strict'|'Lax'|'Extended'|'None'
|
||||
};
|
||||
|
||||
type NetworkCookieParam = {
|
||||
name: string,
|
||||
value: string,
|
||||
url?: string,
|
||||
domain?: string,
|
||||
path?: string,
|
||||
expires?: number,
|
||||
httpOnly?: boolean,
|
||||
secure?: boolean,
|
||||
sameSite?: 'Strict'|'Lax'
|
||||
};
|
||||
|
||||
type ConsoleMessageLocation = {
|
||||
url?: string,
|
||||
lineNumber?: number,
|
||||
|
@ -56,8 +56,6 @@ export class Coverage {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {Coverage};
|
||||
|
||||
class JSCoverage {
|
||||
_client: CDPSession;
|
||||
_enabled: boolean;
|
||||
|
@ -16,9 +16,10 @@
|
||||
*/
|
||||
|
||||
import { EventEmitter } from 'events';
|
||||
import { Events } from './events';
|
||||
import { assert, helper, RegisteredListener } from '../helper';
|
||||
import { filterCookies, NetworkCookie, SetNetworkCookieParam } from '../network';
|
||||
import { Connection, ConnectionEvents } from './Connection';
|
||||
import { Events } from './events';
|
||||
import { Permissions } from './features/permissions';
|
||||
import { Page, Viewport } from './Page';
|
||||
|
||||
@ -289,10 +290,34 @@ export class BrowserContext extends EventEmitter {
|
||||
return this._browser;
|
||||
}
|
||||
|
||||
async cookies(...urls: string[]): Promise<NetworkCookie[]> {
|
||||
const { cookies } = await this._connection.send('Browser.getCookies', {
|
||||
browserContextId: this._browserContextId || undefined
|
||||
});
|
||||
return filterCookies(cookies, urls);
|
||||
}
|
||||
|
||||
async clearCookies() {
|
||||
await this._connection.send('Browser.clearCookies', {
|
||||
browserContextId: this._browserContextId || undefined,
|
||||
});
|
||||
}
|
||||
|
||||
async setCookies(cookies: SetNetworkCookieParam[]) {
|
||||
const items = cookies.map(cookie => {
|
||||
const item = Object.assign({}, cookie);
|
||||
assert(item.url !== 'about:blank', `Blank page can not have cookie "${item.name}"`);
|
||||
assert(!String.prototype.startsWith.call(item.url || '', 'data:'), `Data URL page can not have cookie "${item.name}"`);
|
||||
return item;
|
||||
});
|
||||
await this._connection.send('Browser.setCookies', {
|
||||
browserContextId: this._browserContextId || undefined,
|
||||
cookies
|
||||
});
|
||||
}
|
||||
|
||||
async close() {
|
||||
assert(this._browserContextId, 'Non-incognito contexts cannot be closed!');
|
||||
await this._browser._disposeContext(this._browserContextId);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {Browser, BrowserContext, Target};
|
||||
|
@ -94,59 +94,6 @@ export class Page extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
async cookies(...urls: Array<string>): Promise<Array<any>> {
|
||||
const connection = Connection.fromSession(this._session);
|
||||
const {cookies} = await connection.send('Browser.getCookies', {
|
||||
browserContextId: this._target._context._browserContextId || undefined,
|
||||
urls: urls.length ? urls : [this.url()]
|
||||
});
|
||||
// Firefox's cookies are missing sameSite when it is 'None'
|
||||
return cookies.map(cookie => ({sameSite: 'None', ...cookie}));
|
||||
}
|
||||
|
||||
async deleteCookie(...cookies: Array<any>) {
|
||||
const pageURL = this.url();
|
||||
const items = [];
|
||||
for (const cookie of cookies) {
|
||||
const item = {
|
||||
url: cookie.url,
|
||||
domain: cookie.domain,
|
||||
path: cookie.path,
|
||||
name: cookie.name,
|
||||
};
|
||||
if (!item.url && pageURL.startsWith('http'))
|
||||
item.url = pageURL;
|
||||
items.push(item);
|
||||
}
|
||||
|
||||
const connection = Connection.fromSession(this._session);
|
||||
await connection.send('Browser.deleteCookies', {
|
||||
browserContextId: this._target._context._browserContextId || undefined,
|
||||
cookies: items,
|
||||
});
|
||||
}
|
||||
|
||||
async setCookie(...cookies: Array<any>) {
|
||||
const pageURL = this.url();
|
||||
const startsWithHTTP = pageURL.startsWith('http');
|
||||
const items = cookies.map(cookie => {
|
||||
const item = Object.assign({}, cookie);
|
||||
if (!item.url && startsWithHTTP)
|
||||
item.url = pageURL;
|
||||
assert(item.url !== 'about:blank', `Blank page can not have cookie "${item.name}"`);
|
||||
assert(!String.prototype.startsWith.call(item.url || '', 'data:'), `Data URL page can not have cookie "${item.name}"`);
|
||||
return item;
|
||||
});
|
||||
await this.deleteCookie(...items);
|
||||
if (items.length) {
|
||||
const connection = Connection.fromSession(this._session);
|
||||
await connection.send('Browser.setCookies', {
|
||||
browserContextId: this._target._context._browserContextId || undefined,
|
||||
cookies: items
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async setExtraHTTPHeaders(headers) {
|
||||
await this._networkManager.setExtraHTTPHeaders(headers);
|
||||
}
|
||||
|
46
src/network.ts
Normal file
46
src/network.ts
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export type NetworkCookie = {
|
||||
name: string,
|
||||
value: string,
|
||||
domain: string,
|
||||
path: string,
|
||||
expires: number,
|
||||
size: number,
|
||||
httpOnly: boolean,
|
||||
secure: boolean,
|
||||
session: boolean,
|
||||
sameSite: 'Strict' | 'Lax' | 'None'
|
||||
};
|
||||
|
||||
export type SetNetworkCookieParam = {
|
||||
name: string,
|
||||
value: string,
|
||||
url?: string,
|
||||
domain?: string,
|
||||
path?: string,
|
||||
expires?: number,
|
||||
httpOnly?: boolean,
|
||||
secure?: boolean,
|
||||
sameSite?: 'Strict' | 'Lax' | 'None'
|
||||
};
|
||||
|
||||
export function filterCookies(cookies: NetworkCookie[], urls: string[]) {
|
||||
const parsedURLs = urls.map(s => new URL(s));
|
||||
// Chromiums's cookies are missing sameSite when it is 'None'
|
||||
return cookies.filter(c => {
|
||||
if (!parsedURLs.length)
|
||||
return true;
|
||||
for (const parsedURL of parsedURLs) {
|
||||
if (parsedURL.hostname !== c.domain)
|
||||
continue;
|
||||
if (!parsedURL.pathname.startsWith(c.path))
|
||||
continue;
|
||||
if ((parsedURL.protocol === 'https:') !== c.secure)
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
@ -17,9 +17,10 @@
|
||||
|
||||
import * as childProcess from 'child_process';
|
||||
import { EventEmitter } from 'events';
|
||||
import { assert, helper, RegisteredListener } from '../helper';
|
||||
import { filterCookies, NetworkCookie } from '../network';
|
||||
import { Connection } from './Connection';
|
||||
import { Events } from './events';
|
||||
import { RegisteredListener, assert, helper } from '../helper';
|
||||
import { Page, Viewport } from './Page';
|
||||
import { Target } from './Target';
|
||||
import { TaskQueue } from './TaskQueue';
|
||||
@ -255,4 +256,30 @@ export class BrowserContext extends EventEmitter {
|
||||
assert(this._id, 'Non-incognito profiles cannot be closed!');
|
||||
await this._browser._disposeContext(this._id);
|
||||
}
|
||||
|
||||
async cookies(...urls: string[]): Promise<NetworkCookie[]> {
|
||||
const page = (await this.pages())[0];
|
||||
const response = await page._session.send('Page.getCookies');
|
||||
const cookies = response.cookies.map(cookie => {
|
||||
// Webkit returns 0 for a cookie without an expiration
|
||||
if (cookie.expires === 0)
|
||||
cookie.expires = -1;
|
||||
return cookie;
|
||||
});
|
||||
return filterCookies(cookies, urls);
|
||||
}
|
||||
|
||||
async clearCookies() {
|
||||
const page = (await this.pages())[0];
|
||||
const response = await page._session.send('Page.getCookies');
|
||||
const promises = [];
|
||||
for (const cookie of response.cookies) {
|
||||
const item = {
|
||||
cookieName: cookie.name,
|
||||
url: (cookie.secure ? 'https://' : 'http://') + cookie.domain + cookie.path
|
||||
};
|
||||
promises.push(page._session.send('Page.deleteCookie', item));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ export type Viewport = {
|
||||
|
||||
export class Page extends EventEmitter {
|
||||
private _closed = false;
|
||||
private _session: TargetSession;
|
||||
_session: TargetSession;
|
||||
private _target: Target;
|
||||
private _keyboard: input.Keyboard;
|
||||
private _mouse: input.Mouse;
|
||||
@ -222,29 +222,6 @@ export class Page extends EventEmitter {
|
||||
return this.mainFrame().$x(expression);
|
||||
}
|
||||
|
||||
async cookies(...urls: string[]): Promise<NetworkCookie[]> {
|
||||
const response = await this._session.send('Page.getCookies');
|
||||
return response.cookies.map(cookie => {
|
||||
// Webkit returns 0 for a cookie without an expiration
|
||||
if (cookie.expires === 0)
|
||||
cookie.expires = -1;
|
||||
return cookie;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteCookie(...cookies: DeleteNetworkCookieParam[]) {
|
||||
const pageURL = this.url();
|
||||
for (const cookie of cookies) {
|
||||
const item = {
|
||||
cookieName: cookie.name,
|
||||
url: cookie.url
|
||||
};
|
||||
if (!cookie.url && pageURL.startsWith('http'))
|
||||
item.url = pageURL;
|
||||
await this._session.send('Page.deleteCookie', item).catch(e => debugError('deleting ' + JSON.stringify(item) + ' => ' + e));
|
||||
}
|
||||
}
|
||||
|
||||
async addScriptTag(options: { url?: string; path?: string; content?: string; type?: string; }): Promise<ElementHandle> {
|
||||
return this.mainFrame().addScriptTag(options);
|
||||
}
|
||||
@ -525,24 +502,6 @@ type ScreenshotOptions = {
|
||||
encoding?: string,
|
||||
}
|
||||
|
||||
type NetworkCookie = {
|
||||
name: string,
|
||||
value: string,
|
||||
domain: string,
|
||||
path: string,
|
||||
expires: number,
|
||||
size: number,
|
||||
httpOnly: boolean,
|
||||
secure: boolean,
|
||||
session: boolean,
|
||||
sameSite?: 'Strict'|'Lax'|'Extended'|'None'
|
||||
};
|
||||
|
||||
type DeleteNetworkCookieParam = {
|
||||
name: string,
|
||||
url?: string,
|
||||
};
|
||||
|
||||
type ConsoleMessageLocation = {
|
||||
url?: string,
|
||||
lineNumber?: number,
|
||||
|
@ -19,17 +19,17 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||
const {it, fit, xit} = testRunner;
|
||||
const {beforeAll, beforeEach, afterAll, afterEach} = testRunner;
|
||||
|
||||
describe('Page.cookies', function() {
|
||||
it('should return no cookies in pristine browser context', async({page, server}) => {
|
||||
describe('BrowserContext.cookies', function() {
|
||||
it('should return no cookies in pristine browser context', async({context, page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
expect(await page.cookies()).toEqual([]);
|
||||
expect(await context.cookies()).toEqual([]);
|
||||
});
|
||||
it('should get a cookie', async({page, server}) => {
|
||||
it('should get a cookie', async({context, page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await page.evaluate(() => {
|
||||
document.cookie = 'username=John Doe';
|
||||
});
|
||||
expect(await page.cookies()).toEqual([{
|
||||
expect(await context.cookies()).toEqual([{
|
||||
name: 'username',
|
||||
value: 'John Doe',
|
||||
domain: 'localhost',
|
||||
@ -42,43 +42,43 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||
sameSite: 'None',
|
||||
}]);
|
||||
});
|
||||
it('should properly report httpOnly cookie', async({page, server}) => {
|
||||
it('should properly report httpOnly cookie', async({context, page, server}) => {
|
||||
server.setRoute('/empty.html', (req, res) => {
|
||||
res.setHeader('Set-Cookie', ';HttpOnly; Path=/');
|
||||
res.end();
|
||||
});
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const cookies = await page.cookies();
|
||||
const cookies = await context.cookies();
|
||||
expect(cookies.length).toBe(1);
|
||||
expect(cookies[0].httpOnly).toBe(true);
|
||||
});
|
||||
it.skip(FFOX || WEBKIT)('should properly report "Strict" sameSite cookie', async({page, server}) => {
|
||||
it.skip(WEBKIT)('should properly report "Strict" sameSite cookie', async({context, page, server}) => {
|
||||
server.setRoute('/empty.html', (req, res) => {
|
||||
res.setHeader('Set-Cookie', ';SameSite=Strict');
|
||||
res.end();
|
||||
});
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const cookies = await page.cookies();
|
||||
const cookies = await context.cookies();
|
||||
expect(cookies.length).toBe(1);
|
||||
expect(cookies[0].sameSite).toBe('Strict');
|
||||
});
|
||||
it.skip(FFOX || WEBKIT)('should properly report "Lax" sameSite cookie', async({page, server}) => {
|
||||
it.skip(WEBKIT)('should properly report "Lax" sameSite cookie', async({context, page, server}) => {
|
||||
server.setRoute('/empty.html', (req, res) => {
|
||||
res.setHeader('Set-Cookie', ';SameSite=Lax');
|
||||
res.end();
|
||||
});
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const cookies = await page.cookies();
|
||||
const cookies = await context.cookies();
|
||||
expect(cookies.length).toBe(1);
|
||||
expect(cookies[0].sameSite).toBe('Lax');
|
||||
});
|
||||
it('should get multiple cookies', async({page, server}) => {
|
||||
it('should get multiple cookies', async({context, page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await page.evaluate(() => {
|
||||
document.cookie = 'username=John Doe';
|
||||
document.cookie = 'password=1234';
|
||||
});
|
||||
const cookies = await page.cookies();
|
||||
const cookies = await context.cookies();
|
||||
cookies.sort((a, b) => a.name.localeCompare(b.name));
|
||||
expect(cookies).toEqual([
|
||||
{
|
||||
@ -107,8 +107,8 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||
},
|
||||
]);
|
||||
});
|
||||
it.skip(WEBKIT)('should get cookies from multiple urls', async({page, server}) => {
|
||||
await page.setCookie({
|
||||
it.skip(WEBKIT)('should get cookies from multiple urls', async({context}) => {
|
||||
await context.setCookies([{
|
||||
url: 'https://foo.com',
|
||||
name: 'doggo',
|
||||
value: 'woofs',
|
||||
@ -120,8 +120,8 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||
url: 'https://baz.com',
|
||||
name: 'birdo',
|
||||
value: 'tweets',
|
||||
});
|
||||
const cookies = await page.cookies('https://foo.com', 'https://baz.com');
|
||||
}]);
|
||||
const cookies = await context.cookies('https://foo.com', 'https://baz.com');
|
||||
cookies.sort((a, b) => a.name.localeCompare(b.name));
|
||||
expect(cookies).toEqual([{
|
||||
name: 'birdo',
|
||||
@ -149,27 +149,23 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||
});
|
||||
});
|
||||
|
||||
describe.skip(WEBKIT)('Page.setCookie', function() {
|
||||
it('should work', async({page, server}) => {
|
||||
describe.skip(WEBKIT)('BrowserContext.setCookies', function() {
|
||||
it('should work', async({context, page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await page.setCookie({
|
||||
await context.setCookies([{
|
||||
url: server.EMPTY_PAGE,
|
||||
name: 'password',
|
||||
value: '123456'
|
||||
});
|
||||
}]);
|
||||
expect(await page.evaluate(() => document.cookie)).toEqual('password=123456');
|
||||
});
|
||||
it('should isolate cookies in browser contexts', async({page, server, browser}) => {
|
||||
it('should isolate cookies in browser contexts', async({context, server, browser}) => {
|
||||
const anotherContext = await browser.createIncognitoBrowserContext();
|
||||
const anotherPage = await anotherContext.newPage();
|
||||
await context.setCookies([{url: server.EMPTY_PAGE, name: 'page1cookie', value: 'page1value'}]);
|
||||
await anotherContext.setCookies([{url: server.EMPTY_PAGE, name: 'page2cookie', value: 'page2value'}]);
|
||||
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await anotherPage.goto(server.EMPTY_PAGE);
|
||||
|
||||
await page.setCookie({name: 'page1cookie', value: 'page1value'});
|
||||
await anotherPage.setCookie({name: 'page2cookie', value: 'page2value'});
|
||||
|
||||
const cookies1 = await page.cookies();
|
||||
const cookies2 = await anotherPage.cookies();
|
||||
const cookies1 = await context.cookies();
|
||||
const cookies2 = await anotherContext.cookies();
|
||||
expect(cookies1.length).toBe(1);
|
||||
expect(cookies2.length).toBe(1);
|
||||
expect(cookies1[0].name).toBe('page1cookie');
|
||||
@ -178,15 +174,17 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||
expect(cookies2[0].value).toBe('page2value');
|
||||
await anotherContext.close();
|
||||
});
|
||||
it('should set multiple cookies', async({page, server}) => {
|
||||
it('should set multiple cookies', async({context, page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await page.setCookie({
|
||||
await context.setCookies([{
|
||||
url: server.EMPTY_PAGE,
|
||||
name: 'password',
|
||||
value: '123456'
|
||||
}, {
|
||||
url: server.EMPTY_PAGE,
|
||||
name: 'foo',
|
||||
value: 'bar'
|
||||
});
|
||||
}]);
|
||||
expect(await page.evaluate(() => {
|
||||
const cookies = document.cookie.split(';');
|
||||
return cookies.map(cookie => cookie.trim()).sort();
|
||||
@ -195,23 +193,23 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||
'password=123456',
|
||||
]);
|
||||
});
|
||||
it('should have |expires| set to |-1| for session cookies', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await page.setCookie({
|
||||
it('should have |expires| set to |-1| for session cookies', async({context, server}) => {
|
||||
await context.setCookies([{
|
||||
url: server.EMPTY_PAGE,
|
||||
name: 'password',
|
||||
value: '123456'
|
||||
});
|
||||
const cookies = await page.cookies();
|
||||
}]);
|
||||
const cookies = await context.cookies();
|
||||
expect(cookies[0].session).toBe(true);
|
||||
expect(cookies[0].expires).toBe(-1);
|
||||
});
|
||||
it('should set cookie with reasonable defaults', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await page.setCookie({
|
||||
it('should set cookie with reasonable defaults', async({context, server}) => {
|
||||
await context.setCookies([{
|
||||
url: server.EMPTY_PAGE,
|
||||
name: 'password',
|
||||
value: '123456'
|
||||
});
|
||||
const cookies = await page.cookies();
|
||||
}]);
|
||||
const cookies = await context.cookies();
|
||||
expect(cookies.sort((a, b) => a.name.localeCompare(b.name))).toEqual([{
|
||||
name: 'password',
|
||||
value: '123456',
|
||||
@ -225,14 +223,15 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||
sameSite: 'None',
|
||||
}]);
|
||||
});
|
||||
it('should set a cookie with a path', async({page, server}) => {
|
||||
it('should set a cookie with a path', async({context, page, server}) => {
|
||||
await page.goto(server.PREFIX + '/grid.html');
|
||||
await page.setCookie({
|
||||
await context.setCookies([{
|
||||
domain: 'localhost',
|
||||
path: '/grid.html',
|
||||
name: 'gridcookie',
|
||||
value: 'GRID',
|
||||
path: '/grid.html'
|
||||
});
|
||||
expect(await page.cookies()).toEqual([{
|
||||
}]);
|
||||
expect(await context.cookies()).toEqual([{
|
||||
name: 'gridcookie',
|
||||
value: 'GRID',
|
||||
domain: 'localhost',
|
||||
@ -246,29 +245,17 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||
}]);
|
||||
expect(await page.evaluate('document.cookie')).toBe('gridcookie=GRID');
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
expect(await page.cookies()).toEqual([]);
|
||||
expect(await page.evaluate('document.cookie')).toBe('');
|
||||
await page.goto(server.PREFIX + '/grid.html');
|
||||
expect(await page.evaluate('document.cookie')).toBe('gridcookie=GRID');
|
||||
});
|
||||
it('should not set a cookie on a blank page', async function({page}) {
|
||||
await page.goto('about:blank');
|
||||
it('should not set a cookie with blank page URL', async function({context, server}) {
|
||||
let error = null;
|
||||
try {
|
||||
await page.setCookie({name: 'example-cookie', value: 'best'});
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
expect(error.message).toContain('At least one of the url and domain needs to be specified');
|
||||
});
|
||||
it('should not set a cookie with blank page URL', async function({page, server}) {
|
||||
let error = null;
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
try {
|
||||
await page.setCookie(
|
||||
{name: 'example-cookie', value: 'best'},
|
||||
await context.setCookies([
|
||||
{url: server.EMPTY_PAGE, name: 'example-cookie', value: 'best'},
|
||||
{url: 'about:blank', name: 'example-cookie-blank', value: 'best'}
|
||||
);
|
||||
]);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
@ -276,48 +263,46 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||
`Blank page can not have cookie "example-cookie-blank"`
|
||||
);
|
||||
});
|
||||
it('should not set a cookie on a data URL page', async function({page}) {
|
||||
it('should not set a cookie on a data URL page', async function({context}) {
|
||||
let error = null;
|
||||
await page.goto('data:,Hello%2C%20World!');
|
||||
try {
|
||||
await page.setCookie({name: 'example-cookie', value: 'best'});
|
||||
await context.setCookies([{url: 'data:,Hello%2C%20World!', name: 'example-cookie', value: 'best'}]);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
expect(error.message).toContain('At least one of the url and domain needs to be specified');
|
||||
expect(error.message).toContain('Data URL page can not have cookie "example-cookie"');
|
||||
});
|
||||
it('should default to setting secure cookie for HTTPS websites', async({page, server}) => {
|
||||
it('should default to setting secure cookie for HTTPS websites', async({context, page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const SECURE_URL = 'https://example.com';
|
||||
await page.setCookie({
|
||||
await context.setCookies([{
|
||||
url: SECURE_URL,
|
||||
name: 'foo',
|
||||
value: 'bar',
|
||||
});
|
||||
const [cookie] = await page.cookies(SECURE_URL);
|
||||
}]);
|
||||
const [cookie] = await context.cookies(SECURE_URL);
|
||||
expect(cookie.secure).toBe(true);
|
||||
});
|
||||
it('should be able to set unsecure cookie for HTTP website', async({page, server}) => {
|
||||
it('should be able to set unsecure cookie for HTTP website', async({context, page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const HTTP_URL = 'http://example.com';
|
||||
await page.setCookie({
|
||||
await context.setCookies([{
|
||||
url: HTTP_URL,
|
||||
name: 'foo',
|
||||
value: 'bar',
|
||||
});
|
||||
const [cookie] = await page.cookies(HTTP_URL);
|
||||
}]);
|
||||
const [cookie] = await context.cookies(HTTP_URL);
|
||||
expect(cookie.secure).toBe(false);
|
||||
});
|
||||
it('should set a cookie on a different domain', async({page, server}) => {
|
||||
it('should set a cookie on a different domain', async({context, page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await page.setCookie({
|
||||
await context.setCookies([{
|
||||
url: 'https://www.example.com',
|
||||
name: 'example-cookie',
|
||||
value: 'best',
|
||||
});
|
||||
}]);
|
||||
expect(await page.evaluate('document.cookie')).toBe('');
|
||||
expect(await page.cookies()).toEqual([]);
|
||||
expect(await page.cookies('https://www.example.com')).toEqual([{
|
||||
expect(await context.cookies('https://www.example.com')).toEqual([{
|
||||
name: 'example-cookie',
|
||||
value: 'best',
|
||||
domain: 'www.example.com',
|
||||
@ -330,9 +315,12 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||
sameSite: 'None',
|
||||
}]);
|
||||
});
|
||||
it('should set cookies from a frame', async({page, server}) => {
|
||||
it('should set cookies from a frame', async({context, page, server}) => {
|
||||
await page.goto(server.PREFIX + '/grid.html');
|
||||
await page.setCookie({name: 'localhost-cookie', value: 'best'});
|
||||
await context.setCookies([
|
||||
{url: server.PREFIX, name: 'localhost-cookie', value: 'best'},
|
||||
{url: server.CROSS_PROCESS_PREFIX, name: '127-cookie', value: 'worst'}
|
||||
]);
|
||||
await page.evaluate(src => {
|
||||
let fulfill;
|
||||
const promise = new Promise(x => fulfill = x);
|
||||
@ -342,11 +330,10 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||
iframe.src = src;
|
||||
return promise;
|
||||
}, server.CROSS_PROCESS_PREFIX);
|
||||
await page.setCookie({name: '127-cookie', value: 'worst', url: server.CROSS_PROCESS_PREFIX});
|
||||
expect(await page.evaluate('document.cookie')).toBe('localhost-cookie=best');
|
||||
expect(await page.frames()[1].evaluate('document.cookie')).toBe('127-cookie=worst');
|
||||
|
||||
expect(await page.cookies()).toEqual([{
|
||||
expect(await context.cookies(server.PREFIX)).toEqual([{
|
||||
name: 'localhost-cookie',
|
||||
value: 'best',
|
||||
domain: 'localhost',
|
||||
@ -359,7 +346,7 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||
sameSite: 'None',
|
||||
}]);
|
||||
|
||||
expect(await page.cookies(server.CROSS_PROCESS_PREFIX)).toEqual([{
|
||||
expect(await context.cookies(server.CROSS_PROCESS_PREFIX)).toEqual([{
|
||||
name: '127-cookie',
|
||||
value: 'worst',
|
||||
domain: '127.0.0.1',
|
||||
@ -374,22 +361,35 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Page.deleteCookie', function() {
|
||||
it.skip(WEBKIT)('should work', async({page, server}) => {
|
||||
describe.skip(WEBKIT)('BrowserContext.setCookies', function() {
|
||||
it.skip(WEBKIT)('should clear cookies', async({context, page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await page.setCookie({
|
||||
await context.setCookies([{
|
||||
url: server.EMPTY_PAGE,
|
||||
name: 'cookie1',
|
||||
value: '1'
|
||||
}, {
|
||||
name: 'cookie2',
|
||||
value: '2'
|
||||
}, {
|
||||
name: 'cookie3',
|
||||
value: '3'
|
||||
});
|
||||
expect(await page.evaluate('document.cookie')).toBe('cookie1=1; cookie2=2; cookie3=3');
|
||||
await page.deleteCookie({name: 'cookie2'});
|
||||
expect(await page.evaluate('document.cookie')).toBe('cookie1=1; cookie3=3');
|
||||
}]);
|
||||
expect(await page.evaluate('document.cookie')).toBe('cookie1=1');
|
||||
await context.clearCookies();
|
||||
expect(await page.evaluate('document.cookie')).toBe('');
|
||||
});
|
||||
it('should isolate cookies when clearing', async({context, server, browser}) => {
|
||||
const anotherContext = await browser.createIncognitoBrowserContext();
|
||||
await context.setCookies([{url: server.EMPTY_PAGE, name: 'page1cookie', value: 'page1value'}]);
|
||||
await anotherContext.setCookies([{url: server.EMPTY_PAGE, name: 'page2cookie', value: 'page2value'}]);
|
||||
|
||||
expect((await context.cookies()).length).toBe(1);
|
||||
expect((await anotherContext.cookies()).length).toBe(1);
|
||||
|
||||
await context.clearCookies();
|
||||
expect((await context.cookies()).length).toBe(0);
|
||||
expect((await anotherContext.cookies()).length).toBe(1);
|
||||
|
||||
await anotherContext.clearCookies();
|
||||
expect((await context.cookies()).length).toBe(0);
|
||||
expect((await anotherContext.cookies()).length).toBe(0);
|
||||
|
||||
await anotherContext.close();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user