Skip to content

Commit

Permalink
feat: add missing slowMo to launchPersistentContext
Browse files Browse the repository at this point in the history
  • Loading branch information
JoelEinbinder committed Mar 31, 2020
1 parent a2e1d4c commit a60979b
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 49 deletions.
1 change: 1 addition & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -3688,6 +3688,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`.
Expand Down
5 changes: 0 additions & 5 deletions src/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
17 changes: 13 additions & 4 deletions src/server/browserType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
* limitations under the License.
*/

import { ConnectOptions } from '../browser';
import { BrowserContext } from '../browserContext';
import { BrowserServer } from './browserServer';

Expand All @@ -24,7 +23,7 @@ export type BrowserArgOptions = {
devtools?: boolean,
};

export type LaunchOptions = BrowserArgOptions & {
export type ProcessOptions = BrowserArgOptions & {
executablePath?: string,
ignoreDefaultArgs?: boolean | string[],
handleSIGINT?: boolean,
Expand All @@ -39,11 +38,21 @@ export type LaunchOptions = BrowserArgOptions & {
env?: {[key: string]: string} | undefined
};

export type ConnectOptions = {
wsEndpoint: string
} & BrowserOptions;

type BrowserOptions = {
slowMo?: number,
}

export type LaunchOptions = ProcessOptions & BrowserOptions;
export type ServerOptions = ProcessOptions & { 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?: ServerOptions): Promise<BrowserServer>;
launchPersistentContext(userDataDir: string, options?: LaunchOptions): Promise<BrowserContext>;
connect(options: ConnectOptions): Promise<Browser>;
}
28 changes: 15 additions & 13 deletions src/server/chromium.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, ProcessOptions, ConnectOptions, ServerOptions } from './browserType';
import { LaunchType } from '../browser';
import { BrowserServer, WebSocketWrapper } from './browserServer';
import { Events } from '../events';
import { ConnectionTransport, ProtocolRequest } from '../transport';
Expand All @@ -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: ServerOptions = {}): Promise<BrowserServer> {
return (await this._launchServer(options, 'server', undefined, options.port)).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 = undefined
} = 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: ProcessOptions, launchType: LaunchType, userDataDir?: string, port?: number): Promise<{ browserServer: BrowserServer, transport?: ConnectionTransport }> {
const {
ignoreDefaultArgs = false,
args = [],
Expand Down
28 changes: 15 additions & 13 deletions src/server/firefox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, ServerOptions, ProcessOptions, ConnectOptions } from './browserType';
import { launchProcess, waitForLine } from './processLauncher';
import { ConnectionTransport, SequenceNumberMixer } from '../transport';

Expand All @@ -47,28 +47,30 @@ 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();
(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);
async launchServer(options: ServerOptions = {}): Promise<BrowserServer> {
return await this._launchServer(options, 'server', undefined, options.port);
}

async launchPersistentContext(userDataDir: string, options?: LaunchOptions): Promise<BrowserContext> {
const { timeout = 30000 } = options || {};
async launchPersistentContext(userDataDir: string, options: LaunchOptions = {}): Promise<BrowserContext> {
const {
timeout = 30000,
slowMo = undefined,
} = 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.
Expand All @@ -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: ProcessOptions, launchType: LaunchType, userDataDir?: string, port?: number): Promise<BrowserServer> {
const {
ignoreDefaultArgs = false,
args = [],
Expand Down
28 changes: 15 additions & 13 deletions src/server/webkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, ProcessOptions, ServerOptions, 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';
Expand All @@ -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: ServerOptions = {}): Promise<BrowserServer> {
return (await this._launchServer(options, 'server', undefined, options.port)).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 = undefined,
} = 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: ProcessOptions, launchType: LaunchType, userDataDir?: string, port?: number): Promise<{ browserServer: BrowserServer, transport?: ConnectionTransport }> {
const {
ignoreDefaultArgs = false,
args = [],
Expand Down
2 changes: 1 addition & 1 deletion test/launcher.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
await neverResolves;
expect(error.message).toContain('Protocol error');
});
it('should throw if userDataDir option is passed', async() => {
fit('should throw if userDataDir option is passed', async() => {
let waitError = null;
const options = Object.assign({}, defaultBrowserOptions, {userDataDir: 'random-path'});
await browserType.launch(options).catch(e => waitError = e);
Expand Down

0 comments on commit a60979b

Please sign in to comment.