feat(size): emulate window.screen size (#5967)

This commit is contained in:
Pavel Feldman 2021-03-30 05:10:58 +08:00 committed by GitHub
parent 8c6822bd32
commit f1c0d09765
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 391 additions and 43 deletions

View File

@ -216,7 +216,18 @@ Toggles bypassing page's Content-Security-Policy.
- `width` <[int]> page width in pixels.
- `height` <[int]> page height in pixels.
Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `null` disables the default viewport.
Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. `null` disables the default viewport.
## context-option-screen
* langs:
- alias-java: screenSize
- alias-csharp: screenSize
- `screen` <[Object]>
- `width` <[int]> page width in pixels.
- `height` <[int]> page height in pixels.
Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the
[`option: viewport`] is set.
## evaluate-expression
- `expression` <[string]>
@ -546,6 +557,7 @@ is considered matching if all specified properties match.
- %%-context-option-bypasscsp-%%
- %%-context-option-viewport-%%
- %%-python-context-option-viewport-%%
- %%-context-option-screen-%%
- %%-python-context-option-no-viewport-%%
- %%-context-option-useragent-%%
- %%-context-option-devicescalefactor-%%

View File

@ -166,6 +166,10 @@ export type PlaywrightInitializer = {
width: number,
height: number,
},
screen?: {
width: number,
height: number,
},
deviceScaleFactor: number,
isMobile: boolean,
hasTouch: boolean,
@ -294,6 +298,10 @@ export type BrowserTypeLaunchPersistentContextParams = {
width: number,
height: number,
},
screen?: {
width: number,
height: number,
},
ignoreHTTPSErrors?: boolean,
javaScriptEnabled?: boolean,
bypassCSP?: boolean,
@ -359,6 +367,10 @@ export type BrowserTypeLaunchPersistentContextOptions = {
width: number,
height: number,
},
screen?: {
width: number,
height: number,
},
ignoreHTTPSErrors?: boolean,
javaScriptEnabled?: boolean,
bypassCSP?: boolean,
@ -439,6 +451,10 @@ export type BrowserNewContextParams = {
width: number,
height: number,
},
screen?: {
width: number,
height: number,
},
ignoreHTTPSErrors?: boolean,
javaScriptEnabled?: boolean,
bypassCSP?: boolean,
@ -492,6 +508,10 @@ export type BrowserNewContextOptions = {
width: number,
height: number,
},
screen?: {
width: number,
height: number,
},
ignoreHTTPSErrors?: boolean,
javaScriptEnabled?: boolean,
bypassCSP?: boolean,

View File

@ -275,6 +275,11 @@ ContextOptions:
properties:
width: number
height: number
screen:
type: object?
properties:
width: number
height: number
ignoreHTTPSErrors: boolean?
javaScriptEnabled: boolean?
bypassCSP: boolean?
@ -351,6 +356,11 @@ Playwright:
properties:
width: number
height: number
screen:
type: object?
properties:
width: number
height: number
deviceScaleFactor: number
isMobile: boolean
hasTouch: boolean

View File

@ -204,6 +204,10 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
width: tNumber,
height: tNumber,
})),
screen: tOptional(tObject({
width: tNumber,
height: tNumber,
})),
ignoreHTTPSErrors: tOptional(tBoolean),
javaScriptEnabled: tOptional(tBoolean),
bypassCSP: tOptional(tBoolean),
@ -257,6 +261,10 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
width: tNumber,
height: tNumber,
})),
screen: tOptional(tObject({
width: tNumber,
height: tNumber,
})),
ignoreHTTPSErrors: tOptional(tBoolean),
javaScriptEnabled: tOptional(tBoolean),
bypassCSP: tOptional(tBoolean),

View File

