mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
feat: add missing slowMo to launchPersistentContext (#1597)
`slowMo` was missing in `launchPersistentContext`, and I refactored the types a bit.
This commit is contained in:
parent
a853690c16
commit
6053784188
@ -3690,6 +3690,7 @@ const browser = await chromium.launch({ // Or 'firefox' or 'webkit'.
|
||||
- `dumpio` <[boolean]> Whether to pipe the browser process stdout and stderr into `process.stdout` and `process.stderr`. Defaults to `false`.
|
||||
- `env` <[Object]> Specify environment variables that will be visible to the browser. Defaults to `process.env`.
|
||||
- `devtools` <[boolean]> **Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the `headless` option will be set `false`.
|
||||
- `slowMo` <[number]> Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on. Defaults to 0.
|
||||
- returns: <[Promise]<[BrowserContext]>> Promise which resolves to the browser app instance.
|
||||
|
||||
Launches browser instance that uses persistent storage located at `userDataDir`.
|
||||
|
||||
@ -27,11 +27,6 @@ export interface Browser extends platform.EventEmitterType {
|
||||
_setDebugFunction(debugFunction: (message: string) => void): void;
|
||||
}
|
||||
|
||||
export type ConnectOptions = {
|
||||
slowMo?: number,
|
||||
wsEndpoint: string
|
||||
};
|
||||
|
||||
export async function createPageInNewContext(browser: Browser, options?: BrowserContextOptions): Promise<Page> {
|
||||
const context = await browser.newContext(options);
|
||||
const page = await context.newPage();
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ConnectOptions } from '../browser';
|
||||
import { BrowserContext } from '../browserContext';
|
||||
import { BrowserServer } from './browserServer';
|
||||
|
||||
@ -24,7 +23,7 @@ export type BrowserArgOptions = {
|
||||
devtools?: boolean,
|
||||
};
|
||||
|
||||
export type LaunchOptions = BrowserArgOptions & {
|
||||
type LaunchOptionsBase = BrowserArgOptions & {
|
||||
executablePath?: string,
|
||||
ignoreDefaultArgs?: boolean | string[],
|
||||
handleSIGINT?: boolean,
|
||||
@ -39,11 +38,17 @@ export type LaunchOptions = BrowserArgOptions & {
|
||||
env?: {[key: string]: string} | undefined
|
||||
};
|
||||
|
||||
export type ConnectOptions = {
|
||||
wsEndpoint: string,
|
||||
slowMo?: number
|
||||
};
|
||||
export type LaunchOptions = LaunchOptionsBase & { slowMo?: number };
|
||||
export type LaunchServerOptions = LaunchOptionsBase & { port?: number };
|
||||
export interface BrowserType<Browser> {
|
||||
executablePath(): string;
|
||||
name(): string;
|
||||
launch(options?: LaunchOptions & { slowMo?: number }): Promise<Browser>;
|
||||
launchServer(options?: LaunchOptions & { port?: number }): Promise<BrowserServer>;
|
||||
launch(options?: LaunchOptions): Promise<Browser>;
|
||||
launchServer(options?: LaunchServerOptions): Promise<BrowserServer>;
|
||||
launchPersistentContext(userDataDir: string, options?: LaunchOptions): Promise<BrowserContext>;
|
||||
connect(options: ConnectOptions): Promise<Browser>;
|
||||
}
|
||||
|
||||
@ -18,15 +18,15 @@
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { debugError, helper } from '../helper';
|
||||
import { debugError, helper, assert } from '../helper';
|
||||
import { CRBrowser } from '../chromium/crBrowser';
|
||||
import * as platform from '../platform';
|
||||
import * as ws from 'ws';
|
||||
import { launchProcess } from '../server/processLauncher';
|
||||
import { kBrowserCloseMessageId } from '../chromium/crConnection';
|
||||
import { PipeTransport } from './pipeTransport';
|
||||
import { LaunchOptions, BrowserArgOptions, BrowserType } from './browserType';
|
||||
import { ConnectOptions, LaunchType } from '../browser';
|
||||
import { LaunchOptions, BrowserArgOptions, BrowserType, ConnectOptions, LaunchServerOptions } from './browserType';
|
||||
import { LaunchType } from '../browser';
|
||||
import { BrowserServer, WebSocketWrapper } from './browserServer';
|
||||
import { Events } from '../events';
|
||||
import { ConnectionTransport, ProtocolRequest } from '../transport';
|
||||
@ -45,28 +45,30 @@ export class Chromium implements BrowserType<CRBrowser> {
|
||||
return 'chromium';
|
||||
}
|
||||
|
||||
async launch(options?: LaunchOptions & { slowMo?: number }): Promise<CRBrowser> {
|
||||
if (options && (options as any).userDataDir)
|
||||
throw new Error('userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
|
||||
async launch(options: LaunchOptions = {}): Promise<CRBrowser> {
|
||||
assert(!(options as any).userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
|
||||
const { browserServer, transport } = await this._launchServer(options, 'local');
|
||||
const browser = await CRBrowser.connect(transport!, false, options && options.slowMo);
|
||||
const browser = await CRBrowser.connect(transport!, false, options.slowMo);
|
||||
(browser as any)['__server__'] = browserServer;
|
||||
return browser;
|
||||
}
|
||||
|
||||
async launchServer(options?: LaunchOptions & { port?: number }): Promise<BrowserServer> {
|
||||
return (await this._launchServer(options, 'server', undefined, options && options.port)).browserServer;
|
||||
async launchServer(options: LaunchServerOptions = {}): Promise<BrowserServer> {
|
||||
return (await this._launchServer(options, 'server')).browserServer;
|
||||
}
|
||||
|
||||
async launchPersistentContext(userDataDir: string, options?: LaunchOptions): Promise<BrowserContext> {
|
||||
const { timeout = 30000 } = options || {};
|
||||
async launchPersistentContext(userDataDir: string, options: LaunchOptions = {}): Promise<BrowserContext> {
|
||||
const {
|
||||
timeout = 30000,
|
||||
slowMo = 0
|
||||
} = options;
|
||||
const { transport } = await this._launchServer(options, 'persistent', userDataDir);
|
||||
const browser = await CRBrowser.connect(transport!, true);
|
||||
const browser = await CRBrowser.connect(transport!, true, slowMo);
|
||||
await helper.waitWithTimeout(browser._firstPagePromise, 'first page', timeout);
|
||||
return browser._defaultContext;
|
||||
}
|
||||
|
||||
private async _launchServer(options: LaunchOptions = {}, launchType: LaunchType, userDataDir?: string, port?: number): Promise<{ browserServer: BrowserServer, transport?: ConnectionTransport }> {
|
||||
private async _launchServer(options: LaunchServerOptions, launchType: LaunchType, userDataDir?: string): Promise<{ browserServer: BrowserServer, transport?: ConnectionTransport }> {
|
||||
const {
|
||||
ignoreDefaultArgs = false,
|
||||
args = [],
|
||||
@ -76,7 +78,9 @@ export class Chromium implements BrowserType<CRBrowser> {
|
||||
handleSIGINT = true,
|
||||
handleSIGTERM = true,
|
||||
handleSIGHUP = true,
|
||||
port = 0,
|
||||
} = options;
|
||||
assert(!port || launchType === 'server', 'Cannot specify a port without launching as a server.');
|
||||
|
||||
let temporaryUserDataDir: string | null = null;
|
||||
if (!userDataDir) {
|
||||
@ -124,7 +128,7 @@ export class Chromium implements BrowserType<CRBrowser> {
|
||||
let transport: PipeTransport | undefined = undefined;
|
||||
let browserServer: BrowserServer | undefined = undefined;
|
||||
transport = new PipeTransport(launchedProcess.stdio[3] as NodeJS.WritableStream, launchedProcess.stdio[4] as NodeJS.ReadableStream, () => browserServer!.close());
|
||||
browserServer = new BrowserServer(launchedProcess, gracefullyClose, launchType === 'server' ? wrapTransportWithWebSocket(transport, port || 0) : null);
|
||||
browserServer = new BrowserServer(launchedProcess, gracefullyClose, launchType === 'server' ? wrapTransportWithWebSocket(transport, port) : null);
|
||||
return { browserServer, transport };
|
||||
}
|
||||
|
||||
|
||||
@ -19,16 +19,16 @@ import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as ws from 'ws';
|
||||
import { ConnectOptions, LaunchType } from '../browser';
|
||||
import { LaunchType } from '../browser';
|
||||
import { BrowserContext } from '../browserContext';
|
||||
import { TimeoutError } from '../errors';
|
||||
import { Events } from '../events';
|
||||
import { FFBrowser } from '../firefox/ffBrowser';
|
||||
import { kBrowserCloseMessageId } from '../firefox/ffConnection';
|
||||
import { debugError, helper } from '../helper';
|
||||
import { debugError, helper, assert } from '../helper';
|
||||
import * as platform from '../platform';
|
||||
import { BrowserServer, WebSocketWrapper } from './browserServer';
|
||||
import { BrowserArgOptions, BrowserType, LaunchOptions } from './browserType';
|
||||
import { BrowserArgOptions, BrowserType, LaunchOptions, LaunchServerOptions, ConnectOptions } from './browserType';
|
||||
import { launchProcess, waitForLine } from './processLauncher';
|
||||
import { ConnectionTransport, SequenceNumberMixer } from '../transport';
|
||||
|
||||
@ -47,12 +47,11 @@ export class Firefox implements BrowserType<FFBrowser> {
|
||||
return 'firefox';
|
||||
}
|
||||
|
||||
async launch(options?: LaunchOptions & { slowMo?: number }): Promise<FFBrowser> {
|
||||
if (options && (options as any).userDataDir)
|
||||
throw new Error('userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
|
||||
async launch(options: LaunchOptions = {}): Promise<FFBrowser> {
|
||||
assert(!(options as any).userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
|
||||
const browserServer = await this._launchServer(options, 'local');
|
||||
const browser = await platform.connectToWebsocket(browserServer.wsEndpoint()!, transport => {
|
||||
return FFBrowser.connect(transport, false, options && options.slowMo);
|
||||
return FFBrowser.connect(transport, false, options.slowMo);
|
||||
});
|
||||
// Hack: for typical launch scenario, ensure that close waits for actual process termination.
|
||||
browser.close = () => browserServer.close();
|
||||
@ -60,15 +59,18 @@ export class Firefox implements BrowserType<FFBrowser> {
|
||||
return browser;
|
||||
}
|
||||
|
||||
async launchServer(options?: LaunchOptions & { port?: number }): Promise<BrowserServer> {
|
||||
return await this._launchServer(options, 'server', undefined, options && options.port);
|
||||
async launchServer(options: LaunchServerOptions = {}): Promise<BrowserServer> {
|
||||
return await this._launchServer(options, 'server');
|
||||
}
|
||||
|
||||
async launchPersistentContext(userDataDir: string, options?: LaunchOptions): Promise<BrowserContext> {
|
||||
const { timeout = 30000 } = options || {};
|
||||
async launchPersistentContext(userDataDir: string, options: LaunchOptions = {}): Promise<BrowserContext> {
|
||||
const {
|
||||
timeout = 30000,
|
||||
slowMo = 0,
|
||||
} = options;
|
||||
const browserServer = await this._launchServer(options, 'persistent', userDataDir);
|
||||
const browser = await platform.connectToWebsocket(browserServer.wsEndpoint()!, transport => {
|
||||
return FFBrowser.connect(transport, true);
|
||||
return FFBrowser.connect(transport, true, slowMo);
|
||||
});
|
||||
await helper.waitWithTimeout(browser._firstPagePromise, 'first page', timeout);
|
||||
// Hack: for typical launch scenario, ensure that close waits for actual process termination.
|
||||
@ -77,7 +79,7 @@ export class Firefox implements BrowserType<FFBrowser> {
|
||||
return browserContext;
|
||||
}
|
||||
|
||||
private async _launchServer(options: LaunchOptions = {}, launchType: LaunchType, userDataDir?: string, port?: number): Promise<BrowserServer> {
|
||||
private async _launchServer(options: LaunchServerOptions, launchType: LaunchType, userDataDir?: string): Promise<BrowserServer> {
|
||||
const {
|
||||
ignoreDefaultArgs = false,
|
||||
args = [],
|
||||
@ -88,7 +90,9 @@ export class Firefox implements BrowserType<FFBrowser> {
|
||||
handleSIGINT = true,
|
||||
handleSIGTERM = true,
|
||||
timeout = 30000,
|
||||
port = 0,
|
||||
} = options;
|
||||
assert(!port || launchType === 'server', 'Cannot specify a port without launching as a server.');
|
||||
|
||||
const firefoxArguments = [];
|
||||
|
||||
@ -145,7 +149,7 @@ export class Firefox implements BrowserType<FFBrowser> {
|
||||
|
||||
let browserServer: BrowserServer | undefined = undefined;
|
||||
let browserWSEndpoint: string | undefined = undefined;
|
||||
const webSocketWrapper = launchType === 'server' ? (await platform.connectToWebsocket(innerEndpoint, t => wrapTransportWithWebSocket(t, port || 0))) : new WebSocketWrapper(innerEndpoint, []);
|
||||
const webSocketWrapper = launchType === 'server' ? (await platform.connectToWebsocket(innerEndpoint, t => wrapTransportWithWebSocket(t, port))) : new WebSocketWrapper(innerEndpoint, []);
|
||||
browserWSEndpoint = webSocketWrapper.wsEndpoint;
|
||||
browserServer = new BrowserServer(launchedProcess, gracefullyClose, webSocketWrapper);
|
||||
return browserServer;
|
||||
|
||||
@ -22,12 +22,12 @@ import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as platform from '../platform';
|
||||
import * as os from 'os';
|
||||
import { debugError, helper } from '../helper';
|
||||
import { debugError, helper, assert } from '../helper';
|
||||
import { kBrowserCloseMessageId } from '../webkit/wkConnection';
|
||||
import { LaunchOptions, BrowserArgOptions, BrowserType } from './browserType';
|
||||
import { LaunchOptions, BrowserArgOptions, BrowserType, LaunchServerOptions, ConnectOptions } from './browserType';
|
||||
import { ConnectionTransport, SequenceNumberMixer } from '../transport';
|
||||
import * as ws from 'ws';
|
||||
import { ConnectOptions, LaunchType } from '../browser';
|
||||
import { LaunchType } from '../browser';
|
||||
import { BrowserServer, WebSocketWrapper } from './browserServer';
|
||||
import { Events } from '../events';
|
||||
import { BrowserContext } from '../browserContext';
|
||||
@ -45,28 +45,30 @@ export class WebKit implements BrowserType<WKBrowser> {
|
||||
return 'webkit';
|
||||
}
|
||||
|
||||
async launch(options?: LaunchOptions & { slowMo?: number }): Promise<WKBrowser> {
|
||||
if (options && (options as any).userDataDir)
|
||||
throw new Error('userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
|
||||
async launch(options: LaunchOptions = {}): Promise<WKBrowser> {
|
||||
assert(!(options as any).userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
|
||||
const { browserServer, transport } = await this._launchServer(options, 'local');
|
||||
const browser = await WKBrowser.connect(transport!, options && options.slowMo);
|
||||
const browser = await WKBrowser.connect(transport!, options.slowMo);
|
||||
(browser as any)['__server__'] = browserServer;
|
||||
return browser;
|
||||
}
|
||||
|
||||
async launchServer(options?: LaunchOptions & { port?: number }): Promise<BrowserServer> {
|
||||
return (await this._launchServer(options, 'server', undefined, options && options.port)).browserServer;
|
||||
async launchServer(options: LaunchServerOptions = {}): Promise<BrowserServer> {
|
||||
return (await this._launchServer(options, 'server')).browserServer;
|
||||
}
|
||||
|
||||
async launchPersistentContext(userDataDir: string, options?: LaunchOptions): Promise<BrowserContext> {
|
||||
const { timeout = 30000 } = options || {};
|
||||
async launchPersistentContext(userDataDir: string, options: LaunchOptions = {}): Promise<BrowserContext> {
|
||||
const {
|
||||
timeout = 30000,
|
||||
slowMo = 0,
|
||||
} = options;
|
||||
const { transport } = await this._launchServer(options, 'persistent', userDataDir);
|
||||
const browser = await WKBrowser.connect(transport!, undefined, true);
|
||||
const browser = await WKBrowser.connect(transport!, slowMo, true);
|
||||
await helper.waitWithTimeout(browser._waitForFirstPageTarget(), 'first page', timeout);
|
||||
return browser._defaultContext;
|
||||
}
|
||||
|
||||
private async _launchServer(options: LaunchOptions = {}, launchType: LaunchType, userDataDir?: string, port?: number): Promise<{ browserServer: BrowserServer, transport?: ConnectionTransport }> {
|
||||
private async _launchServer(options: LaunchServerOptions, launchType: LaunchType, userDataDir?: string): Promise<{ browserServer: BrowserServer, transport?: ConnectionTransport }> {
|
||||
const {
|
||||
ignoreDefaultArgs = false,
|
||||
args = [],
|
||||
@ -76,7 +78,9 @@ export class WebKit implements BrowserType<WKBrowser> {
|
||||
handleSIGINT = true,
|
||||
handleSIGTERM = true,
|
||||
handleSIGHUP = true,
|
||||
port = 0,
|
||||
} = options;
|
||||
assert(!port || launchType === 'server', 'Cannot specify a port without launching as a server.');
|
||||
|
||||
let temporaryUserDataDir: string | null = null;
|
||||
if (!userDataDir) {
|
||||
@ -86,9 +90,9 @@ export class WebKit implements BrowserType<WKBrowser> {
|
||||
|
||||
const webkitArguments = [];
|
||||
if (!ignoreDefaultArgs)
|
||||
webkitArguments.push(...this._defaultArgs(options, launchType, userDataDir!, port || 0));
|
||||
webkitArguments.push(...this._defaultArgs(options, launchType, userDataDir!, port));
|
||||
else if (Array.isArray(ignoreDefaultArgs))
|
||||
webkitArguments.push(...this._defaultArgs(options, launchType, userDataDir!, port || 0).filter(arg => ignoreDefaultArgs.indexOf(arg) === -1));
|
||||
webkitArguments.push(...this._defaultArgs(options, launchType, userDataDir!, port).filter(arg => ignoreDefaultArgs.indexOf(arg) === -1));
|
||||
else
|
||||
webkitArguments.push(...args);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user