mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
feat(size): emulate window.screen size (#5967)
This commit is contained in:
parent
8c6822bd32
commit
f1c0d09765
@ -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-%%
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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' },
|
||||
}),
|
||||
|
||||
@ -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'
|
||||
},
|
||||
};
|
||||
|
||||
@ -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,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@ -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> {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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();
|
||||
});
|
||||
});
|
||||
|
||||
@ -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
82
types/types.d.ts
vendored
@ -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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user