@ -87,7 +87,7 @@ export class CRPage implements PageDelegate {
const features = opener._nextWindowOpenPopupFeatures.shift() || [];
const viewportSize = helper.getViewportSizeFromWindowFeatures(features);
if (viewportSize)
this._page._state.viewportSize = viewportSize;
this._page._state.emulatedSize = { viewport: viewportSize, screen: viewportSize };
}
this._pagePromise = this._mainFrameSession._initialize(hasUIWindow).then(() => this._initializedPage = this._page).catch(e => e);
}
@ -162,8 +162,8 @@ export class CRPage implements PageDelegate {
await this._forAllFrameSessions(frame => frame._updateHttpCredentials(false));
}
async setViewportSize(viewportSize: types.Size): Promise<void> {
assert(this._page._state.viewportSize === viewportSize);
async setEmulatedSize(emulatedSize: types.EmulatedSize): Promise<void> {
assert(this._page._state.emulatedSize === emulatedSize);
await this._mainFrameSession._updateViewport();
}
@ -899,17 +899,19 @@ class FrameSession {
return;
assert(this._isMainFrame());
const options = this._crPage._browserContext._options;
const viewportSize = this._page._state.viewportSize;
if (viewportSize === null)
const emulatedSize = this._page._state.emulatedSize;
if (emulatedSize === null)
return;
const viewportSize = emulatedSize.viewport;
const screenSize = emulatedSize.screen;
const isLandscape = viewportSize.width > viewportSize.height;
const promises = [
this._client.send('Emulation.setDeviceMetricsOverride', {
mobile: !!options.isMobile,
width: viewportSize.width,
height: viewportSize.height,
screenWidth: viewportSize.width,
screenHeight: viewportSize.height,
screenWidth: screenSize.width,
screenHeight: screenSize.height,
deviceScaleFactor: options.deviceScaleFactor || 1,
screenOrientation: isLandscape ? { angle: 90, type: 'landscapePrimary' } : { angle: 0, type: 'portraitPrimary' },
}),

View File

@ -439,10 +439,14 @@ module.exports = {
},
'iPhone 11': {
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Mobile/15E148 Safari/604.1',
'viewport': {
'screen': {
'width': 414,
'height': 896
},
'viewport': {
'width': 414,
'height': 715
},
'deviceScaleFactor': 2,
'isMobile': true,
'hasTouch': true,
@ -450,9 +454,13 @@ module.exports = {
},
'iPhone 11 landscape': {
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Mobile/15E148 Safari/604.1',
'screen': {
'width': 414,
'height': 896
},
'viewport': {
'width': 896,
'height': 414
'width': 800,
'height': 364
},
'deviceScaleFactor': 2,
'isMobile': true,
@ -461,10 +469,14 @@ module.exports = {
},
'iPhone 11 Pro': {
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Mobile/15E148 Safari/604.1',
'viewport': {
'screen': {
'width': 375,
'height': 812
},
'viewport': {
'width': 375,
'height': 635
},
'deviceScaleFactor': 3,
'isMobile': true,
'hasTouch': true,
@ -472,9 +484,13 @@ module.exports = {
},
'iPhone 11 Pro landscape': {
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Mobile/15E148 Safari/604.1',
'screen': {
'width': 375,
'height': 812
},
'viewport': {
'width': 812,
'height': 375
'width': 724,
'height': 325
},
'deviceScaleFactor': 3,
'isMobile': true,
@ -483,10 +499,14 @@ module.exports = {
},
'iPhone 11 Pro Max': {
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Mobile/15E148 Safari/604.1',
'viewport': {
'screen': {
'width': 414,
'height': 896
},
'viewport': {
'width': 414,
'height': 715
},
'deviceScaleFactor': 3,
'isMobile': true,
'hasTouch': true,
@ -494,9 +514,103 @@ module.exports = {
},
'iPhone 11 Pro Max landscape': {
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Mobile/15E148 Safari/604.1',
'screen': {
'width': 414,
'height': 896
},
'viewport': {
'width': 896,
'height': 414
'width': 808,
'height': 364
},
'deviceScaleFactor': 3,
'isMobile': true,
'hasTouch': true,
'defaultBrowserType': 'webkit'
},
'iPhone 12': {
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1',
'screen': {
'width': 390,
'height': 844
},
'viewport': {
'width': 390,
'height': 664
},
'deviceScaleFactor': 3,
'isMobile': true,
'hasTouch': true,
'defaultBrowserType': 'webkit'
},
'iPhone 12 landscape': {
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1',
'screen': {
'width': 390,
'height': 844
},
'viewport': {
'width': 750,
'height': 340
},
'deviceScaleFactor': 3,
'isMobile': true,
'hasTouch': true,
'defaultBrowserType': 'webkit'
},
'iPhone 12 Pro': {
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1',
'screen': {
'width': 390,
'height': 844
},
'viewport': {
'width': 390,
'height': 664
},
'deviceScaleFactor': 3,
'isMobile': true,
'hasTouch': true,
'defaultBrowserType': 'webkit'
},
'iPhone 12 Pro landscape': {
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1',
'screen': {
'width': 390,
'height': 844
},
'viewport': {
'width': 750,
'height': 340
},
'deviceScaleFactor': 3,
'isMobile': true,
'hasTouch': true,
'defaultBrowserType': 'webkit'
},
'iPhone 12 Pro Max': {
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1',
'screen': {
'width': 428,
'height': 926
},
'viewport': {
'width': 428,
'height': 746
},
'deviceScaleFactor': 3,
'isMobile': true,
'hasTouch': true,
'defaultBrowserType': 'webkit'
},
'iPhone 12 Pro Max landscape': {
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1',
'screen': {
'width': 428,
'height': 926
},
'viewport': {
'width': 832,
'height': 378
},
'deviceScaleFactor': 3,
'isMobile': true,
@ -854,5 +968,65 @@ module.exports = {
'isMobile': true,
'hasTouch': true,
'defaultBrowserType': 'chromium'
}
},
'Pixel 4a (5G)': {
'userAgent': 'Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36',
'screen': {
'width': 412,
'height': 892
},
'viewport': {
'width': 412,
'height': 765
},
'deviceScaleFactor': 2.63,
'isMobile': true,
'hasTouch': true,
'defaultBrowserType': 'chromium'
},
'Pixel 4a (5G) landscape': {
'userAgent': 'Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36',
'screen': {
'height': 892,
'width': 412
},
'viewport': {
'width': 840,
'height': 312
},
'deviceScaleFactor': 2.63,
'isMobile': true,
'hasTouch': true,
'defaultBrowserType': 'chromium'
},
'Pixel 5': {
'userAgent': 'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36',
'screen': {
'width': 393,
'height': 851
},
'viewport': {
'width': 393,
'height': 727
},
'deviceScaleFactor': 2.75,
'isMobile': true,
'hasTouch': true,
'defaultBrowserType': 'chromium'
},
'Pixel 5 landscape': {
'userAgent': 'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36',
'screen': {
'width': 851,
'height': 393
},
'viewport': {
'width': 802,
'height': 293
},
'deviceScaleFactor': 2.75,
'isMobile': true,
'hasTouch': true,
'defaultBrowserType': 'chromium'
},
};

View File

@ -315,12 +315,12 @@ export class FFPage implements PageDelegate {
await this._session.send('Network.setExtraHTTPHeaders', { headers: this._page._state.extraHTTPHeaders || [] });
}
async setViewportSize(viewportSize: types.Size): Promise<void> {
assert(this._page._state.viewportSize === viewportSize);
async setEmulatedSize(emulatedSize: types.EmulatedSize): Promise<void> {
assert(this._page._state.emulatedSize === emulatedSize);
await this._session.send('Page.setViewportSize', {
viewportSize: {
width: viewportSize.width,
height: viewportSize.height,
width: emulatedSize.viewport.width,
height: emulatedSize.viewport.height,
},
});
}

View File

@ -52,7 +52,7 @@ export interface PageDelegate {
navigateFrame(frame: frames.Frame, url: string, referrer: string | undefined): Promise<frames.GotoResult>;
updateExtraHTTPHeaders(): Promise<void>;
setViewportSize(viewportSize: types.Size): Promise<void>;
setEmulatedSize(emulatedSize: types.EmulatedSize): Promise<void>;
updateEmulateMedia(): Promise<void>;
updateRequestInterception(): Promise<void>;
setFileChooserIntercepted(enabled: boolean): Promise<void>;
@ -86,7 +86,7 @@ export interface PageDelegate {
}
type PageState = {
viewportSize: types.Size | null;
emulatedSize: { screen: types.Size, viewport: types.Size } | null;
mediaType: types.MediaType | null;
colorScheme: types.ColorScheme | null;
extraHTTPHeaders: types.HeadersArray | null;
@ -163,7 +163,7 @@ export class Page extends SdkObject {
this._crashedPromise = new Promise(f => this._crashedCallback = f);
this._browserContext = browserContext;
this._state = {
viewportSize: browserContext._options.viewport || null,
emulatedSize: browserContext._options.viewport ? { viewport: browserContext._options.viewport, screen: browserContext._options.screen || browserContext._options.viewport } : null,
mediaType: null,
colorScheme: null,
extraHTTPHeaders: null,
@ -369,13 +369,13 @@ export class Page extends SdkObject {
}
async setViewportSize(viewportSize: types.Size) {
this._state.viewportSize = { ...viewportSize };
await this._delegate.setViewportSize(this._state.viewportSize);
this._state.emulatedSize = { viewport: { ...viewportSize }, screen: { ...viewportSize } };
await this._delegate.setEmulatedSize(this._state.emulatedSize);
await this._doSlowMo();
}
viewportSize(): types.Size | null {
return this._state.viewportSize;
return this._state.emulatedSize?.viewport || null;
}
async bringToFront(): Promise<void> {

View File

@ -214,9 +214,12 @@ export type SetNetworkCookieParam = {
sameSite?: 'Strict' | 'Lax' | 'None'
};
export type EmulatedSize = { viewport: Size, screen: Size };
export type BrowserContextOptions = {
sdkLanguage: string,
viewport?: Size,
screen?: Size,
noDefaultViewport?: boolean,
ignoreHTTPSErrors?: boolean,
javaScriptEnabled?: boolean,

View File

@ -97,7 +97,7 @@ export class WKPage implements PageDelegate {
const viewportSize = helper.getViewportSizeFromWindowFeatures(opener._nextWindowOpenPopupFeatures);
opener._nextWindowOpenPopupFeatures = undefined;
if (viewportSize)
this._page._state.viewportSize = viewportSize;
this._page._state.emulatedSize = { viewport: viewportSize, screen: viewportSize };
}
}
@ -181,10 +181,10 @@ export class WKPage implements PageDelegate {
this._page.frames().map(frame => frame.evaluateExpression(bootstrapScript, false, undefined, 'main').catch(e => {}));
if (contextOptions.bypassCSP)
promises.push(session.send('Page.setBypassCSP', { enabled: true }));
if (this._page._state.viewportSize) {
if (this._page._state.emulatedSize) {
promises.push(session.send('Page.setScreenSizeOverride', {
width: this._page._state.viewportSize.width,
height: this._page._state.viewportSize.height,
width: this._page._state.emulatedSize.screen.width,
height: this._page._state.emulatedSize.screen.height,
}));
}
promises.push(this.updateEmulateMedia());
@ -603,8 +603,8 @@ export class WKPage implements PageDelegate {
await this._forAllSessions(session => WKPage._setEmulateMedia(session, this._page._state.mediaType, colorScheme));
}
async setViewportSize(viewportSize: types.Size): Promise<void> {
assert(this._page._state.viewportSize === viewportSize);
async setEmulatedSize(emulatedSize: types.EmulatedSize): Promise<void> {
assert(this._page._state.emulatedSize === emulatedSize);
await this._updateViewport();
}
@ -616,9 +616,11 @@ export class WKPage implements PageDelegate {
async _updateViewport(): Promise<void> {
const options = this._browserContext._options;
const viewportSize = this._page._state.viewportSize;
if (viewportSize === null)
const deviceSize = this._page._state.emulatedSize;
if (deviceSize === null)
return;
const viewportSize = deviceSize.viewport;
const screenSize = deviceSize.screen;
const promises: Promise<any>[] = [
this._pageProxySession.send('Emulation.setDeviceMetricsOverride', {
width: viewportSize.width,
@ -627,8 +629,8 @@ export class WKPage implements PageDelegate {
deviceScaleFactor: options.deviceScaleFactor || 1
}),
this._session.send('Page.setScreenSizeOverride', {
width: viewportSize.width,
height: viewportSize.height,
width: screenSize.width,
height: screenSize.height,
}),
];
if (options.isMobile) {

View File

@ -114,4 +114,47 @@ describe('device', (suite, { browserName }) => {
await context.close();
});
it('should emulate viewport and screen size', async ({server, contextFactory, playwright, contextOptions}) => {
const device = playwright.devices['iPhone 12'];
const context = await contextFactory({
...contextOptions,
...device,
});
const page = await context.newPage();
await page.setContent(`<meta name="viewport" content="width=device-width, user-scalable=no" />`);
expect(await page.evaluate(() => ({
width: window.screen.width,
height: window.screen.height
}))).toEqual({ width: 390, height: 844 });
expect(await page.evaluate(() => ({
width: window.innerWidth,
height: window.innerHeight
}))).toEqual({ width: 390, height: 664 });
await context.close();
});
it('should emulate viewport without screen size', async ({server, contextFactory, playwright, contextOptions}) => {
const device = playwright.devices['iPhone 6'];
const context = await contextFactory({
...contextOptions,
...device,
});
const page = await context.newPage();
await page.setContent(`<meta name="viewport" content="width=device-width, user-scalable=no" />`);
expect(await page.evaluate(() => ({
width: window.screen.width,
height: window.screen.height
}))).toEqual({ width: 375, height: 667 });
expect(await page.evaluate(() => ({
width: window.innerWidth,
height: window.innerHeight
}))).toEqual({ width: 375, height: 667 });
await context.close();
});
});

View File

@ -69,7 +69,7 @@ it('should print the correct context options when using a device and additional
const expectedResult = `BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.setColorScheme(ColorScheme.LIGHT)
.setUserAgent("Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Mobile/15E148 Safari/604.1")
.setViewportSize(414, 896)
.setViewportSize(414, 715)
.setDeviceScaleFactor(2)
.setIsMobile(true)
.setHasTouch(true));`;

82
types/types.d.ts vendored
View File

@ -6576,6 +6576,22 @@ export interface BrowserType<Browser> {
};
};
/**
* Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the `viewport`
* is set.
*/
screen?: {
/**
* page width in pixels.
*/
width: number;
/**
* page height in pixels.
*/
height: number;
};
/**
* Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on.
* Defaults to 0.
@ -6623,7 +6639,7 @@ export interface BrowserType<Browser> {
videosPath?: string;
/**
* Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `null` disables the default viewport.
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. `null` disables the default viewport.
*/
viewport?: null|{
/**
@ -7666,6 +7682,22 @@ export interface AndroidDevice {
};
};
/**
* Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the `viewport`
* is set.
*/
screen?: {
/**
* page width in pixels.
*/
width: number;
/**
* page height in pixels.
*/
height: number;
};
/**
* Changes the timezone of the context. See
* [ICU's metaZones.txt](https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1)
@ -7701,7 +7733,7 @@ export interface AndroidDevice {
videosPath?: string;
/**
* Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `null` disables the default viewport.
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. `null` disables the default viewport.
*/
viewport?: null|{
/**
@ -8418,6 +8450,22 @@ export interface Browser extends EventEmitter {
};
};
/**
* Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the `viewport`
* is set.
*/
screen?: {
/**
* page width in pixels.
*/
width: number;
/**
* page height in pixels.
*/
height: number;
};
/**
* Populates context with given storage state. This option can be used to initialize context with logged-in information
* obtained via
@ -8518,7 +8566,7 @@ export interface Browser extends EventEmitter {
videosPath?: string;
/**
* Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `null` disables the default viewport.
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. `null` disables the default viewport.
*/
viewport?: null|{
/**
@ -10500,6 +10548,22 @@ export interface BrowserContextOptions {
};
};
/**
* Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the `viewport`
* is set.
*/
screen?: {
/**
* page width in pixels.
*/
width: number;
/**
* page height in pixels.
*/
height: number;
};
/**
* Populates context with given storage state. This option can be used to initialize context with logged-in information
* obtained via
@ -10600,7 +10664,7 @@ export interface BrowserContextOptions {
videosPath?: string;
/**
* Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `null` disables the default viewport.
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. `null` disables the default viewport.
*/
viewport?: null|ViewportSize;
}
@ -10907,6 +10971,12 @@ type Devices = {
"iPhone 11 Pro landscape": DeviceDescriptor;
"iPhone 11 Pro Max": DeviceDescriptor;
"iPhone 11 Pro Max landscape": DeviceDescriptor;
"iPhone 12": DeviceDescriptor;
"iPhone 12 landscape": DeviceDescriptor;
"iPhone 12 Pro": DeviceDescriptor;
"iPhone 12 Pro landscape": DeviceDescriptor;
"iPhone 12 Pro Max": DeviceDescriptor;
"iPhone 12 Pro Max landscape": DeviceDescriptor;
"JioPhone 2": DeviceDescriptor;
"JioPhone 2 landscape": DeviceDescriptor;
"Kindle Fire HDX": DeviceDescriptor;
@ -10939,5 +11009,9 @@ type Devices = {
"Pixel 2 landscape": DeviceDescriptor;
"Pixel 2 XL": DeviceDescriptor;
"Pixel 2 XL landscape": DeviceDescriptor;
"Pixel 4a (5G)": DeviceDescriptor;
"Pixel 4a (5G) landscape": DeviceDescriptor;
"Pixel 5": DeviceDescriptor;
"Pixel 5 landscape": DeviceDescriptor;
[key: string]: DeviceDescriptor;
}