Skip to content

Commit 6053784

Browse files
feat: add missing slowMo to launchPersistentContext (#1597)
`slowMo` was missing in `launchPersistentContext`, and I refactored the types a bit.
1 parent a853690 commit 6053784

File tree

6 files changed

+65
-52
lines changed

6 files changed

+65
-52
lines changed

docs/api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3690,6 +3690,7 @@ const browser = await chromium.launch({ // Or 'firefox' or 'webkit'.
36903690
- `dumpio` <[boolean]> Whether to pipe the browser process stdout and stderr into `process.stdout` and `process.stderr`. Defaults to `false`.
36913691
- `env` <[Object]> Specify environment variables that will be visible to the browser. Defaults to `process.env`.
36923692
- `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`.
3693+
- `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.
36933694
- returns: <[Promise]<[BrowserContext]>> Promise which resolves to the browser app instance.
36943695

36953696
Launches browser instance that uses persistent storage located at `userDataDir`.

src/browser.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,6 @@ export interface Browser extends platform.EventEmitterType {
2727
_setDebugFunction(debugFunction: (message: string) => void): void;
2828
}
2929

30-
export type ConnectOptions = {
31-
slowMo?: number,
32-
wsEndpoint: string
33-
};
34-
3530
export async function createPageInNewContext(browser: Browser, options?: BrowserContextOptions): Promise<Page> {
3631
const context = await browser.newContext(options);
3732
const page = await context.newPage();

src/server/browserType.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { ConnectOptions } from '../browser';
1817
import { BrowserContext } from '../browserContext';
1918
import { BrowserServer } from './browserServer';
2019

@@ -24,7 +23,7 @@ export type BrowserArgOptions = {
2423
devtools?: boolean,
2524
};
2625

27-
export type LaunchOptions = BrowserArgOptions & {
26+
type LaunchOptionsBase = BrowserArgOptions & {
2827
executablePath?: string,
2928
ignoreDefaultArgs?: boolean | string[],
3029
handleSIGINT?: boolean,
@@ -39,11 +38,17 @@ export type LaunchOptions = BrowserArgOptions & {
3938
env?: {[key: string]: string} | undefined
4039
};
4140

41+
export type ConnectOptions = {
42+
wsEndpoint: string,
43+
slowMo?: number
44+
};
45+
export type LaunchOptions = LaunchOptionsBase & { slowMo?: number };
46+
export type LaunchServerOptions = LaunchOptionsBase & { port?: number };
4247
export interface BrowserType<Browser> {
4348
executablePath(): string;
4449
name(): string;
45-
launch(options?: LaunchOptions & { slowMo?: number }): Promise<Browser>;
46-
launchServer(options?: LaunchOptions & { port?: number }): Promise<BrowserServer>;
50+
launch(options?: LaunchOptions): Promise<Browser>;
51+
launchServer(options?: LaunchServerOptions): Promise<BrowserServer>;
4752
launchPersistentContext(userDataDir: string, options?: LaunchOptions): Promise<BrowserContext>;
4853
connect(options: ConnectOptions): Promise<Browser>;
4954
}

src/server/chromium.ts

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@
1818
import * as fs from 'fs';
1919
import * as os from 'os';
2020
import * as path from 'path';
21-
import { debugError, helper } from '../helper';
21+
import { debugError, helper, assert } from '../helper';
2222
import { CRBrowser } from '../chromium/crBrowser';
2323
import * as platform from '../platform';
2424
import * as ws from 'ws';
2525
import { launchProcess } from '../server/processLauncher';
2626
import { kBrowserCloseMessageId } from '../chromium/crConnection';
2727
import { PipeTransport } from './pipeTransport';
28-
import { LaunchOptions, BrowserArgOptions, BrowserType } from './browserType';
29-
import { ConnectOptions, LaunchType } from '../browser';
28+
import { LaunchOptions, BrowserArgOptions, BrowserType, ConnectOptions, LaunchServerOptions } from './browserType';
29+
import { LaunchType } from '../browser';
3030
import { BrowserServer, WebSocketWrapper } from './browserServer';
3131
import { Events } from '../events';
3232
import { ConnectionTransport, ProtocolRequest } from '../transport';
@@ -45,28 +45,30 @@ export class Chromium implements BrowserType<CRBrowser> {
4545
return 'chromium';
4646
}
4747

48-
async launch(options?: LaunchOptions & { slowMo?: number }): Promise<CRBrowser> {
49-
if (options && (options as any).userDataDir)
50-
throw new Error('userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
48+
async launch(options: LaunchOptions = {}): Promise<CRBrowser> {
49+
assert(!(options as any).userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
5150
const { browserServer, transport } = await this._launchServer(options, 'local');
52-
const browser = await CRBrowser.connect(transport!, false, options && options.slowMo);
51+
const browser = await CRBrowser.connect(transport!, false, options.slowMo);
5352
(browser as any)['__server__'] = browserServer;
5453
return browser;
5554
}
5655

57-
async launchServer(options?: LaunchOptions & { port?: number }): Promise<BrowserServer> {
58-
return (await this._launchServer(options, 'server', undefined, options && options.port)).browserServer;
56+
async launchServer(options: LaunchServerOptions = {}): Promise<BrowserServer> {
57+
return (await this._launchServer(options, 'server')).browserServer;
5958
}
6059

61-
async launchPersistentContext(userDataDir: string, options?: LaunchOptions): Promise<BrowserContext> {
62-
const { timeout = 30000 } = options || {};
60+
async launchPersistentContext(userDataDir: string, options: LaunchOptions = {}): Promise<BrowserContext> {
61+
const {
62+
timeout = 30000,
63+
slowMo = 0
64+
} = options;
6365
const { transport } = await this._launchServer(options, 'persistent', userDataDir);
64-
const browser = await CRBrowser.connect(transport!, true);
66+
const browser = await CRBrowser.connect(transport!, true, slowMo);
6567
await helper.waitWithTimeout(browser._firstPagePromise, 'first page', timeout);
6668
return browser._defaultContext;
6769
}
6870

69-
private async _launchServer(options: LaunchOptions = {}, launchType: LaunchType, userDataDir?: string, port?: number): Promise<{ browserServer: BrowserServer, transport?: ConnectionTransport }> {
71+
private async _launchServer(options: LaunchServerOptions, launchType: LaunchType, userDataDir?: string): Promise<{ browserServer: BrowserServer, transport?: ConnectionTransport }> {
7072
const {
7173
ignoreDefaultArgs = false,
7274
args = [],
@@ -76,7 +78,9 @@ export class Chromium implements BrowserType<CRBrowser> {
7678
handleSIGINT = true,
7779
handleSIGTERM = true,
7880
handleSIGHUP = true,
81+
port = 0,
7982
} = options;
83+
assert(!port || launchType === 'server', 'Cannot specify a port without launching as a server.');
8084

8185
let temporaryUserDataDir: string | null = null;
8286
if (!userDataDir) {
@@ -124,7 +128,7 @@ export class Chromium implements BrowserType<CRBrowser> {
124128
let transport: PipeTransport | undefined = undefined;
125129
let browserServer: BrowserServer | undefined = undefined;
126130
transport = new PipeTransport(launchedProcess.stdio[3] as NodeJS.WritableStream, launchedProcess.stdio[4] as NodeJS.ReadableStream, () => browserServer!.close());
127-
browserServer = new BrowserServer(launchedProcess, gracefullyClose, launchType === 'server' ? wrapTransportWithWebSocket(transport, port || 0) : null);
131+
browserServer = new BrowserServer(launchedProcess, gracefullyClose, launchType === 'server' ? wrapTransportWithWebSocket(transport, port) : null);
128132
return { browserServer, transport };
129133
}
130134

src/server/firefox.ts

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,16 @@ import * as fs from 'fs';
1919
import * as os from 'os';
2020
import * as path from 'path';
2121
import * as ws from 'ws';
22-
import { ConnectOptions, LaunchType } from '../browser';
22+
import { LaunchType } from '../browser';
2323
import { BrowserContext } from '../browserContext';
2424
import { TimeoutError } from '../errors';
2525
import { Events } from '../events';
2626
import { FFBrowser } from '../firefox/ffBrowser';
2727
import { kBrowserCloseMessageId } from '../firefox/ffConnection';
28-
import { debugError, helper } from '../helper';
28+
import { debugError, helper, assert } from '../helper';
2929
import * as platform from '../platform';
3030
import { BrowserServer, WebSocketWrapper } from './browserServer';
31-
import { BrowserArgOptions, BrowserType, LaunchOptions } from './browserType';
31+
import { BrowserArgOptions, BrowserType, LaunchOptions, LaunchServerOptions, ConnectOptions } from './browserType';
3232
import { launchProcess, waitForLine } from './processLauncher';
3333
import { ConnectionTransport, SequenceNumberMixer } from '../transport';
3434

@@ -47,28 +47,30 @@ export class Firefox implements BrowserType<FFBrowser> {
4747
return 'firefox';
4848
}
4949

50-
async launch(options?: LaunchOptions & { slowMo?: number }): Promise<FFBrowser> {
51-
if (options && (options as any).userDataDir)
52-
throw new Error('userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
50+
async launch(options: LaunchOptions = {}): Promise<FFBrowser> {
51+
assert(!(options as any).userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
5352
const browserServer = await this._launchServer(options, 'local');
5453
const browser = await platform.connectToWebsocket(browserServer.wsEndpoint()!, transport => {
55-
return FFBrowser.connect(transport, false, options && options.slowMo);
54+
return FFBrowser.connect(transport, false, options.slowMo);
5655
});
5756
// Hack: for typical launch scenario, ensure that close waits for actual process termination.
5857
browser.close = () => browserServer.close();
5958
(browser as any)['__server__'] = browserServer;
6059
return browser;
6160
}
6261

63-
async launchServer(options?: LaunchOptions & { port?: number }): Promise<BrowserServer> {
64-
return await this._launchServer(options, 'server', undefined, options && options.port);
62+
async launchServer(options: LaunchServerOptions = {}): Promise<BrowserServer> {
63+
return await this._launchServer(options, 'server');
6564
}
6665

67-
async launchPersistentContext(userDataDir: string, options?: LaunchOptions): Promise<BrowserContext> {
68-
const { timeout = 30000 } = options || {};
66+
async launchPersistentContext(userDataDir: string, options: LaunchOptions = {}): Promise<BrowserContext> {
67+
const {
68+
timeout = 30000,
69+
slowMo = 0,
70+
} = options;
6971
const browserServer = await this._launchServer(options, 'persistent', userDataDir);
7072
const browser = await platform.connectToWebsocket(browserServer.wsEndpoint()!, transport => {
71-
return FFBrowser.connect(transport, true);
73+
return FFBrowser.connect(transport, true, slowMo);
7274
});
7375
await helper.waitWithTimeout(browser._firstPagePromise, 'first page', timeout);
7476
// Hack: for typical launch scenario, ensure that close waits for actual process termination.
@@ -77,7 +79,7 @@ export class Firefox implements BrowserType<FFBrowser> {
7779
return browserContext;
7880
}
7981

80-
private async _launchServer(options: LaunchOptions = {}, launchType: LaunchType, userDataDir?: string, port?: number): Promise<BrowserServer> {
82+
private async _launchServer(options: LaunchServerOptions, launchType: LaunchType, userDataDir?: string): Promise<BrowserServer> {
8183
const {
8284
ignoreDefaultArgs = false,
8385
args = [],
@@ -88,7 +90,9 @@ export class Firefox implements BrowserType<FFBrowser> {
8890
handleSIGINT = true,
8991
handleSIGTERM = true,
9092
timeout = 30000,
93+
port = 0,
9194
} = options;
95+
assert(!port || launchType === 'server', 'Cannot specify a port without launching as a server.');
9296

9397
const firefoxArguments = [];
9498

@@ -145,7 +149,7 @@ export class Firefox implements BrowserType<FFBrowser> {
145149

146150
let browserServer: BrowserServer | undefined = undefined;
147151
let browserWSEndpoint: string | undefined = undefined;
148-
const webSocketWrapper = launchType === 'server' ? (await platform.connectToWebsocket(innerEndpoint, t => wrapTransportWithWebSocket(t, port || 0))) : new WebSocketWrapper(innerEndpoint, []);
152+
const webSocketWrapper = launchType === 'server' ? (await platform.connectToWebsocket(innerEndpoint, t => wrapTransportWithWebSocket(t, port))) : new WebSocketWrapper(innerEndpoint, []);
149153
browserWSEndpoint = webSocketWrapper.wsEndpoint;
150154
browserServer = new BrowserServer(launchedProcess, gracefullyClose, webSocketWrapper);
151155
return browserServer;

src/server/webkit.ts

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ import * as fs from 'fs';
2222
import * as path from 'path';
2323
import * as platform from '../platform';
2424
import * as os from 'os';
25-
import { debugError, helper } from '../helper';
25+
import { debugError, helper, assert } from '../helper';
2626
import { kBrowserCloseMessageId } from '../webkit/wkConnection';
27-
import { LaunchOptions, BrowserArgOptions, BrowserType } from './browserType';
27+
import { LaunchOptions, BrowserArgOptions, BrowserType, LaunchServerOptions, ConnectOptions } from './browserType';
2828
import { ConnectionTransport, SequenceNumberMixer } from '../transport';
2929
import * as ws from 'ws';
30-
import { ConnectOptions, LaunchType } from '../browser';
30+
import { LaunchType } from '../browser';
3131
import { BrowserServer, WebSocketWrapper } from './browserServer';
3232
import { Events } from '../events';
3333
import { BrowserContext } from '../browserContext';
@@ -45,28 +45,30 @@ export class WebKit implements BrowserType<WKBrowser> {
4545
return 'webkit';
4646
}
4747

48-
async launch(options?: LaunchOptions & { slowMo?: number }): Promise<WKBrowser> {
49-
if (options && (options as any).userDataDir)
50-
throw new Error('userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
48+
async launch(options: LaunchOptions = {}): Promise<WKBrowser> {
49+
assert(!(options as any).userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
5150
const { browserServer, transport } = await this._launchServer(options, 'local');
52-
const browser = await WKBrowser.connect(transport!, options && options.slowMo);
51+
const browser = await WKBrowser.connect(transport!, options.slowMo);
5352
(browser as any)['__server__'] = browserServer;
5453
return browser;
5554
}
5655

57-
async launchServer(options?: LaunchOptions & { port?: number }): Promise<BrowserServer> {
58-
return (await this._launchServer(options, 'server', undefined, options && options.port)).browserServer;
56+
async launchServer(options: LaunchServerOptions = {}): Promise<BrowserServer> {
57+
return (await this._launchServer(options, 'server')).browserServer;
5958
}
6059

61-
async launchPersistentContext(userDataDir: string, options?: LaunchOptions): Promise<BrowserContext> {
62-
const { timeout = 30000 } = options || {};
60+
async launchPersistentContext(userDataDir: string, options: LaunchOptions = {}): Promise<BrowserContext> {
61+
const {
62+
timeout = 30000,
63+
slowMo = 0,
64+
} = options;
6365
const { transport } = await this._launchServer(options, 'persistent', userDataDir);
64-
const browser = await WKBrowser.connect(transport!, undefined, true);
66+
const browser = await WKBrowser.connect(transport!, slowMo, true);
6567
await helper.waitWithTimeout(browser._waitForFirstPageTarget(), 'first page', timeout);
6668
return browser._defaultContext;
6769
}
6870

69-
private async _launchServer(options: LaunchOptions = {}, launchType: LaunchType, userDataDir?: string, port?: number): Promise<{ browserServer: BrowserServer, transport?: ConnectionTransport }> {
71+
private async _launchServer(options: LaunchServerOptions, launchType: LaunchType, userDataDir?: string): Promise<{ browserServer: BrowserServer, transport?: ConnectionTransport }> {
7072
const {
7173
ignoreDefaultArgs = false,
7274
args = [],
@@ -76,7 +78,9 @@ export class WebKit implements BrowserType<WKBrowser> {
7678
handleSIGINT = true,
7779
handleSIGTERM = true,
7880
handleSIGHUP = true,
81+
port = 0,
7982
} = options;
83+
assert(!port || launchType === 'server', 'Cannot specify a port without launching as a server.');
8084

8185
let temporaryUserDataDir: string | null = null;
8286
if (!userDataDir) {
@@ -86,9 +90,9 @@ export class WebKit implements BrowserType<WKBrowser> {
8690

8791
const webkitArguments = [];
8892
if (!ignoreDefaultArgs)
89-
webkitArguments.push(...this._defaultArgs(options, launchType, userDataDir!, port || 0));
93+
webkitArguments.push(...this._defaultArgs(options, launchType, userDataDir!, port));
9094
else if (Array.isArray(ignoreDefaultArgs))
91-
webkitArguments.push(...this._defaultArgs(options, launchType, userDataDir!, port || 0).filter(arg => ignoreDefaultArgs.indexOf(arg) === -1));
95+
webkitArguments.push(...this._defaultArgs(options, launchType, userDataDir!, port).filter(arg => ignoreDefaultArgs.indexOf(arg) === -1));
9296
else
9397
webkitArguments.push(...args);
9498

0 commit comments

Comments
 (0)