Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion docs/src/api/params.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,24 @@ When using [`method: Page.goto`], [`method: Page.route`], [`method: Page.waitFor
* baseURL: `http://localhost:3000/foo` (without trailing slash) and navigating to `./bar.html` results in `http://localhost:3000/bar.html`

## context-option-viewport
* langs: js, java
* langs: js
- `viewport` <[null]|"maximized"|[Object]>
* alias: ViewportSize
- `width` <[int]> page width in pixels.
- `height` <[int]> page height in pixels.

Emulates consistent viewport for each page. Defaults to an 1280x720 viewport.
Use `null` to disable the consistent viewport emulation. Learn more about [viewport emulation](../emulation#viewport).
Use `"maximized"` to disable viewport emulation and maximize each native browser window. This is only supported in headed mode and does not enter fullscreen mode or trigger the web Fullscreen API.

:::note
The `null` and `"maximized"` values opt out from the default presets and make viewport depend on the
host window size defined by the operating system. It makes the execution of the
tests non-deterministic.
:::

## java-context-option-viewport
* langs: java
- alias-java: viewportSize
- `viewport` <[null]|[Object]>
* alias: ViewportSize
Expand Down Expand Up @@ -1090,6 +1107,7 @@ between the same pixel in compared images, between zero (strict) and one (lax),
- %%-context-option-bypasscsp-%%
- %%-context-option-baseURL-%%
- %%-context-option-viewport-%%
- %%-java-context-option-viewport-%%
- %%-csharp-context-option-viewport-%%
- %%-python-context-option-viewport-%%
- %%-context-option-screen-%%
Expand Down
2 changes: 1 addition & 1 deletion packages/isomorphic/codegen/java.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ function formatContextOptions(contextOptions: BrowserContextOptions, deviceName:
lines.push(` .setTimezoneId(${quote(options.timezoneId)})`);
if (options.userAgent)
lines.push(` .setUserAgent(${quote(options.userAgent)})`);
if (options.viewport)
if (options.viewport && options.viewport !== 'maximized')
lines.push(` .setViewportSize(${options.viewport.width}, ${options.viewport.height})`);
return lines.join('\n');
}
Expand Down
40 changes: 24 additions & 16 deletions packages/playwright-client/types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11706,13 +11706,15 @@ export interface Browser {

/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use `null` to disable the consistent
* viewport emulation. Learn more about [viewport emulation](https://playwright.dev/docs/emulation#viewport).
* viewport emulation. Learn more about [viewport emulation](https://playwright.dev/docs/emulation#viewport). Use `"maximized"` to disable
* viewport emulation and maximize each native browser window. This is only supported in headed mode and does not
* enter fullscreen mode or trigger the web Fullscreen API.
*
* **NOTE** The `null` value opts out from the default presets, makes viewport depend on the host window size defined
* by the operating system. It makes the execution of the tests non-deterministic.
* **NOTE** The `null` and `"maximized"` values opt out from the default presets and make viewport depend on the host
* window size defined by the operating system. It makes the execution of the tests non-deterministic.
*
*/
viewport?: null|{
viewport?: null|"maximized"|{
/**
* page width in pixels.
*/
Expand Down Expand Up @@ -18015,13 +18017,15 @@ export interface BrowserType<Unused = {}> {

/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use `null` to disable the consistent
* viewport emulation. Learn more about [viewport emulation](https://playwright.dev/docs/emulation#viewport).
* viewport emulation. Learn more about [viewport emulation](https://playwright.dev/docs/emulation#viewport). Use `"maximized"` to disable
* viewport emulation and maximize each native browser window. This is only supported in headed mode and does not
* enter fullscreen mode or trigger the web Fullscreen API.
*
* **NOTE** The `null` value opts out from the default presets, makes viewport depend on the host window size defined
* by the operating system. It makes the execution of the tests non-deterministic.
* **NOTE** The `null` and `"maximized"` values opt out from the default presets and make viewport depend on the host
* window size defined by the operating system. It makes the execution of the tests non-deterministic.
*
*/
viewport?: null|{
viewport?: null|"maximized"|{
/**
* page width in pixels.
*/
Expand Down Expand Up @@ -24875,13 +24879,15 @@ export interface AndroidDevice {

/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use `null` to disable the consistent
* viewport emulation. Learn more about [viewport emulation](https://playwright.dev/docs/emulation#viewport).
* viewport emulation. Learn more about [viewport emulation](https://playwright.dev/docs/emulation#viewport). Use `"maximized"` to disable
* viewport emulation and maximize each native browser window. This is only supported in headed mode and does not
* enter fullscreen mode or trigger the web Fullscreen API.
*
* **NOTE** The `null` value opts out from the default presets, makes viewport depend on the host window size defined
* by the operating system. It makes the execution of the tests non-deterministic.
* **NOTE** The `null` and `"maximized"` values opt out from the default presets and make viewport depend on the host
* window size defined by the operating system. It makes the execution of the tests non-deterministic.
*
*/
viewport?: null|{
viewport?: null|"maximized"|{
/**
* page width in pixels.
*/
Expand Down Expand Up @@ -26142,13 +26148,15 @@ export interface BrowserContextOptions {

/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use `null` to disable the consistent
* viewport emulation. Learn more about [viewport emulation](https://playwright.dev/docs/emulation#viewport).
* viewport emulation. Learn more about [viewport emulation](https://playwright.dev/docs/emulation#viewport). Use `"maximized"` to disable
* viewport emulation and maximize each native browser window. This is only supported in headed mode and does not
* enter fullscreen mode or trigger the web Fullscreen API.
*
* **NOTE** The `null` value opts out from the default presets, makes viewport depend on the host window size defined
* by the operating system. It makes the execution of the tests non-deterministic.
* **NOTE** The `null` and `"maximized"` values opt out from the default presets and make viewport depend on the host
* window size defined by the operating system. It makes the execution of the tests non-deterministic.
*
*/
viewport?: null|ViewportSize;
viewport?: null|"maximized"|ViewportSize;
}

export interface ViewportSize {
Expand Down
5 changes: 3 additions & 2 deletions packages/playwright-core/src/client/browserContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -574,8 +574,9 @@ export async function prepareBrowserContextParams(options: BrowserContextOptions
network.validateHeaders(options.extraHTTPHeaders);
const contextParams: channels.BrowserNewContextParams = {
...options,
viewport: options.viewport === null ? undefined : options.viewport,
noDefaultViewport: options.viewport === null,
viewport: options.viewport === null || options.viewport === 'maximized' ? undefined : options.viewport,
viewportMaximized: options.viewport === 'maximized',
noDefaultViewport: options.viewport === null || options.viewport === 'maximized',
extraHTTPHeaders: options.extraHTTPHeaders ? headersObjectToArray(options.extraHTTPHeaders) : undefined,
storageState: options.storageState ? await prepareStorageState(options.storageState) : undefined,
serviceWorkers: options.serviceWorkers,
Expand Down
9 changes: 9 additions & 0 deletions packages/playwright-core/src/client/channels.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ export type AndroidDeviceLaunchBrowserParams = {
width: number,
height: number,
},
viewportMaximized?: boolean,
screen?: {
width: number,
height: number,
Expand Down Expand Up @@ -446,6 +447,7 @@ export type AndroidDeviceLaunchBrowserOptions = {
width: number,
height: number,
},
viewportMaximized?: boolean,
screen?: {
width: number,
height: number,
Expand Down Expand Up @@ -828,6 +830,7 @@ export type BrowserNewContextParams = {
width: number,
height: number,
},
viewportMaximized?: boolean,
screen?: {
width: number,
height: number,
Expand Down Expand Up @@ -898,6 +901,7 @@ export type BrowserNewContextOptions = {
width: number,
height: number,
},
viewportMaximized?: boolean,
screen?: {
width: number,
height: number,
Expand Down Expand Up @@ -971,6 +975,7 @@ export type BrowserNewContextForReuseParams = {
width: number,
height: number,
},
viewportMaximized?: boolean,
screen?: {
width: number,
height: number,
Expand Down Expand Up @@ -1041,6 +1046,7 @@ export type BrowserNewContextForReuseOptions = {
width: number,
height: number,
},
viewportMaximized?: boolean,
screen?: {
width: number,
height: number,
Expand Down Expand Up @@ -1153,6 +1159,7 @@ export type BrowserContextInitializer = {
width: number,
height: number,
},
viewportMaximized?: boolean,
screen?: {
width: number,
height: number,
Expand Down Expand Up @@ -1798,6 +1805,7 @@ export type BrowserTypeLaunchPersistentContextParams = {
width: number,
height: number,
},
viewportMaximized?: boolean,
screen?: {
width: number,
height: number,
Expand Down Expand Up @@ -1881,6 +1889,7 @@ export type BrowserTypeLaunchPersistentContextOptions = {
width: number,
height: number,
},
viewportMaximized?: boolean,
screen?: {
width: number,
height: number,
Expand Down
4 changes: 2 additions & 2 deletions packages/playwright-core/src/client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ export type ClientCertificate = {
passphrase?: string;
};

export type BrowserContextOptions = Omit<channels.BrowserNewContextOptions, 'viewport' | 'noDefaultViewport' | 'extraHTTPHeaders' | 'clientCertificates' | 'storageState' | 'recordHar' | 'colorScheme' | 'reducedMotion' | 'forcedColors' | 'acceptDownloads' | 'contrast' | 'agent' | 'httpCredentials'> & {
viewport?: Size | null;
export type BrowserContextOptions = Omit<channels.BrowserNewContextOptions, 'viewport' | 'noDefaultViewport' | 'viewportMaximized' | 'extraHTTPHeaders' | 'clientCertificates' | 'storageState' | 'recordHar' | 'colorScheme' | 'reducedMotion' | 'forcedColors' | 'acceptDownloads' | 'contrast' | 'agent' | 'httpCredentials'> & {
viewport?: Size | 'maximized' | null;
extraHTTPHeaders?: Headers;
httpCredentials?: HttpCredentials | HttpCredentials[];
logger?: Logger;
Expand Down
18 changes: 16 additions & 2 deletions packages/playwright-core/src/server/browserContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -760,10 +760,15 @@ export abstract class BrowserContext<EM extends EventMap = EventMap> extends Sdk
}

export function validateBrowserContextOptions(options: types.BrowserContextOptions, browserOptions: BrowserOptions) {
const noDefaultViewportDescription = options.viewportMaximized ? '"maximized" viewport' : 'null "viewport"';
if (options.noDefaultViewport && options.deviceScaleFactor !== undefined)
throw new Error(`"deviceScaleFactor" option is not supported with null "viewport"`);
throw new Error(`"deviceScaleFactor" option is not supported with ${noDefaultViewportDescription}`);
if (options.noDefaultViewport && !!options.isMobile)
throw new Error(`"isMobile" option is not supported with null "viewport"`);
throw new Error(`"isMobile" option is not supported with ${noDefaultViewportDescription}`);
if (options.viewportMaximized && !browserOptions.headful)
throw new Error(`"maximized" viewport is not supported in headless mode`);
if (options.viewportMaximized && !supportsMaximizedViewport(browserOptions))
throw new Error(`"maximized" viewport is not supported for this browser`);
if (options.acceptDownloads === undefined && browserOptions.name !== 'electron')
options.acceptDownloads = 'accept';
// Electron requires explicit acceptDownloads: true since we wait for
Expand All @@ -778,6 +783,14 @@ export function validateBrowserContextOptions(options: types.BrowserContextOptio
verifyGeolocation(options.geolocation);
}

function supportsMaximizedViewport(browserOptions: BrowserOptions) {
if (browserOptions.name === 'chromium')
return !browserOptions.channel?.startsWith('bidi-');
if (browserOptions.name === 'firefox')
return !browserOptions.channel?.startsWith('moz-');
return browserOptions.name === 'webkit';
}

export function findMatchingHttpCredentials(credentials: HttpCredentials[] | undefined, url: string): HttpCredentials | undefined {
const origin = new URL(url).origin.toLowerCase();
return credentials?.find(c => !c.origin || c.origin.toLowerCase() === origin);
Expand Down Expand Up @@ -849,6 +862,7 @@ const paramsThatAllowContextReuse: (keyof channels.BrowserNewContextForReusePara

const defaultNewContextParamValues: channels.BrowserNewContextForReuseParams = {
noDefaultViewport: false,
viewportMaximized: false,
ignoreHTTPSErrors: false,
javaScriptEnabled: true,
bypassCSP: false,
Expand Down
9 changes: 9 additions & 0 deletions packages/playwright-core/src/server/channels.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ export type AndroidDeviceLaunchBrowserParams = {
width: number,
height: number,
},
viewportMaximized?: boolean,
screen?: {
width: number,
height: number,
Expand Down Expand Up @@ -447,6 +448,7 @@ export type AndroidDeviceLaunchBrowserOptions = {
width: number,
height: number,
},
viewportMaximized?: boolean,
screen?: {
width: number,
height: number,
Expand Down Expand Up @@ -829,6 +831,7 @@ export type BrowserNewContextParams = {
width: number,
height: number,
},
viewportMaximized?: boolean,
screen?: {
width: number,
height: number,
Expand Down Expand Up @@ -899,6 +902,7 @@ export type BrowserNewContextOptions = {
width: number,
height: number,
},
viewportMaximized?: boolean,
screen?: {
width: number,
height: number,
Expand Down Expand Up @@ -972,6 +976,7 @@ export type BrowserNewContextForReuseParams = {
width: number,
height: number,
},
viewportMaximized?: boolean,
screen?: {
width: number,
height: number,
Expand Down Expand Up @@ -1042,6 +1047,7 @@ export type BrowserNewContextForReuseOptions = {
width: number,
height: number,
},
viewportMaximized?: boolean,
screen?: {
width: number,
height: number,
Expand Down Expand Up @@ -1154,6 +1160,7 @@ export type BrowserContextInitializer = {
width: number,
height: number,
},
viewportMaximized?: boolean,
screen?: {
width: number,
height: number,
Expand Down Expand Up @@ -1799,6 +1806,7 @@ export type BrowserTypeLaunchPersistentContextParams = {
width: number,
height: number,
},
viewportMaximized?: boolean,
screen?: {
width: number,
height: number,
Expand Down Expand Up @@ -1882,6 +1890,7 @@ export type BrowserTypeLaunchPersistentContextOptions = {
width: number,
height: number,
},
viewportMaximized?: boolean,
screen?: {
width: number,
height: number,
Expand Down
10 changes: 6 additions & 4 deletions packages/playwright-core/src/server/chromium/crPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import type * as types from '../types';
import type * as channels from '../channels';


export type WindowBounds = { top?: number, left?: number, width?: number, height?: number };
export type WindowBounds = { top?: number, left?: number, width?: number, height?: number, windowState?: Protocol.Browser.WindowState };

// Browsers disallow these WebUI hosts in off-the-record profiles and redirect them to the original
// profile, which crashes when the profile was created over CDP. Edge allows most of them in InPrivate.
Expand Down Expand Up @@ -465,9 +465,10 @@ class FrameSession {

async _initialize(hasUIWindow: boolean) {
const browserOptions = this._crPage._browserContext._browser.options;
const options = this._crPage._browserContext._options;
if (!this._page.isStorageStatePage && hasUIWindow &&
!this._crPage._browserContext._browser.isClank() &&
!this._crPage._browserContext._options.noDefaultViewport) {
(!options.noDefaultViewport || options.viewportMaximized)) {
try {
const { windowId } = await this._client.send('Browser.getWindowForTarget');
this._windowId = windowId;
Expand Down Expand Up @@ -546,13 +547,14 @@ class FrameSession {
promises.push(this.exposePlaywrightBinding());
if (this._isMainFrame() && !skipDefaultOverrides)
promises.push(this._client.send('Emulation.setFocusEmulationEnabled', { enabled: true }));
const options = this._crPage._browserContext._options;
if (options.bypassCSP)
promises.push(this._client.send('Page.setBypassCSP', { enabled: true }));
if (options.ignoreHTTPSErrors || options.internalIgnoreHTTPSErrors)
promises.push(this._client.send('Security.setIgnoreCertificateErrors', { ignore: true }));
if (this._isMainFrame())
promises.push(this._updateViewport());
if (this._windowId && options.viewportMaximized)
promises.push(this.setWindowBounds({ windowState: 'maximized' }));
if (options.hasTouch)
promises.push(this._client.send('Emulation.setTouchEmulationEnabled', { enabled: true }));
if (options.javaScriptEnabled === false)
Expand Down Expand Up @@ -985,7 +987,7 @@ class FrameSession {
if (JSON.stringify(this._metricsOverride) === JSON.stringify(metricsOverride))
return;
const promises = [];
if (!preserveWindowBoundaries && this._windowId) {
if (!preserveWindowBoundaries && this._windowId && !options.viewportMaximized) {
let insets = { width: 0, height: 0 };
if (this._crPage._browserContext._browser.options.headful) {
// TODO: popup windows have their own insets.
Expand Down
5 changes: 5 additions & 0 deletions packages/playwright-core/src/server/firefox/ffBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,11 @@ export class FFBrowserContext extends BrowserContext {
},
}));
}
if (this._options.viewportMaximized) {
promises.push(this._browser.session.send('Browser.setWindowMaximized', {
browserContextId,
}));
}
promises.push(this.doUpdateDefaultViewport());
if (this._options.hasTouch)
promises.push(this._browser.session.send('Browser.setTouchOverride', { browserContextId, hasTouch: true }));
Expand Down
Loading