-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add device emulation to benchmark-web-vitals
#166
Changes from all commits
f67584f
042099f
c73d2d2
484025e
e46e83f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,13 +19,21 @@ | |
/** | ||
* External dependencies | ||
*/ | ||
import puppeteer, { Browser, PredefinedNetworkConditions } from 'puppeteer'; | ||
import puppeteer, { | ||
Browser, | ||
PredefinedNetworkConditions, | ||
KnownDevices, | ||
} from 'puppeteer'; | ||
import round from 'lodash-es/round.js'; | ||
|
||
/* eslint-disable jsdoc/valid-types */ | ||
/** @typedef {import("puppeteer").NetworkConditions} NetworkConditions */ | ||
/** @typedef {keyof typeof import("puppeteer").networkConditions} NetworkConditionName */ | ||
/** @typedef {keyof typeof PredefinedNetworkConditions} NetworkConditionName */ | ||
/** @typedef {import("puppeteer").Device} Device */ | ||
/** @typedef {keyof typeof KnownDevices} KnownDeviceName */ | ||
|
||
/* eslint-enable jsdoc/valid-types */ | ||
// TODO: deviceScaleFactor, isMobile, isLandscape, hasTouch. | ||
/** @typedef {{width: number, height: number}} ViewportDimensions */ | ||
|
||
/** | ||
|
@@ -97,10 +105,15 @@ export const options = [ | |
description: | ||
'Enable emulation of network conditions (may be either "Slow 3G" or "Fast 3G")', | ||
}, | ||
{ | ||
argname: '-e, --emulate-device <device>', | ||
description: | ||
'Enable a specific device by name, for example "Moto G4" or "iPad"', | ||
}, | ||
{ | ||
argname: '-w, --window-viewport <dimensions>', | ||
description: | ||
'Open page with the supplied viewport dimensions such as "mobile" (an alias for "412x823") or "desktop" (an alias for "1350x940"), defaults to "960x700"', | ||
'Open page with the supplied viewport dimensions such as "mobile" (an alias for "412x823") or "desktop" (an alias for "1350x940"), defaults to "960x700" if no specific device is being emulated', | ||
}, | ||
]; | ||
|
||
|
@@ -115,6 +128,7 @@ export const options = [ | |
* @property {boolean} showVariance - See above. | ||
* @property {?number} cpuThrottleFactor - See above. | ||
* @property {?NetworkConditions} networkConditions - See above. | ||
* @property {?Device} emulateDevice - See above. | ||
* @property {?ViewportDimensions} windowViewport - See above. | ||
*/ | ||
|
||
|
@@ -129,17 +143,18 @@ export const options = [ | |
*/ | ||
|
||
/** | ||
* @param {Object} opt | ||
* @param {?string} opt.url | ||
* @param {string|number} opt.number | ||
* @param {?string} opt.file | ||
* @param {?string[]} opt.metrics | ||
* @param {string} opt.output | ||
* @param {boolean} opt.showPercentiles | ||
* @param {boolean} opt.showVariance | ||
* @param {?string} opt.throttleCpu | ||
* @param {?NetworkConditionName} opt.networkConditions | ||
* @param {?string} opt.windowViewport | ||
* @param {Object} opt | ||
* @param {?string} opt.url | ||
* @param {string|number} opt.number | ||
* @param {?string} opt.file | ||
* @param {?string[]} opt.metrics | ||
* @param {string} opt.output | ||
* @param {boolean} opt.showPercentiles | ||
* @param {boolean} opt.showVariance | ||
* @param {?string} opt.throttleCpu | ||
* @param {?string} opt.networkConditions | ||
* @param {?string} opt.emulateDevice | ||
* @param {?string} opt.windowViewport | ||
* @return {Params} Parameters. | ||
*/ | ||
function getParamsFromOptions( opt ) { | ||
|
@@ -160,7 +175,10 @@ function getParamsFromOptions( opt ) { | |
showVariance: Boolean( opt.showVariance ), | ||
cpuThrottleFactor: null, | ||
networkConditions: null, | ||
windowViewport: { width: 960, height: 700 }, // Viewport similar to @wordpress/e2e-test-utils 'large' configuration. | ||
emulateDevice: null, | ||
windowViewport: ! opt.emulateDevice | ||
? { width: 960, height: 700 } | ||
: null, // Viewport similar to @wordpress/e2e-test-utils 'large' configuration. | ||
}; | ||
|
||
if ( isNaN( params.amount ) ) { | ||
|
@@ -200,10 +218,18 @@ function getParamsFromOptions( opt ) { | |
PredefinedNetworkConditions[ opt.networkConditions ]; | ||
} | ||
|
||
if ( opt.emulateDevice ) { | ||
if ( ! ( opt.emulateDevice in KnownDevices ) ) { | ||
throw new Error( | ||
`Unrecognized device to emulate: ${ opt.emulateDevice }` | ||
); | ||
} | ||
params.emulateDevice = KnownDevices[ opt.emulateDevice ]; | ||
} | ||
|
||
if ( opt.windowViewport ) { | ||
if ( 'mobile' === opt.windowViewport ) { | ||
// This corresponds to the mobile viewport tested in Lighthouse: <https://github.com/GoogleChrome/lighthouse/blob/b64b3534542c9dcaabb33d40b84ed7c93eefbd7d/core/config/constants.js#L14-L22>. | ||
// TODO: Consider deviceScaleFactor. | ||
params.windowViewport = { | ||
width: 412, | ||
height: 823, | ||
|
@@ -338,7 +364,7 @@ export async function handler( opt ) { | |
const params = getParamsFromOptions( opt ); | ||
const results = []; | ||
|
||
const browser = await puppeteer.launch( { headless: 'new' } ); | ||
const browser = await puppeteer.launch( { headless: true } ); | ||
|
||
const metricsDefinition = getMetricsDefinition( params.metrics ); | ||
|
||
|
@@ -449,12 +475,17 @@ async function benchmarkURL( | |
await page.emulateNetworkConditions( params.networkConditions ); | ||
} | ||
|
||
await page.setViewport( params.windowViewport ); | ||
await page | ||
.mainFrame() | ||
.waitForFunction( | ||
`window.innerWidth === ${ params.windowViewport.width } && window.innerHeight === ${ params.windowViewport.height }` | ||
); | ||
Comment on lines
-453
to
-457
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I removed this code because it with the |
||
if ( params.emulateDevice ) { | ||
await page.emulate( params.emulateDevice ); | ||
} | ||
if ( params.windowViewport ) { | ||
await page.setViewport( { | ||
...( params.emulateDevice | ||
? params.emulateDevice.viewport | ||
: {} ), | ||
...params.windowViewport, | ||
} ); | ||
} | ||
|
||
// Load the page. | ||
const urlObj = new URL( url ); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change was caught by TypeScript since Puppeteer the new headless mode is now the default.