feat: add page.emulateNetworkConditions (#6759)
This commit is contained in:
parent
ebd087a316
commit
5ea76e9333
45
docs/api.md
45
docs/api.md
@ -42,6 +42,7 @@
|
||||
* [puppeteer.errors](#puppeteererrors)
|
||||
* [puppeteer.executablePath()](#puppeteerexecutablepath)
|
||||
* [puppeteer.launch([options])](#puppeteerlaunchoptions)
|
||||
* [puppeteer.networkConditions](#puppeteernetworkconditions)
|
||||
* [puppeteer.product](#puppeteerproduct)
|
||||
* [puppeteer.registerCustomQueryHandler(name, queryHandler)](#puppeteerregistercustomqueryhandlername-queryhandler)
|
||||
* [puppeteer.unregisterCustomQueryHandler(name)](#puppeteerunregistercustomqueryhandlername)
|
||||
@ -128,6 +129,7 @@
|
||||
* [page.emulateIdleState(overrides)](#pageemulateidlestateoverrides)
|
||||
* [page.emulateMediaFeatures(features)](#pageemulatemediafeaturesfeatures)
|
||||
* [page.emulateMediaType(type)](#pageemulatemediatypetype)
|
||||
* [page.emulateNetworkConditions(networkConditions)](#pageemulatenetworkconditionsnetworkconditions)
|
||||
* [page.emulateTimezone(timezoneId)](#pageemulatetimezonetimezoneid)
|
||||
* [page.emulateVisionDeficiency(type)](#pageemulatevisiondeficiencytype)
|
||||
* [page.evaluate(pageFunction[, ...args])](#pageevaluatepagefunction-args)
|
||||
@ -610,6 +612,26 @@ const browser = await puppeteer.launch({
|
||||
>
|
||||
> See [`this article`](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/) for a description of the differences between Chromium and Chrome. [`This article`](https://chromium.googlesource.com/chromium/src/+/lkgr/docs/chromium_browser_vs_google_chrome.md) describes some differences for Linux users.
|
||||
|
||||
#### puppeteer.networkConditions
|
||||
- returns: <[Object]>
|
||||
|
||||
Returns a list of network conditions to be used with [`page.emulateNetworkConditions(networkConditions)`](#pageemulatenetworkconditionsnetworkconditions). Actual list of
|
||||
conditions can be found in [`src/common/NetworkConditions.ts`](https://github.com/puppeteer/puppeteer/blob/main/src/common/NetworkConditions.ts).
|
||||
|
||||
```js
|
||||
const puppeteer = require('puppeteer');
|
||||
const slow3G = puppeteer.networkConditions['Slow 3G'];
|
||||
|
||||
(async () => {
|
||||
const browser = await puppeteer.launch();
|
||||
const page = await browser.newPage();
|
||||
await page.emulateNetworkConditions(slow3G);
|
||||
await page.goto('https://www.google.com');
|
||||
// other actions...
|
||||
await browser.close();
|
||||
})();
|
||||
```
|
||||
|
||||
#### puppeteer.product
|
||||
- returns: <[string]> returns the name of the browser that is under automation (`"chrome"` or `"firefox"`)
|
||||
|
||||
@ -1441,6 +1463,29 @@ await page.evaluate(() => matchMedia('print').matches);
|
||||
// → false
|
||||
```
|
||||
|
||||
#### page.emulateNetworkConditions(networkConditions)
|
||||
- `networkConditions` <?[Object]> Passing `null` disables network condition emulation.
|
||||
- `download` <[number]> Download speed (bytes/s), `-1` to disable
|
||||
- `upload` <[number]> Upload speed (bytes/s), `-1` to disable
|
||||
- `latency` <[number]> Latency (ms), `0` to disable
|
||||
- returns: <[Promise]>
|
||||
|
||||
> **NOTE** This does not affect WebSockets and WebRTC PeerConnections (see https://crbug.com/563644)
|
||||
|
||||
```js
|
||||
const puppeteer = require('puppeteer');
|
||||
const slow3G = puppeteer.networkConditions['Slow 3G'];
|
||||
|
||||
(async () => {
|
||||
const browser = await puppeteer.launch();
|
||||
const page = await browser.newPage();
|
||||
await page.emulateNetworkConditions(slow3G);
|
||||
await page.goto('https://www.google.com');
|
||||
// other actions...
|
||||
await browser.close();
|
||||
})();
|
||||
```
|
||||
|
||||
#### page.emulateTimezone(timezoneId)
|
||||
- `timezoneId` <?[string]> Changes the timezone of the page. See [ICU’s `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. Passing `null` disables timezone emulation.
|
||||
- returns: <[Promise]>
|
||||
|
32
src/common/NetworkConditions.ts
Normal file
32
src/common/NetworkConditions.ts
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright 2021 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { NetworkConditions } from './NetworkManager.js';
|
||||
|
||||
export type PredefinedNetworkConditions = { [name: string]: NetworkConditions };
|
||||
|
||||
export const networkConditions: PredefinedNetworkConditions = {
|
||||
'Slow 3G': {
|
||||
download: ((500 * 1000) / 8) * 0.8,
|
||||
upload: ((500 * 1000) / 8) * 0.8,
|
||||
latency: 400 * 5,
|
||||
},
|
||||
'Fast 3G': {
|
||||
download: ((1.6 * 1000 * 1000) / 8) * 0.9,
|
||||
upload: ((750 * 1000) / 8) * 0.9,
|
||||
latency: 150 * 3.75,
|
||||
},
|
||||
};
|
@ -30,6 +30,22 @@ export interface Credentials {
|
||||
password: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface NetworkConditions {
|
||||
// Download speed (bytes/s)
|
||||
download: number;
|
||||
// Upload speed (bytes/s)
|
||||
upload: number;
|
||||
// Latency (ms)
|
||||
latency: number;
|
||||
}
|
||||
|
||||
export interface InternalNetworkConditions extends NetworkConditions {
|
||||
offline: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* We use symbols to prevent any external parties listening to these events.
|
||||
* They are internal to Puppeteer.
|
||||
@ -56,13 +72,18 @@ export class NetworkManager extends EventEmitter {
|
||||
Protocol.Network.RequestWillBeSentEvent
|
||||
>();
|
||||
_extraHTTPHeaders: Record<string, string> = {};
|
||||
_offline = false;
|
||||
_credentials?: Credentials = null;
|
||||
_attemptedAuthentications = new Set<string>();
|
||||
_userRequestInterceptionEnabled = false;
|
||||
_protocolRequestInterceptionEnabled = false;
|
||||
_userCacheDisabled = false;
|
||||
_requestIdToInterceptionId = new Map<string, string>();
|
||||
_emulatedNetworkConditions: InternalNetworkConditions = {
|
||||
offline: false,
|
||||
upload: -1,
|
||||
download: -1,
|
||||
latency: 0,
|
||||
};
|
||||
|
||||
constructor(
|
||||
client: CDPSession,
|
||||
@ -130,14 +151,32 @@ export class NetworkManager extends EventEmitter {
|
||||
}
|
||||
|
||||
async setOfflineMode(value: boolean): Promise<void> {
|
||||
if (this._offline === value) return;
|
||||
this._offline = value;
|
||||
this._emulatedNetworkConditions.offline = value;
|
||||
await this._updateNetworkConditions();
|
||||
}
|
||||
|
||||
async emulateNetworkConditions(
|
||||
networkConditions: NetworkConditions | null
|
||||
): Promise<void> {
|
||||
this._emulatedNetworkConditions.upload = networkConditions
|
||||
? networkConditions.upload
|
||||
: -1;
|
||||
this._emulatedNetworkConditions.download = networkConditions
|
||||
? networkConditions.download
|
||||
: -1;
|
||||
this._emulatedNetworkConditions.latency = networkConditions
|
||||
? networkConditions.latency
|
||||
: 0;
|
||||
|
||||
await this._updateNetworkConditions();
|
||||
}
|
||||
|
||||
async _updateNetworkConditions(): Promise<void> {
|
||||
await this._client.send('Network.emulateNetworkConditions', {
|
||||
offline: this._offline,
|
||||
// values of 0 remove any active throttling. crbug.com/456324#c9
|
||||
latency: 0,
|
||||
downloadThroughput: -1,
|
||||
uploadThroughput: -1,
|
||||
offline: this._emulatedNetworkConditions.offline,
|
||||
latency: this._emulatedNetworkConditions.latency,
|
||||
uploadThroughput: this._emulatedNetworkConditions.upload,
|
||||
downloadThroughput: this._emulatedNetworkConditions.download,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,11 @@ import { Browser, BrowserContext } from './Browser.js';
|
||||
import { Target } from './Target.js';
|
||||
import { createJSHandle, JSHandle, ElementHandle } from './JSHandle.js';
|
||||
import { Viewport } from './PuppeteerViewport.js';
|
||||
import { Credentials, NetworkManagerEmittedEvents } from './NetworkManager.js';
|
||||
import {
|
||||
Credentials,
|
||||
NetworkConditions,
|
||||
NetworkManagerEmittedEvents,
|
||||
} from './NetworkManager.js';
|
||||
import { HTTPRequest } from './HTTPRequest.js';
|
||||
import { HTTPResponse } from './HTTPResponse.js';
|
||||
import { Accessibility } from './Accessibility.js';
|
||||
@ -693,6 +697,14 @@ export class Page extends EventEmitter {
|
||||
return this._frameManager.networkManager().setOfflineMode(enabled);
|
||||
}
|
||||
|
||||
emulateNetworkConditions(
|
||||
networkConditions: NetworkConditions | null
|
||||
): Promise<void> {
|
||||
return this._frameManager
|
||||
.networkManager()
|
||||
.emulateNetworkConditions(networkConditions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param timeout - Maximum navigation time in milliseconds.
|
||||
*/
|
||||
|
@ -26,6 +26,10 @@ import {
|
||||
} from './QueryHandler.js';
|
||||
import { Product } from './Product.js';
|
||||
import { connectToBrowser, BrowserOptions } from './BrowserConnector.js';
|
||||
import {
|
||||
PredefinedNetworkConditions,
|
||||
networkConditions,
|
||||
} from './NetworkConditions.js';
|
||||
|
||||
/**
|
||||
* Settings that are common to the Puppeteer class, regardless of enviroment.
|
||||
@ -125,6 +129,31 @@ export class Puppeteer {
|
||||
return puppeteerErrors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @remarks
|
||||
* Returns a list of network conditions to be used with `page.emulateNetworkConditions(networkConditions)`. Actual list of predefined conditions can be found in {@link https://github.com/puppeteer/puppeteer/blob/main/src/common/NetworkConditions.ts | src/common/NetworkConditions.ts}.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* ```js
|
||||
* const puppeteer = require('puppeteer');
|
||||
* const slow3G = puppeteer.networkConditions['Slow 3G'];
|
||||
*
|
||||
* (async () => {
|
||||
* const browser = await puppeteer.launch();
|
||||
* const page = await browser.newPage();
|
||||
* await page.emulateNetworkConditions(slow3G);
|
||||
* await page.goto('https://www.google.com');
|
||||
* // other actions...
|
||||
* await browser.close();
|
||||
* })();
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
get networkConditions(): PredefinedNetworkConditions {
|
||||
return networkConditions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a {@link CustomQueryHandler | custom query handler}. After
|
||||
* registration, the handler can be used everywhere where a selector is
|
||||
|
@ -388,6 +388,28 @@ describe('Page', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describeFailsFirefox('Page.emulateNetworkConditions', function () {
|
||||
it('should change navigator.connection.effectiveType', async () => {
|
||||
const { page, puppeteer } = getTestState();
|
||||
|
||||
const slow3G = puppeteer.networkConditions['Slow 3G'];
|
||||
const fast3G = puppeteer.networkConditions['Fast 3G'];
|
||||
|
||||
expect(
|
||||
await page.evaluate('window.navigator.connection.effectiveType')
|
||||
).toBe('4g');
|
||||
await page.emulateNetworkConditions(fast3G);
|
||||
expect(
|
||||
await page.evaluate('window.navigator.connection.effectiveType')
|
||||
).toBe('3g');
|
||||
await page.emulateNetworkConditions(slow3G);
|
||||
expect(
|
||||
await page.evaluate('window.navigator.connection.effectiveType')
|
||||
).toBe('2g');
|
||||
await page.emulateNetworkConditions(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ExecutionContext.queryObjects', function () {
|
||||
itFailsFirefox('should work', async () => {
|
||||
const { page } = getTestState();
|
||||
|
@ -576,6 +576,13 @@ function compareDocumentations(actual, expected) {
|
||||
expectedName: 'Viewport',
|
||||
},
|
||||
],
|
||||
[
|
||||
'Method Page.emulateNetworkConditions() networkConditions',
|
||||
{
|
||||
actualName: 'Object',
|
||||
expectedName: 'NetworkConditions',
|
||||
},
|
||||
],
|
||||
[
|
||||
'Method Page.setViewport() options.viewport',
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user