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`.
- `isMobile` <[boolean]> Whether the `meta viewport` tag is taken into account. Defaults to `false`.
- `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.
- `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]>
@ -264,12 +261,9 @@ await context.close();
- [browserContext.cookies([...urls])](#browsercontextcookiesurls)
- [browserContext.newPage(url)](#browsercontextnewpageurl)
- [browserContext.pages()](#browsercontextpages)
- [browserContext.setCacheEnabled([enabled])](#browsercontextsetcacheenabledenabled)
- [browserContext.setCookies(cookies)](#browsercontextsetcookiescookies)
- [browserContext.setGeolocation(geolocation)](#browsercontextsetgeolocationgeolocation)
- [browserContext.setOfflineMode(enabled)](#browsercontextsetofflinemodeenabled)
- [browserContext.setPermissions(origin, permissions[])](#browsercontextsetpermissionsorigin-permissions)
- [browserContext.setRequestInterception(enabled)](#browsercontextsetrequestinterceptionenabled)
<!-- GEN:stop -->
#### 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.
#### 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)
- `cookies` <[Array]<[Object]>>
- `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.
#### browserContext.setOfflineMode(enabled)
- `enabled` <[boolean]> When `true`, enables offline mode for the context.
- returns: <[Promise]>
#### browserContext.setPermissions(origin, permissions[])
- `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:
@ -396,32 +380,6 @@ const context = browser.defaultContext();
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
* extends: [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter)
@ -513,10 +471,13 @@ page.removeListener('request', logRequest);
- [page.reload([options])](#pagereloadoptions)
- [page.screenshot([options])](#pagescreenshotoptions)
- [page.select(selector, value, options)](#pageselectselector-value-options)
- [page.setCacheEnabled([enabled])](#pagesetcacheenabledenabled)
- [page.setContent(html[, options])](#pagesetcontenthtml-options)
- [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout)
- [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout)
- [page.setExtraHTTPHeaders(headers)](#pagesetextrahttpheadersheaders)
- [page.setOfflineMode(enabled)](#pagesetofflinemodeenabled)
- [page.setRequestInterception(enabled)](#pagesetrequestinterceptionenabled)
- [page.setViewport(viewport)](#pagesetviewportviewport)
- [page.title()](#pagetitle)
- [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)
#### 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])
- `html` <[string]> HTML markup to assign to the page.
- `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.
#### 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)
- `viewport` <[Object]>
- `width` <[number]> page width in pixels. **required**

View File

@ -42,9 +42,6 @@ export type BrowserContextOptions = {
javaScriptEnabled?: boolean,
bypassCSP?: boolean,
userAgent?: string,
cacheEnabled?: boolean;
interceptNetwork?: boolean;
offlineMode?: boolean;
timezoneId?: string,
geolocation?: types.Geolocation,
permissions?: { [key: string]: string[] };
@ -115,27 +112,6 @@ export class BrowserContext {
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() {
if (this._closed)
return;

View File

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

View File

@ -77,6 +77,9 @@ type PageState = {
mediaType: types.MediaType | null;
colorScheme: types.ColorScheme | null;
extraHTTPHeaders: network.Headers | null;
cacheEnabled: boolean | null;
interceptNetwork: boolean | null;
offlineMode: boolean | null;
credentials: types.Credentials | null;
hasTouch: boolean | null;
};
@ -120,6 +123,9 @@ export class Page extends platform.EventEmitter {
mediaType: null,
colorScheme: null,
extraHTTPHeaders: null,
cacheEnabled: null,
interceptNetwork: null,
offlineMode: null,
credentials: null,
hasTouch: null,
};
@ -397,6 +403,27 @@ export class Page extends platform.EventEmitter {
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) {
this._state.credentials = credentials;
await this._delegate.authenticate(credentials);

View File

@ -121,13 +121,14 @@ export class WKPage implements PageDelegate {
this._workers.initializeSession(session)
];
const contextOptions = this._page.browserContext()._options;
if (contextOptions.interceptNetwork)
if (this._page._state.interceptNetwork)
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 }));
if (contextOptions.cacheEnabled === false)
if (this._page._state.cacheEnabled === false)
promises.push(session.send('Network.setResourceCachingDisabled', { disabled: true }));
const contextOptions = this._page.browserContext()._options;
if (contextOptions.userAgent)
promises.push(session.send('Page.overrideUserAgent', { value: contextOptions.userAgent }));
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
const isNavigationRequest = event.type === 'Document';
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._page._frameManager.requestStarted(request.request);
}

View File

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

View File

@ -831,9 +831,9 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROMI
const error = await navigationPromise;
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.
await context.setCacheEnabled(false);
await page.setCacheEnabled(false);
await page.goto(server.EMPTY_PAGE);
// Attach three frames.
const frames = [

View File

@ -779,8 +779,8 @@ module.exports.describe = function({testRunner, expect, headless, playwright, FF
});
});
describe('Context.setCacheEnabled', function() {
it('should enable or disable the cache based on the state passed', async({context, page, server}) => {
describe('Page.setCacheEnabled', function() {
it('should enable or disable the cache based on the state passed', async({page, server}) => {
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.
@ -792,7 +792,7 @@ module.exports.describe = function({testRunner, expect, headless, playwright, FF
// Rely on "if-modified-since" caching in our test server.
expect(cachedRequest.headers['if-modified-since']).not.toBe(undefined);
await context.setCacheEnabled(false);
await page.setCacheEnabled(false);
await page.goto(server.EMPTY_PAGE);
const [nonCachedRequest] = await Promise.all([
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 {beforeAll, beforeEach, afterAll, afterEach} = testRunner;
describe('Provisional page', function() {
it('should receive extraHttpHeaders', async({page, server}) => {
describe('provisional page', function() {
it('extraHttpHeaders should be pushed to provisional page', async({page, server}) => {
await page.goto(server.EMPTY_PAGE);
const pagePath = '/one-style.html';
server.setRoute(pagePath, async (req, res) => {
@ -35,14 +35,14 @@ module.exports.describe = function ({ testRunner, expect }) {
expect(htmlReq.headers['foo']).toBe(undefined);
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 context.setRequestInterception(true);
await page.setRequestInterception(true);
expect(await page.evaluate(() => navigator.onLine)).toBe(true);
let intercepted = null;
const order = [];
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 => {
order.push('goto');