Revert "fix: move offline/cache/interception switches to BrowserContext (#748)" (#793)

This reverts commit 6faf74bc95.
This commit is contained in:
Pavel Feldman 2020-01-31 16:23:15 -08:00 committed by GitHub
parent 9438136ae9
commit ef1d2fb995
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 200 additions and 257 deletions

View file

@ -212,9 +212,6 @@ Indicates that the browser is connected.
- `deviceScaleFactor` <[number]> Specify device scale factor (can be thought of as dpr). Defaults to `1`. - `deviceScaleFactor` <[number]> Specify device scale factor (can be thought of as dpr). Defaults to `1`.
- `isMobile` <[boolean]> Whether the `meta viewport` tag is taken into account. Defaults to `false`. - `isMobile` <[boolean]> Whether the `meta viewport` tag is taken into account. Defaults to `false`.
- `userAgent` <?[string]> Specific user agent to use in this context. - `userAgent` <?[string]> Specific user agent to use in this context.
- `cacheEnabled` <?[boolean]> Toggles HTTP cache in the context. By default HTTP cache is enabled.
- `interceptNetwork` <?[boolean]> Toggles network interception in the context. Defaults to false.
- `offlineMode` <?[boolean]> Toggles offline network mode in the context. Defaults to false.
- `javaScriptEnabled` <?[boolean]> Whether or not to enable or disable JavaScript in the context. Defaults to true. - `javaScriptEnabled` <?[boolean]> Whether or not to enable or disable JavaScript in the context. Defaults to true.
- `timezoneId` <?[string]> Changes the timezone of the context. See [ICUs `metaZones.txt`](https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1) for a list of supported timezone IDs. - `timezoneId` <?[string]> Changes the timezone of the context. See [ICUs `metaZones.txt`](https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1) for a list of supported timezone IDs.
- `geolocation` <[Object]> - `geolocation` <[Object]>
@ -264,12 +261,9 @@ await context.close();
- [browserContext.cookies([...urls])](#browsercontextcookiesurls) - [browserContext.cookies([...urls])](#browsercontextcookiesurls)
- [browserContext.newPage(url)](#browsercontextnewpageurl) - [browserContext.newPage(url)](#browsercontextnewpageurl)
- [browserContext.pages()](#browsercontextpages) - [browserContext.pages()](#browsercontextpages)
- [browserContext.setCacheEnabled([enabled])](#browsercontextsetcacheenabledenabled)
- [browserContext.setCookies(cookies)](#browsercontextsetcookiescookies) - [browserContext.setCookies(cookies)](#browsercontextsetcookiescookies)
- [browserContext.setGeolocation(geolocation)](#browsercontextsetgeolocationgeolocation) - [browserContext.setGeolocation(geolocation)](#browsercontextsetgeolocationgeolocation)
- [browserContext.setOfflineMode(enabled)](#browsercontextsetofflinemodeenabled)
- [browserContext.setPermissions(origin, permissions[])](#browsercontextsetpermissionsorigin-permissions) - [browserContext.setPermissions(origin, permissions[])](#browsercontextsetpermissionsorigin-permissions)
- [browserContext.setRequestInterception(enabled)](#browsercontextsetrequestinterceptionenabled)
<!-- GEN:stop --> <!-- GEN:stop -->
#### browserContext.clearCookies() #### browserContext.clearCookies()
@ -327,12 +321,6 @@ Creates a new page in the browser context and optionally navigates it to the spe
An array of all pages inside the browser context. An array of all pages inside the browser context.
#### browserContext.setCacheEnabled([enabled])
- `enabled` <[boolean]> sets the `enabled` state of the HTTP cache.
- returns: <[Promise]>
Toggles ignoring HTTP cache for each request based on the enabled state. By default, HTTP cache is enabled.
#### browserContext.setCookies(cookies) #### browserContext.setCookies(cookies)
- `cookies` <[Array]<[Object]>> - `cookies` <[Array]<[Object]>>
- `name` <[string]> **required** - `name` <[string]> **required**
@ -365,10 +353,6 @@ await browserContext.setGeolocation({latitude: 59.95, longitude: 30.31667});
> **NOTE** Consider using [browserContext.setPermissions](#browsercontextsetpermissions-permissions) to grant permissions for the page to read its geolocation. > **NOTE** Consider using [browserContext.setPermissions](#browsercontextsetpermissions-permissions) to grant permissions for the page to read its geolocation.
#### browserContext.setOfflineMode(enabled)
- `enabled` <[boolean]> When `true`, enables offline mode for the context.
- returns: <[Promise]>
#### browserContext.setPermissions(origin, permissions[]) #### browserContext.setPermissions(origin, permissions[])
- `origin` <[string]> The [origin] to grant permissions to, e.g. "https://example.com". - `origin` <[string]> The [origin] to grant permissions to, e.g. "https://example.com".
- `permissions` <[Array]<[string]>> An array of permissions to grant. All permissions that are not listed here will be automatically denied. Permissions can be one of the following values: - `permissions` <[Array]<[string]>> An array of permissions to grant. All permissions that are not listed here will be automatically denied. Permissions can be one of the following values:
@ -396,32 +380,6 @@ const context = browser.defaultContext();
await context.setPermissions('https://html5demos.com', ['geolocation']); await context.setPermissions('https://html5demos.com', ['geolocation']);
``` ```
#### browserContext.setRequestInterception(enabled)
- `enabled` <[boolean]> Whether to enable request interception.
- returns: <[Promise]>
Activating request interception enables `request.abort`, `request.continue` and
`request.respond` methods. This provides the capability to modify network requests that are made by all pages in the context.
Once request interception is enabled, every request will stall unless it's continued, responded or aborted.
An example of a naïve request interceptor that aborts all image requests:
```js
const context = await browser.newContext();
const page = await context.newPage();
page.on('request', interceptedRequest => {
if (interceptedRequest.url().endsWith('.png') || interceptedRequest.url().endsWith('.jpg'))
interceptedRequest.abort();
else
interceptedRequest.continue();
});
await context.setRequestInterception(true);
await page.goto('https://example.com');
await browser.close();
```
> **NOTE** Enabling request interception disables HTTP cache.
### class: Page ### class: Page
* extends: [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter) * extends: [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter)
@ -513,10 +471,13 @@ page.removeListener('request', logRequest);
- [page.reload([options])](#pagereloadoptions) - [page.reload([options])](#pagereloadoptions)
- [page.screenshot([options])](#pagescreenshotoptions) - [page.screenshot([options])](#pagescreenshotoptions)
- [page.select(selector, value, options)](#pageselectselector-value-options) - [page.select(selector, value, options)](#pageselectselector-value-options)
- [page.setCacheEnabled([enabled])](#pagesetcacheenabledenabled)
- [page.setContent(html[, options])](#pagesetcontenthtml-options) - [page.setContent(html[, options])](#pagesetcontenthtml-options)
- [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout) - [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout)
- [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout) - [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout)
- [page.setExtraHTTPHeaders(headers)](#pagesetextrahttpheadersheaders) - [page.setExtraHTTPHeaders(headers)](#pagesetextrahttpheadersheaders)
- [page.setOfflineMode(enabled)](#pagesetofflinemodeenabled)
- [page.setRequestInterception(enabled)](#pagesetrequestinterceptionenabled)
- [page.setViewport(viewport)](#pagesetviewportviewport) - [page.setViewport(viewport)](#pagesetviewportviewport)
- [page.title()](#pagetitle) - [page.title()](#pagetitle)
- [page.tripleclick(selector[, options])](#pagetripleclickselector-options) - [page.tripleclick(selector[, options])](#pagetripleclickselector-options)
@ -1261,6 +1222,12 @@ page.select('select#colors', { value: 'blue' }, { index: 2 }, 'red');
Shortcut for [page.mainFrame().select()](#frameselectselector-values) Shortcut for [page.mainFrame().select()](#frameselectselector-values)
#### page.setCacheEnabled([enabled])
- `enabled` <[boolean]> sets the `enabled` state of the cache.
- returns: <[Promise]>
Toggles ignoring cache for each request based on the enabled state. By default, caching is enabled.
#### page.setContent(html[, options]) #### page.setContent(html[, options])
- `html` <[string]> HTML markup to assign to the page. - `html` <[string]> HTML markup to assign to the page.
- `options` <[Object]> Parameters which might have the following properties: - `options` <[Object]> Parameters which might have the following properties:
@ -1312,6 +1279,35 @@ The extra HTTP headers will be sent with every request the page initiates.
> **NOTE** page.setExtraHTTPHeaders does not guarantee the order of headers in the outgoing requests. > **NOTE** page.setExtraHTTPHeaders does not guarantee the order of headers in the outgoing requests.
#### page.setOfflineMode(enabled)
- `enabled` <[boolean]> When `true`, enables offline mode for the page.
- returns: <[Promise]>
#### page.setRequestInterception(enabled)
- `enabled` <[boolean]> Whether to enable request interception.
- returns: <[Promise]>
Activating request interception enables `request.abort`, `request.continue` and
`request.respond` methods. This provides the capability to modify network requests that are made by a page.
Once request interception is enabled, every request will stall unless it's continued, responded or aborted.
An example of a naïve request interceptor that aborts all image requests:
```js
const page = await browser.newPage();
await page.setRequestInterception(true);
page.on('request', interceptedRequest => {
if (interceptedRequest.url().endsWith('.png') || interceptedRequest.url().endsWith('.jpg'))
interceptedRequest.abort();
else
interceptedRequest.continue();
});
await page.goto('https://example.com');
await browser.close();
```
> **NOTE** Enabling request interception disables page caching.
#### page.setViewport(viewport) #### page.setViewport(viewport)
- `viewport` <[Object]> - `viewport` <[Object]>
- `width` <[number]> page width in pixels. **required** - `width` <[number]> page width in pixels. **required**

View file

@ -42,9 +42,6 @@ export type BrowserContextOptions = {
javaScriptEnabled?: boolean, javaScriptEnabled?: boolean,
bypassCSP?: boolean, bypassCSP?: boolean,
userAgent?: string, userAgent?: string,
cacheEnabled?: boolean;
interceptNetwork?: boolean;
offlineMode?: boolean;
timezoneId?: string, timezoneId?: string,
geolocation?: types.Geolocation, geolocation?: types.Geolocation,
permissions?: { [key: string]: string[] }; permissions?: { [key: string]: string[] };
@ -115,27 +112,6 @@ export class BrowserContext {
await this._delegate.setGeolocation(geolocation); await this._delegate.setGeolocation(geolocation);
} }
async setCacheEnabled(enabled: boolean = true) {
if (this._options.cacheEnabled === enabled)
return;
this._options.cacheEnabled = enabled;
await Promise.all(this._existingPages().map(page => page._delegate.setCacheEnabled(enabled)));
}
async setRequestInterception(enabled: boolean) {
if (this._options.interceptNetwork === enabled)
return;
this._options.interceptNetwork = enabled;
await Promise.all(this._existingPages().map(page => page._delegate.setRequestInterception(enabled)));
}
async setOfflineMode(enabled: boolean) {
if (this._options.offlineMode === enabled)
return;
this._options.offlineMode = enabled;
await Promise.all(this._existingPages().map(page => page._delegate.setOfflineMode(enabled)));
}
async close() { async close() {
if (this._closed) if (this._closed)
return; return;

View file

@ -29,9 +29,12 @@ export class CRNetworkManager {
private _page: Page; private _page: Page;
private _requestIdToRequest = new Map<string, InterceptableRequest>(); private _requestIdToRequest = new Map<string, InterceptableRequest>();
private _requestIdToRequestWillBeSentEvent = new Map<string, Protocol.Network.requestWillBeSentPayload>(); private _requestIdToRequestWillBeSentEvent = new Map<string, Protocol.Network.requestWillBeSentPayload>();
private _offline = false;
private _credentials: {username: string, password: string} | null = null; private _credentials: {username: string, password: string} | null = null;
private _attemptedAuthentications = new Set<string>(); private _attemptedAuthentications = new Set<string>();
private _userRequestInterceptionEnabled = false;
private _protocolRequestInterceptionEnabled = false; private _protocolRequestInterceptionEnabled = false;
private _userCacheDisabled = false;
private _requestIdToInterceptionId = new Map<string, string>(); private _requestIdToInterceptionId = new Map<string, string>();
private _eventListeners: RegisteredListener[]; private _eventListeners: RegisteredListener[];
@ -60,17 +63,7 @@ export class CRNetworkManager {
} }
async initialize() { async initialize() {
const promises: Promise<any>[] = [ await this._client.send('Network.enable');
this._client.send('Network.enable')
];
const options = this._page.browserContext()._options;
if (options.offlineMode)
promises.push(this.setOfflineMode(options.offlineMode));
if (this._userRequestInterceptionEnabled())
promises.push(this._updateProtocolRequestInterception());
else if (options.cacheEnabled === false)
promises.push(this._updateProtocolCacheDisabled());
await Promise.all(promises);
} }
dispose() { dispose() {
@ -82,9 +75,10 @@ export class CRNetworkManager {
await this._updateProtocolRequestInterception(); await this._updateProtocolRequestInterception();
} }
async setOfflineMode(offline: boolean) { async setOfflineMode(value: boolean) {
this._offline = value;
await this._client.send('Network.emulateNetworkConditions', { await this._client.send('Network.emulateNetworkConditions', {
offline, offline: this._offline,
// values of 0 remove any active throttling. crbug.com/456324#c9 // values of 0 remove any active throttling. crbug.com/456324#c9
latency: 0, latency: 0,
downloadThroughput: -1, downloadThroughput: -1,
@ -97,19 +91,17 @@ export class CRNetworkManager {
} }
async setCacheEnabled(enabled: boolean) { async setCacheEnabled(enabled: boolean) {
this._userCacheDisabled = !enabled;
await this._updateProtocolCacheDisabled(); await this._updateProtocolCacheDisabled();
} }
async setRequestInterception(value: boolean) { async setRequestInterception(value: boolean) {
this._userRequestInterceptionEnabled = value;
await this._updateProtocolRequestInterception(); await this._updateProtocolRequestInterception();
} }
private _userRequestInterceptionEnabled() : boolean { async _updateProtocolRequestInterception() {
return !!this._page.browserContext()._options.interceptNetwork; const enabled = this._userRequestInterceptionEnabled || !!this._credentials;
}
private async _updateProtocolRequestInterception() {
const enabled = this._userRequestInterceptionEnabled() || !!this._credentials;
if (enabled === this._protocolRequestInterceptionEnabled) if (enabled === this._protocolRequestInterceptionEnabled)
return; return;
this._protocolRequestInterceptionEnabled = enabled; this._protocolRequestInterceptionEnabled = enabled;
@ -129,15 +121,13 @@ export class CRNetworkManager {
} }
} }
private async _updateProtocolCacheDisabled() { async _updateProtocolCacheDisabled() {
const options = this._page.browserContext()._options;
const cacheDisabled = options.cacheEnabled === false;
await this._client.send('Network.setCacheDisabled', { await this._client.send('Network.setCacheDisabled', {
cacheDisabled: cacheDisabled || this._protocolRequestInterceptionEnabled cacheDisabled: this._userCacheDisabled || this._protocolRequestInterceptionEnabled
}); });
} }
private _onRequestWillBeSent(event: Protocol.Network.requestWillBeSentPayload) { _onRequestWillBeSent(event: Protocol.Network.requestWillBeSentPayload) {
// Request interception doesn't happen for data URLs with Network Service. // Request interception doesn't happen for data URLs with Network Service.
if (this._protocolRequestInterceptionEnabled && !event.request.url.startsWith('data:')) { if (this._protocolRequestInterceptionEnabled && !event.request.url.startsWith('data:')) {
const requestId = event.requestId; const requestId = event.requestId;
@ -153,7 +143,7 @@ export class CRNetworkManager {
this._onRequest(event, null); this._onRequest(event, null);
} }
private _onAuthRequired(event: Protocol.Fetch.authRequiredPayload) { _onAuthRequired(event: Protocol.Fetch.authRequiredPayload) {
let response: 'Default' | 'CancelAuth' | 'ProvideCredentials' = 'Default'; let response: 'Default' | 'CancelAuth' | 'ProvideCredentials' = 'Default';
if (this._attemptedAuthentications.has(event.requestId)) { if (this._attemptedAuthentications.has(event.requestId)) {
response = 'CancelAuth'; response = 'CancelAuth';
@ -168,8 +158,8 @@ export class CRNetworkManager {
}).catch(debugError); }).catch(debugError);
} }
private _onRequestPaused(event: Protocol.Fetch.requestPausedPayload) { _onRequestPaused(event: Protocol.Fetch.requestPausedPayload) {
if (!this._userRequestInterceptionEnabled() && this._protocolRequestInterceptionEnabled) { if (!this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled) {
this._client.send('Fetch.continueRequest', { this._client.send('Fetch.continueRequest', {
requestId: event.requestId requestId: event.requestId
}).catch(debugError); }).catch(debugError);
@ -188,7 +178,7 @@ export class CRNetworkManager {
} }
} }
private _onRequest(event: Protocol.Network.requestWillBeSentPayload, interceptionId: string | null) { _onRequest(event: Protocol.Network.requestWillBeSentPayload, interceptionId: string | null) {
if (event.request.url.startsWith('data:')) if (event.request.url.startsWith('data:'))
return; return;
let redirectChain: network.Request[] = []; let redirectChain: network.Request[] = [];
@ -204,12 +194,12 @@ export class CRNetworkManager {
const frame = event.frameId ? this._page._frameManager.frame(event.frameId) : null; const frame = event.frameId ? this._page._frameManager.frame(event.frameId) : null;
const isNavigationRequest = event.requestId === event.loaderId && event.type === 'Document'; const isNavigationRequest = event.requestId === event.loaderId && event.type === 'Document';
const documentId = isNavigationRequest ? event.loaderId : undefined; const documentId = isNavigationRequest ? event.loaderId : undefined;
const request = new InterceptableRequest(this._client, frame, interceptionId, documentId, this._userRequestInterceptionEnabled(), event, redirectChain); const request = new InterceptableRequest(this._client, frame, interceptionId, documentId, this._userRequestInterceptionEnabled, event, redirectChain);
this._requestIdToRequest.set(event.requestId, request); this._requestIdToRequest.set(event.requestId, request);
this._page._frameManager.requestStarted(request.request); this._page._frameManager.requestStarted(request.request);
} }
private _createResponse(request: InterceptableRequest, responsePayload: Protocol.Network.Response): network.Response { _createResponse(request: InterceptableRequest, responsePayload: Protocol.Network.Response): network.Response {
const getResponseBody = async () => { const getResponseBody = async () => {
const response = await this._client.send('Network.getResponseBody', { requestId: request._requestId }); const response = await this._client.send('Network.getResponseBody', { requestId: request._requestId });
return platform.Buffer.from(response.body, response.base64Encoded ? 'base64' : 'utf8'); return platform.Buffer.from(response.body, response.base64Encoded ? 'base64' : 'utf8');
@ -217,7 +207,7 @@ export class CRNetworkManager {
return new network.Response(request.request, responsePayload.status, responsePayload.statusText, headersObject(responsePayload.headers), getResponseBody); return new network.Response(request.request, responsePayload.status, responsePayload.statusText, headersObject(responsePayload.headers), getResponseBody);
} }
private _handleRequestRedirect(request: InterceptableRequest, responsePayload: Protocol.Network.Response) { _handleRequestRedirect(request: InterceptableRequest, responsePayload: Protocol.Network.Response) {
const response = this._createResponse(request, responsePayload); const response = this._createResponse(request, responsePayload);
request.request._redirectChain.push(request.request); request.request._redirectChain.push(request.request);
response._requestFinished(new Error('Response body is unavailable for redirect responses')); response._requestFinished(new Error('Response body is unavailable for redirect responses'));
@ -228,7 +218,7 @@ export class CRNetworkManager {
this._page._frameManager.requestFinished(request.request); this._page._frameManager.requestFinished(request.request);
} }
private _onResponseReceived(event: Protocol.Network.responseReceivedPayload) { _onResponseReceived(event: Protocol.Network.responseReceivedPayload) {
const request = this._requestIdToRequest.get(event.requestId); const request = this._requestIdToRequest.get(event.requestId);
// FileUpload sends a response without a matching request. // FileUpload sends a response without a matching request.
if (!request) if (!request)
@ -237,7 +227,7 @@ export class CRNetworkManager {
this._page._frameManager.requestReceivedResponse(response); this._page._frameManager.requestReceivedResponse(response);
} }
private _onLoadingFinished(event: Protocol.Network.loadingFinishedPayload) { _onLoadingFinished(event: Protocol.Network.loadingFinishedPayload) {
const request = this._requestIdToRequest.get(event.requestId); const request = this._requestIdToRequest.get(event.requestId);
// For certain requestIds we never receive requestWillBeSent event. // For certain requestIds we never receive requestWillBeSent event.
// @see https://crbug.com/750469 // @see https://crbug.com/750469
@ -255,7 +245,7 @@ export class CRNetworkManager {
this._page._frameManager.requestFinished(request.request); this._page._frameManager.requestFinished(request.request);
} }
private _onLoadingFailed(event: Protocol.Network.loadingFailedPayload) { _onLoadingFailed(event: Protocol.Network.loadingFailedPayload) {
const request = this._requestIdToRequest.get(event.requestId); const request = this._requestIdToRequest.get(event.requestId);
// For certain requestIds we never receive requestWillBeSent event. // For certain requestIds we never receive requestWillBeSent event.
// @see https://crbug.com/750469 // @see https://crbug.com/750469

View file

@ -89,10 +89,6 @@ export class FFPage implements PageDelegate {
promises.push(this._session.send('Page.setJavascriptEnabled', { enabled: false })); promises.push(this._session.send('Page.setJavascriptEnabled', { enabled: false }));
if (options.userAgent) if (options.userAgent)
promises.push(this._session.send('Page.setUserAgent', { userAgent: options.userAgent })); promises.push(this._session.send('Page.setUserAgent', { userAgent: options.userAgent }));
if (options.cacheEnabled === false)
promises.push(this.setCacheEnabled(false));
if (options.interceptNetwork)
promises.push(this.setRequestInterception(true));
await Promise.all(promises); await Promise.all(promises);
} }

View file

@ -77,6 +77,9 @@ type PageState = {
mediaType: types.MediaType | null; mediaType: types.MediaType | null;
colorScheme: types.ColorScheme | null; colorScheme: types.ColorScheme | null;
extraHTTPHeaders: network.Headers | null; extraHTTPHeaders: network.Headers | null;
cacheEnabled: boolean | null;
interceptNetwork: boolean | null;
offlineMode: boolean | null;
credentials: types.Credentials | null; credentials: types.Credentials | null;
hasTouch: boolean | null; hasTouch: boolean | null;
}; };
@ -120,6 +123,9 @@ export class Page extends platform.EventEmitter {
mediaType: null, mediaType: null,
colorScheme: null, colorScheme: null,
extraHTTPHeaders: null, extraHTTPHeaders: null,
cacheEnabled: null,
interceptNetwork: null,
offlineMode: null,
credentials: null, credentials: null,
hasTouch: null, hasTouch: null,
}; };
@ -397,6 +403,27 @@ export class Page extends platform.EventEmitter {
await this._delegate.evaluateOnNewDocument(source); await this._delegate.evaluateOnNewDocument(source);
} }
async setCacheEnabled(enabled: boolean = true) {
if (this._state.cacheEnabled === enabled)
return;
this._state.cacheEnabled = enabled;
await this._delegate.setCacheEnabled(enabled);
}
async setRequestInterception(enabled: boolean) {
if (this._state.interceptNetwork === enabled)
return;
this._state.interceptNetwork = enabled;
await this._delegate.setRequestInterception(enabled);
}
async setOfflineMode(enabled: boolean) {
if (this._state.offlineMode === enabled)
return;
this._state.offlineMode = enabled;
await this._delegate.setOfflineMode(enabled);
}
async authenticate(credentials: types.Credentials | null) { async authenticate(credentials: types.Credentials | null) {
this._state.credentials = credentials; this._state.credentials = credentials;
await this._delegate.authenticate(credentials); await this._delegate.authenticate(credentials);

View file

@ -121,13 +121,14 @@ export class WKPage implements PageDelegate {
this._workers.initializeSession(session) this._workers.initializeSession(session)
]; ];
const contextOptions = this._page.browserContext()._options; if (this._page._state.interceptNetwork)
if (contextOptions.interceptNetwork)
promises.push(session.send('Network.setInterceptionEnabled', { enabled: true, interceptRequests: true })); promises.push(session.send('Network.setInterceptionEnabled', { enabled: true, interceptRequests: true }));
if (contextOptions.offlineMode) if (this._page._state.offlineMode)
promises.push(session.send('Network.setEmulateOfflineState', { offline: true })); promises.push(session.send('Network.setEmulateOfflineState', { offline: true }));
if (contextOptions.cacheEnabled === false) if (this._page._state.cacheEnabled === false)
promises.push(session.send('Network.setResourceCachingDisabled', { disabled: true })); promises.push(session.send('Network.setResourceCachingDisabled', { disabled: true }));
const contextOptions = this._page.browserContext()._options;
if (contextOptions.userAgent) if (contextOptions.userAgent)
promises.push(session.send('Page.overrideUserAgent', { value: contextOptions.userAgent })); promises.push(session.send('Page.overrideUserAgent', { value: contextOptions.userAgent }));
if (this._page._state.mediaType || this._page._state.colorScheme) if (this._page._state.mediaType || this._page._state.colorScheme)
@ -584,7 +585,7 @@ export class WKPage implements PageDelegate {
// TODO(einbinder) this will fail if we are an XHR document request // TODO(einbinder) this will fail if we are an XHR document request
const isNavigationRequest = event.type === 'Document'; const isNavigationRequest = event.type === 'Document';
const documentId = isNavigationRequest ? event.loaderId : undefined; const documentId = isNavigationRequest ? event.loaderId : undefined;
const request = new WKInterceptableRequest(session, !!this._page.browserContext()._options.interceptNetwork, frame, event, redirectChain, documentId); const request = new WKInterceptableRequest(session, !!this._page._state.interceptNetwork, frame, event, redirectChain, documentId);
this._requestIdToRequest.set(event.requestId, request); this._requestIdToRequest.set(event.requestId, request);
this._page._frameManager.requestStarted(request.request); this._page._frameManager.requestStarted(request.request);
} }

View file

@ -17,7 +17,7 @@
const utils = require('./utils'); const utils = require('./utils');
module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, WEBKIT, FFOX}) { module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, WEBKIT}) {
const {describe, xdescribe, fdescribe} = testRunner; const {describe, xdescribe, fdescribe} = testRunner;
const {it, fit, xit, dit} = testRunner; const {it, fit, xit, dit} = testRunner;
const {beforeAll, beforeEach, afterAll, afterEach} = testRunner; const {beforeAll, beforeEach, afterAll, afterEach} = testRunner;
@ -313,40 +313,4 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, WE
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
}); });
}); });
describe.skip(FFOX)('BrowserContext({offlineMode})', function() {
it('should create offline pages', async({newPage, server}) => {
const page = await newPage({ offlineMode: true });
expect(await page.evaluate(() => window.navigator.onLine)).toBe(false);
let error = null;
await page.goto(server.EMPTY_PAGE).catch(e => error = e);
expect(error).toBeTruthy();
});
});
describe('BrowserContext({cacheEnabled})', function() {
it('should create pages with disabled cache', async({newPage, server}) => {
const page = await newPage({ cacheEnabled: false });
await page.goto(server.PREFIX + '/cached/one-style.html');
// WebKit does r.setCachePolicy(ResourceRequestCachePolicy::ReloadIgnoringCacheData);
// when navigating to the same url, load empty.html to avoid that.
await page.goto(server.EMPTY_PAGE);
const [cachedRequest] = await Promise.all([
server.waitForRequest('/cached/one-style.html'),
page.goto(server.PREFIX + '/cached/one-style.html'),
]);
// Rely on "if-modified-since" caching in our test server.
expect(cachedRequest.headers['if-modified-since']).toBe(undefined);
});
});
describe('BrowserContext({interceptNetwork})', function() {
it('should enable request interception', async({newPage, httpsServer}) => {
const page = await newPage({ ignoreHTTPSErrors: true, interceptNetwork: true });
page.on('request', request => request.abort());
let error;
await page.goto(httpsServer.EMPTY_PAGE).catch(e => error = e);
expect(error).toBeTruthy();
});
});
}; };

View file

@ -224,7 +224,7 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROMI
}); });
describe('Chromium-Specific Page Tests', function() { describe('Chromium-Specific Page Tests', function() {
it('BrowserContext.setRequestInterception should work with intervention headers', async({context, server, page}) => { it('Page.setRequestInterception should work with intervention headers', async({server, page}) => {
server.setRoute('/intervention', (req, res) => res.end(` server.setRoute('/intervention', (req, res) => res.end(`
<script> <script>
document.write('<script src="${server.CROSS_PROCESS_PREFIX}/intervention.js">' + '</scr' + 'ipt>'); document.write('<script src="${server.CROSS_PROCESS_PREFIX}/intervention.js">' + '</scr' + 'ipt>');
@ -237,7 +237,7 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROMI
res.end('console.log(1);'); res.end('console.log(1);');
}); });
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => request.continue()); page.on('request', request => request.continue());
await page.goto(server.PREFIX + '/intervention'); await page.goto(server.PREFIX + '/intervention');
// Check for feature URL substring rather than https://www.chromestatus.com to // Check for feature URL substring rather than https://www.chromestatus.com to

View file

@ -44,7 +44,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
expect(page.frames().length).toBe(2); expect(page.frames().length).toBe(2);
}); });
it('should load oopif iframes with subresources and request interception', async function({browser, page, server, context}) { it('should load oopif iframes with subresources and request interception', async function({browser, page, server, context}) {
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => request.continue()); page.on('request', request => request.continue());
await page.goto(server.PREFIX + '/dynamic-oopif.html'); await page.goto(server.PREFIX + '/dynamic-oopif.html');
expect(oopifs(browser).length).toBe(1); expect(oopifs(browser).length).toBe(1);

View file

@ -24,9 +24,9 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
const {it, fit, xit, dit} = testRunner; const {it, fit, xit, dit} = testRunner;
const {beforeAll, beforeEach, afterAll, afterEach} = testRunner; const {beforeAll, beforeEach, afterAll, afterEach} = testRunner;
describe('BrowserContext.setRequestInterception', function() { describe('Page.setRequestInterception', function() {
it('should intercept', async({context, page, server}) => { it('should intercept', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
expect(request.url()).toContain('empty.html'); expect(request.url()).toContain('empty.html');
expect(request.headers()['user-agent']).toBeTruthy(); expect(request.headers()['user-agent']).toBeTruthy();
@ -41,10 +41,10 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
const response = await page.goto(server.EMPTY_PAGE); const response = await page.goto(server.EMPTY_PAGE);
expect(response.ok()).toBe(true); expect(response.ok()).toBe(true);
}); });
it('should work when POST is redirected with 302', async({context, page, server}) => { it('should work when POST is redirected with 302', async({page, server}) => {
server.setRedirect('/rredirect', '/empty.html'); server.setRedirect('/rredirect', '/empty.html');
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => request.continue()); page.on('request', request => request.continue());
await page.setContent(` await page.setContent(`
<form action='/rredirect' method='post'> <form action='/rredirect' method='post'>
@ -57,9 +57,9 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
]); ]);
}); });
// @see https://github.com/GoogleChrome/puppeteer/issues/3973 // @see https://github.com/GoogleChrome/puppeteer/issues/3973
it('should work when header manipulation headers with redirect', async({context, page, server}) => { it('should work when header manipulation headers with redirect', async({page, server}) => {
server.setRedirect('/rrredirect', '/empty.html'); server.setRedirect('/rrredirect', '/empty.html');
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
const headers = Object.assign({}, request.headers(), { const headers = Object.assign({}, request.headers(), {
foo: 'bar' foo: 'bar'
@ -69,8 +69,8 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
await page.goto(server.PREFIX + '/rrredirect'); await page.goto(server.PREFIX + '/rrredirect');
}); });
// @see https://github.com/GoogleChrome/puppeteer/issues/4743 // @see https://github.com/GoogleChrome/puppeteer/issues/4743
it('should be able to remove headers', async({context, page, server}) => { it('should be able to remove headers', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
const headers = Object.assign({}, request.headers(), { const headers = Object.assign({}, request.headers(), {
foo: 'bar', foo: 'bar',
@ -86,8 +86,8 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
expect(serverRequest.headers.origin).toBe(undefined); expect(serverRequest.headers.origin).toBe(undefined);
}); });
it('should contain referer header', async({context, page, server}) => { it('should contain referer header', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
const requests = []; const requests = [];
page.on('request', request => { page.on('request', request => {
requests.push(request); requests.push(request);
@ -103,23 +103,23 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
await context.setCookies([{ url: server.EMPTY_PAGE, name: 'foo', value: 'bar'}]); await context.setCookies([{ url: server.EMPTY_PAGE, name: 'foo', value: 'bar'}]);
// Setup request interception. // Setup request interception.
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => request.continue()); page.on('request', request => request.continue());
const response = await page.reload(); const response = await page.reload();
expect(response.status()).toBe(200); expect(response.status()).toBe(200);
}); });
it('should stop intercepting', async({context, page, server}) => { it('should stop intercepting', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.once('request', request => request.continue()); page.once('request', request => request.continue());
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
await context.setRequestInterception(false); await page.setRequestInterception(false);
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
}); });
it('should show custom HTTP headers', async({context, page, server}) => { it('should show custom HTTP headers', async({page, server}) => {
await page.setExtraHTTPHeaders({ await page.setExtraHTTPHeaders({
foo: 'bar' foo: 'bar'
}); });
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
expect(request.headers()['foo']).toBe('bar'); expect(request.headers()['foo']).toBe('bar');
request.continue(); request.continue();
@ -128,10 +128,10 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
expect(response.ok()).toBe(true); expect(response.ok()).toBe(true);
}); });
// @see https://github.com/GoogleChrome/puppeteer/issues/4337 // @see https://github.com/GoogleChrome/puppeteer/issues/4337
it('should work with redirect inside sync XHR', async({context, page, server}) => { it('should work with redirect inside sync XHR', async({page, server}) => {
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
server.setRedirect('/logo.png', '/pptr.png'); server.setRedirect('/logo.png', '/pptr.png');
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => request.continue()); page.on('request', request => request.continue());
const status = await page.evaluate(async() => { const status = await page.evaluate(async() => {
const request = new XMLHttpRequest(); const request = new XMLHttpRequest();
@ -141,9 +141,9 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
}); });
expect(status).toBe(200); expect(status).toBe(200);
}); });
it('should work with custom referer headers', async({context, page, server}) => { it('should work with custom referer headers', async({page, server}) => {
await page.setExtraHTTPHeaders({ 'referer': server.EMPTY_PAGE }); await page.setExtraHTTPHeaders({ 'referer': server.EMPTY_PAGE });
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
expect(request.headers()['referer']).toBe(server.EMPTY_PAGE); expect(request.headers()['referer']).toBe(server.EMPTY_PAGE);
request.continue(); request.continue();
@ -151,8 +151,8 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
const response = await page.goto(server.EMPTY_PAGE); const response = await page.goto(server.EMPTY_PAGE);
expect(response.ok()).toBe(true); expect(response.ok()).toBe(true);
}); });
it('should be abortable', async({context, page, server}) => { it('should be abortable', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
if (request.url().endsWith('.css')) if (request.url().endsWith('.css'))
request.abort(); request.abort();
@ -166,8 +166,8 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
expect(response.request().failure()).toBe(null); expect(response.request().failure()).toBe(null);
expect(failedRequests).toBe(1); expect(failedRequests).toBe(1);
}); });
it('should be abortable with custom error codes', async({context, page, server}) => { it('should be abortable with custom error codes', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
request.abort('internetdisconnected'); request.abort('internetdisconnected');
}); });
@ -182,11 +182,11 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
else else
expect(failedRequest.failure().errorText).toBe('net::ERR_INTERNET_DISCONNECTED'); expect(failedRequest.failure().errorText).toBe('net::ERR_INTERNET_DISCONNECTED');
}); });
it('should send referer', async({context, page, server}) => { it('should send referer', async({page, server}) => {
await page.setExtraHTTPHeaders({ await page.setExtraHTTPHeaders({
referer: 'http://google.com/' referer: 'http://google.com/'
}); });
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => request.continue()); page.on('request', request => request.continue());
const [request] = await Promise.all([ const [request] = await Promise.all([
server.waitForRequest('/grid.html'), server.waitForRequest('/grid.html'),
@ -194,8 +194,8 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
]); ]);
expect(request.headers['referer']).toBe('http://google.com/'); expect(request.headers['referer']).toBe('http://google.com/');
}); });
it('should fail navigation when aborting main resource', async({context, page, server}) => { it('should fail navigation when aborting main resource', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => request.abort()); page.on('request', request => request.abort());
let error = null; let error = null;
await page.goto(server.EMPTY_PAGE).catch(e => error = e); await page.goto(server.EMPTY_PAGE).catch(e => error = e);
@ -207,8 +207,8 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
else else
expect(error.message).toContain('net::ERR_FAILED'); expect(error.message).toContain('net::ERR_FAILED');
}); });
it('should work with redirects', async({context, page, server}) => { it('should work with redirects', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
const requests = []; const requests = [];
page.on('request', request => { page.on('request', request => {
request.continue(); request.continue();
@ -234,8 +234,8 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
expect(request.redirectChain().indexOf(request)).toBe(i); expect(request.redirectChain().indexOf(request)).toBe(i);
} }
}); });
it('should work with redirects for subresources', async({context, page, server}) => { it('should work with redirects for subresources', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
const requests = []; const requests = [];
page.on('request', request => { page.on('request', request => {
request.continue(); request.continue();
@ -258,11 +258,11 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
expect(redirectChain[0].url()).toContain('/one-style.css'); expect(redirectChain[0].url()).toContain('/one-style.css');
expect(redirectChain[2].url()).toContain('/three-style.css'); expect(redirectChain[2].url()).toContain('/three-style.css');
}); });
it('should work with equal requests', async({context, page, server}) => { it('should work with equal requests', async({page, server}) => {
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
let responseCount = 1; let responseCount = 1;
server.setRoute('/zzz', (req, res) => res.end((responseCount++) * 11 + '')); server.setRoute('/zzz', (req, res) => res.end((responseCount++) * 11 + ''));
await context.setRequestInterception(true); await page.setRequestInterception(true);
let spinner = false; let spinner = false;
// Cancel 2nd request. // Cancel 2nd request.
@ -277,8 +277,8 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
])); ]));
expect(results).toEqual(['11', 'FAILED', '22']); expect(results).toEqual(['11', 'FAILED', '22']);
}); });
it('should navigate to dataURL and not fire dataURL requests', async({context, page, server}) => { it('should navigate to dataURL and not fire dataURL requests', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
const requests = []; const requests = [];
page.on('request', request => { page.on('request', request => {
requests.push(request); requests.push(request);
@ -289,9 +289,9 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
expect(response).toBe(null); expect(response).toBe(null);
expect(requests.length).toBe(0); expect(requests.length).toBe(0);
}); });
it('should be able to fetch dataURL and not fire dataURL requests', async({context, page, server}) => { it('should be able to fetch dataURL and not fire dataURL requests', async({page, server}) => {
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
await context.setRequestInterception(true); await page.setRequestInterception(true);
const requests = []; const requests = [];
page.on('request', request => { page.on('request', request => {
requests.push(request); requests.push(request);
@ -302,8 +302,8 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
expect(text).toBe('<div>yo</div>'); expect(text).toBe('<div>yo</div>');
expect(requests.length).toBe(0); expect(requests.length).toBe(0);
}); });
it.skip(FFOX)('should navigate to URL with hash and and fire requests without hash', async({context, page, server}) => { it.skip(FFOX)('should navigate to URL with hash and and fire requests without hash', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
const requests = []; const requests = [];
page.on('request', request => { page.on('request', request => {
requests.push(request); requests.push(request);
@ -315,25 +315,25 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
expect(requests.length).toBe(1); expect(requests.length).toBe(1);
expect(requests[0].url()).toBe(server.EMPTY_PAGE); expect(requests[0].url()).toBe(server.EMPTY_PAGE);
}); });
it('should work with encoded server', async({context, page, server}) => { it('should work with encoded server', async({page, server}) => {
// The requestWillBeSent will report encoded URL, whereas interception will // The requestWillBeSent will report encoded URL, whereas interception will
// report URL as-is. @see crbug.com/759388 // report URL as-is. @see crbug.com/759388
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => request.continue()); page.on('request', request => request.continue());
const response = await page.goto(server.PREFIX + '/some nonexisting page'); const response = await page.goto(server.PREFIX + '/some nonexisting page');
expect(response.status()).toBe(404); expect(response.status()).toBe(404);
}); });
it('should work with badly encoded server', async({context, page, server}) => { it('should work with badly encoded server', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
server.setRoute('/malformed?rnd=%911', (req, res) => res.end()); server.setRoute('/malformed?rnd=%911', (req, res) => res.end());
page.on('request', request => request.continue()); page.on('request', request => request.continue());
const response = await page.goto(server.PREFIX + '/malformed?rnd=%911'); const response = await page.goto(server.PREFIX + '/malformed?rnd=%911');
expect(response.status()).toBe(200); expect(response.status()).toBe(200);
}); });
it('should work with encoded server - 2', async({context, page, server}) => { it('should work with encoded server - 2', async({page, server}) => {
// The requestWillBeSent will report URL as-is, whereas interception will // The requestWillBeSent will report URL as-is, whereas interception will
// report encoded URL for stylesheet. @see crbug.com/759388 // report encoded URL for stylesheet. @see crbug.com/759388
await context.setRequestInterception(true); await page.setRequestInterception(true);
const requests = []; const requests = [];
page.on('request', request => { page.on('request', request => {
request.continue(); request.continue();
@ -344,9 +344,9 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
expect(requests.length).toBe(1); expect(requests.length).toBe(1);
expect(requests[0].response().status()).toBe(404); expect(requests[0].response().status()).toBe(404);
}); });
it('should not throw "Invalid Interception Id" if the request was cancelled', async({context, page, server}) => { it('should not throw "Invalid Interception Id" if the request was cancelled', async({page, server}) => {
await page.setContent('<iframe></iframe>'); await page.setContent('<iframe></iframe>');
await context.setRequestInterception(true); await page.setRequestInterception(true);
let request = null; let request = null;
page.on('request', async r => request = r); page.on('request', async r => request = r);
page.$eval('iframe', (frame, url) => frame.src = url, server.EMPTY_PAGE), page.$eval('iframe', (frame, url) => frame.src = url, server.EMPTY_PAGE),
@ -371,9 +371,9 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
expect(error.message).toContain('Request Interception is not enabled'); expect(error.message).toContain('Request Interception is not enabled');
}); });
it('should intercept main resource during cross-process navigation', async({context, page, server}) => { it('should intercept main resource during cross-process navigation', async({page, server}) => {
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
await context.setRequestInterception(true); await page.setRequestInterception(true);
let intercepted = false; let intercepted = false;
page.on('request', request => { page.on('request', request => {
if (request.url().includes(server.CROSS_PROCESS_PREFIX + '/empty.html')) if (request.url().includes(server.CROSS_PROCESS_PREFIX + '/empty.html'))
@ -384,8 +384,8 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
expect(response.ok()).toBe(true); expect(response.ok()).toBe(true);
expect(intercepted).toBe(true); expect(intercepted).toBe(true);
}); });
it('should not throw when continued after navigation', async({context, page, server}) => { it('should not throw when continued after navigation', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
if (request.url() !== server.PREFIX + '/one-style.css') if (request.url() !== server.PREFIX + '/one-style.css')
request.continue(); request.continue();
@ -399,8 +399,8 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
const notAnError = await request.continue().then(() => null).catch(e => e); const notAnError = await request.continue().then(() => null).catch(e => e);
expect(notAnError).toBe(null); expect(notAnError).toBe(null);
}); });
it('should not throw when continued after cross-process navigation', async({context, page, server}) => { it('should not throw when continued after cross-process navigation', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
if (request.url() !== server.PREFIX + '/one-style.css') if (request.url() !== server.PREFIX + '/one-style.css')
request.continue(); request.continue();
@ -417,13 +417,13 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
}); });
describe('Request.continue', function() { describe('Request.continue', function() {
it('should work', async({context, page, server}) => { it('should work', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => request.continue()); page.on('request', request => request.continue());
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
}); });
it('should amend HTTP headers', async({context, page, server}) => { it('should amend HTTP headers', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
const headers = Object.assign({}, request.headers()); const headers = Object.assign({}, request.headers());
headers['FOO'] = 'bar'; headers['FOO'] = 'bar';
@ -436,10 +436,10 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
]); ]);
expect(request.headers['foo']).toBe('bar'); expect(request.headers['foo']).toBe('bar');
}); });
it('should amend method', async({context, page, server}) => { it('should amend method', async({page, server}) => {
const sRequest = server.waitForRequest('/sleep.zzz'); const sRequest = server.waitForRequest('/sleep.zzz');
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
request.continue({ method: 'POST' }); request.continue({ method: 'POST' });
}); });
@ -450,18 +450,18 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
expect(request.method).toBe('POST'); expect(request.method).toBe('POST');
expect((await sRequest).method).toBe('POST'); expect((await sRequest).method).toBe('POST');
}); });
it('should amend method on main request', async({context, page, server}) => { it('should amend method on main request', async({page, server}) => {
const request = server.waitForRequest('/empty.html'); const request = server.waitForRequest('/empty.html');
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
request.continue({ method: 'POST' }); request.continue({ method: 'POST' });
}); });
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
expect((await request).method).toBe('POST'); expect((await request).method).toBe('POST');
}); });
it('should amend post data', async({context, page, server}) => { it('should amend post data', async({page, server}) => {
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
request.continue({ postData: 'doggo' }); request.continue({ postData: 'doggo' });
}); });
@ -474,8 +474,8 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
}); });
describe('Request.fulfill', function() { describe('Request.fulfill', function() {
it('should work', async({context, page, server}) => { it('should work', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
request.fulfill({ request.fulfill({
status: 201, status: 201,
@ -491,8 +491,8 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
expect(response.headers().foo).toBe('bar'); expect(response.headers().foo).toBe('bar');
expect(await page.evaluate(() => document.body.textContent)).toBe('Yo, page!'); expect(await page.evaluate(() => document.body.textContent)).toBe('Yo, page!');
}); });
it('should work with status code 422', async({context, page, server}) => { it('should work with status code 422', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
request.fulfill({ request.fulfill({
status: 422, status: 422,
@ -504,8 +504,8 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
expect(response.statusText()).toBe('Unprocessable Entity'); expect(response.statusText()).toBe('Unprocessable Entity');
expect(await page.evaluate(() => document.body.textContent)).toBe('Yo, page!'); expect(await page.evaluate(() => document.body.textContent)).toBe('Yo, page!');
}); });
it('should allow mocking binary responses', async({context, page, server}) => { it('should allow mocking binary responses', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
const imageBuffer = fs.readFileSync(path.join(__dirname, 'assets', 'pptr.png')); const imageBuffer = fs.readFileSync(path.join(__dirname, 'assets', 'pptr.png'));
request.fulfill({ request.fulfill({
@ -522,8 +522,8 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
const img = await page.$('img'); const img = await page.$('img');
expect(await img.screenshot()).toBeGolden('mock-binary-response.png'); expect(await img.screenshot()).toBeGolden('mock-binary-response.png');
}); });
it('should stringify intercepted request response headers', async({context, page, server}) => { it('should stringify intercepted request response headers', async({page, server}) => {
await context.setRequestInterception(true); await page.setRequestInterception(true);
page.on('request', request => { page.on('request', request => {
request.fulfill({ request.fulfill({
status: 200, status: 200,
@ -542,7 +542,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
}); });
describe('Page.authenticate', function() { describe('Page.authenticate', function() {
it('should work', async({context, page, server}) => { it('should work', async({page, server}) => {
server.setAuth('/empty.html', 'user', 'pass'); server.setAuth('/empty.html', 'user', 'pass');
let response = await page.goto(server.EMPTY_PAGE); let response = await page.goto(server.EMPTY_PAGE);
expect(response.status()).toBe(401); expect(response.status()).toBe(401);
@ -553,7 +553,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
response = await page.reload(); response = await page.reload();
expect(response.status()).toBe(200); expect(response.status()).toBe(200);
}); });
it('should fail if wrong credentials', async({context, page, server}) => { it('should fail if wrong credentials', async({page, server}) => {
// Use unique user/password since Chromium caches credentials per origin. // Use unique user/password since Chromium caches credentials per origin.
server.setAuth('/empty.html', 'user2', 'pass2'); server.setAuth('/empty.html', 'user2', 'pass2');
await page.authenticate({ await page.authenticate({
@ -563,7 +563,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
const response = await page.goto(server.EMPTY_PAGE); const response = await page.goto(server.EMPTY_PAGE);
expect(response.status()).toBe(401); expect(response.status()).toBe(401);
}); });
it('should allow disable authentication', async({context, page, server}) => { it('should allow disable authentication', async({page, server}) => {
// Use unique user/password since Chromium caches credentials per origin. // Use unique user/password since Chromium caches credentials per origin.
server.setAuth('/empty.html', 'user3', 'pass3'); server.setAuth('/empty.html', 'user3', 'pass3');
await page.authenticate({ await page.authenticate({
@ -580,41 +580,32 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
}); });
describe.skip(FFOX)('Interception.setOfflineMode', function() { describe.skip(FFOX)('Interception.setOfflineMode', function() {
it('should work', async({context, page, server}) => { it('should work', async({page, server}) => {
await context.setOfflineMode(true); await page.setOfflineMode(true);
let error = null; let error = null;
await page.goto(server.EMPTY_PAGE).catch(e => error = e); await page.goto(server.EMPTY_PAGE).catch(e => error = e);
expect(error).toBeTruthy(); expect(error).toBeTruthy();
await context.setOfflineMode(false); await page.setOfflineMode(false);
const response = await page.goto(server.EMPTY_PAGE); const response = await page.goto(server.EMPTY_PAGE);
expect(response.status()).toBe(200); expect(response.status()).toBe(200);
}); });
it('should emulate navigator.onLine', async({context, page}) => { it('should emulate navigator.onLine', async({page, server}) => {
expect(await page.evaluate(() => window.navigator.onLine)).toBe(true); expect(await page.evaluate(() => window.navigator.onLine)).toBe(true);
await context.setOfflineMode(true); await page.setOfflineMode(true);
expect(await page.evaluate(() => window.navigator.onLine)).toBe(false); expect(await page.evaluate(() => window.navigator.onLine)).toBe(false);
await context.setOfflineMode(false); await page.setOfflineMode(false);
expect(await page.evaluate(() => window.navigator.onLine)).toBe(true); expect(await page.evaluate(() => window.navigator.onLine)).toBe(true);
}); });
it('should propagate to new pages', async({context, page, server}) => {
await context.setOfflineMode(true);
expect(await page.evaluate(() => window.navigator.onLine)).toBe(false);
const newPage = await context.newPage();
expect(await newPage.evaluate(() => window.navigator.onLine)).toBe(false);
let error = null;
await newPage.goto(server.EMPTY_PAGE).catch(e => error = e);
expect(error).toBeTruthy();
});
}); });
describe('Interception vs isNavigationRequest', () => { describe('Interception vs isNavigationRequest', () => {
it('should work with request interception', async({context, page, server}) => { it('should work with request interception', async({page, server}) => {
const requests = new Map(); const requests = new Map();
page.on('request', request => { page.on('request', request => {
requests.set(request.url().split('/').pop(), request); requests.set(request.url().split('/').pop(), request);
request.continue(); request.continue();
}); });
await context.setRequestInterception(true); await page.setRequestInterception(true);
server.setRedirect('/rrredirect', '/frames/one-frame.html'); server.setRedirect('/rrredirect', '/frames/one-frame.html');
await page.goto(server.PREFIX + '/rrredirect'); await page.goto(server.PREFIX + '/rrredirect');
expect(requests.get('rrredirect').isNavigationRequest()).toBe(true); expect(requests.get('rrredirect').isNavigationRequest()).toBe(true);
@ -625,11 +616,11 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
}); });
}); });
describe('Context.setCacheEnabled', function() { describe('Page.setCacheEnabled', function() {
it('should stay disabled when toggling request interception on/off', async({context, page, server}) => { it('should stay disabled when toggling request interception on/off', async({page, server}) => {
await context.setCacheEnabled(false); await page.setCacheEnabled(false);
await context.setRequestInterception(true); await page.setRequestInterception(true);
await context.setRequestInterception(false); await page.setRequestInterception(false);
await page.goto(server.PREFIX + '/cached/one-style.html'); await page.goto(server.PREFIX + '/cached/one-style.html');
const [nonCachedRequest] = await Promise.all([ const [nonCachedRequest] = await Promise.all([
@ -643,6 +634,8 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
describe('ignoreHTTPSErrors', function() { describe('ignoreHTTPSErrors', function() {
it('should work with request interception', async({newPage, httpsServer}) => { it('should work with request interception', async({newPage, httpsServer}) => {
const page = await newPage({ ignoreHTTPSErrors: true, interceptNetwork: true }); const page = await newPage({ ignoreHTTPSErrors: true, interceptNetwork: true });
await page.setRequestInterception(true);
page.on('request', request => request.continue()); page.on('request', request => request.continue());
const response = await page.goto(httpsServer.EMPTY_PAGE); const response = await page.goto(httpsServer.EMPTY_PAGE);
expect(response.status()).toBe(200); expect(response.status()).toBe(200);

View file

@ -831,9 +831,9 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROMI
const error = await navigationPromise; const error = await navigationPromise;
expect(error.message).toContain('frame was detached'); expect(error.message).toContain('frame was detached');
}); });
it('should return matching responses', async({context, page, server}) => { it('should return matching responses', async({page, server}) => {
// Disable cache: otherwise, chromium will cache similar requests. // Disable cache: otherwise, chromium will cache similar requests.
await context.setCacheEnabled(false); await page.setCacheEnabled(false);
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
// Attach three frames. // Attach three frames.
const frames = [ const frames = [

View file

@ -779,8 +779,8 @@ module.exports.describe = function({testRunner, expect, headless, playwright, FF
}); });
}); });
describe('Context.setCacheEnabled', function() { describe('Page.setCacheEnabled', function() {
it('should enable or disable the cache based on the state passed', async({context, page, server}) => { it('should enable or disable the cache based on the state passed', async({page, server}) => {
await page.goto(server.PREFIX + '/cached/one-style.html'); await page.goto(server.PREFIX + '/cached/one-style.html');
// WebKit does r.setCachePolicy(ResourceRequestCachePolicy::ReloadIgnoringCacheData); // WebKit does r.setCachePolicy(ResourceRequestCachePolicy::ReloadIgnoringCacheData);
// when navigating to the same url, load empty.html to avoid that. // when navigating to the same url, load empty.html to avoid that.
@ -792,7 +792,7 @@ module.exports.describe = function({testRunner, expect, headless, playwright, FF
// Rely on "if-modified-since" caching in our test server. // Rely on "if-modified-since" caching in our test server.
expect(cachedRequest.headers['if-modified-since']).not.toBe(undefined); expect(cachedRequest.headers['if-modified-since']).not.toBe(undefined);
await context.setCacheEnabled(false); await page.setCacheEnabled(false);
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
const [nonCachedRequest] = await Promise.all([ const [nonCachedRequest] = await Promise.all([
server.waitForRequest('/cached/one-style.html'), server.waitForRequest('/cached/one-style.html'),

View file

@ -19,8 +19,8 @@ module.exports.describe = function ({ testRunner, expect }) {
const {it, fit, xit, dit} = testRunner; const {it, fit, xit, dit} = testRunner;
const {beforeAll, beforeEach, afterAll, afterEach} = testRunner; const {beforeAll, beforeEach, afterAll, afterEach} = testRunner;
describe('Provisional page', function() { describe('provisional page', function() {
it('should receive extraHttpHeaders', async({page, server}) => { it('extraHttpHeaders should be pushed to provisional page', async({page, server}) => {
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
const pagePath = '/one-style.html'; const pagePath = '/one-style.html';
server.setRoute(pagePath, async (req, res) => { server.setRoute(pagePath, async (req, res) => {
@ -35,14 +35,14 @@ module.exports.describe = function ({ testRunner, expect }) {
expect(htmlReq.headers['foo']).toBe(undefined); expect(htmlReq.headers['foo']).toBe(undefined);
expect(cssReq.headers['foo']).toBe('bar'); expect(cssReq.headers['foo']).toBe('bar');
}); });
it('should continue loading when interception gets disabled', async({context, page, server}) => { it('should continue load when interception gets disabled during provisional load', async({page, server}) => {
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
await context.setRequestInterception(true); await page.setRequestInterception(true);
expect(await page.evaluate(() => navigator.onLine)).toBe(true); expect(await page.evaluate(() => navigator.onLine)).toBe(true);
let intercepted = null; let intercepted = null;
const order = []; const order = [];
page.on('request', request => { page.on('request', request => {
intercepted = context.setRequestInterception(false).then(() => order.push('setRequestInterception')); intercepted = page.setRequestInterception(false).then(() => order.push('setRequestInterception'));
}); });
const response = await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html').then(response => { const response = await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html').then(response => {
order.push('goto'); order.push('goto');