From 12a555fc5c952a4c08cc440479bf8d54e350ab6b Mon Sep 17 00:00:00 2001 From: Jack Franklin Date: Mon, 15 Feb 2021 10:34:33 +0000 Subject: [PATCH] fix: improve TS types for launching browsers This commit tidies up the quite confusing state of all the various types required to launch a browser. As we saw when upgrading DevTools (https://source.chromium.org/chromium/chromium/src/+/master:third_party/devtools-frontend/src/test/conductor/hooks.ts;l=77), we had to define our launch options variable like so: ```ts const opts: puppeteer.LaunchOptions & puppeteer.ChromeArgOptions & puppeteer.BrowserOptions = { ... }; ``` This commit fixes that by introducing `AllNodeLaunchOptions`, which is defined as the intersection of all the above types. Additionally, the types defined as `ChromeArgOptions` are actually used for launching both Chrome and Firefox, so I have renamed them to `BrowserArgOptions`, and therefore this change is breaking because anyone using `ChromeArgOptions` in their types will need to switch. BREAKING CHANGE: renamed type `ChromeArgOptions` to `BrowserArgOptions` --- src/api-docs-entry.ts | 4 +- src/common/BrowserConnector.ts | 14 +++++- src/node/LaunchOptions.ts | 84 +++++++++++++++++++++++++++++++++- src/node/Launcher.ts | 25 +++------- src/node/Puppeteer.ts | 6 +-- 5 files changed, 106 insertions(+), 27 deletions(-) diff --git a/src/api-docs-entry.ts b/src/api-docs-entry.ts index 2fb85cef92c89..41a2d7f9ccc34 100644 --- a/src/api-docs-entry.ts +++ b/src/api-docs-entry.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { LaunchOptions, ChromeArgOptions } from './node/LaunchOptions.js'; +import { LaunchOptions, BrowserArgOptions } from './node/LaunchOptions.js'; import { BrowserOptions } from './common/BrowserConnector.js'; import { Product } from './common/Product.js'; import { Browser } from './common/Browser.js'; @@ -95,7 +95,7 @@ export * from 'devtools-protocol/types/protocol'; */ export declare function launch( options?: LaunchOptions & - ChromeArgOptions & + BrowserArgOptions & BrowserOptions & { product?: Product; extraPrefsFirefox?: Record; diff --git a/src/common/BrowserConnector.ts b/src/common/BrowserConnector.ts index 5da9cbc144284..8fdf39ad07d43 100644 --- a/src/common/BrowserConnector.ts +++ b/src/common/BrowserConnector.ts @@ -24,12 +24,24 @@ import { Viewport } from './PuppeteerViewport.js'; import { isNode } from '../environment.js'; /** - * Generic browser options that can be passed when launching any browser. + * Generic browser options that can be passed when launching any browser or when + * connecting to an existing browser instance. * @public */ export interface BrowserOptions { + /** + * Whether to ignore HTTPS errors during navigation. + * @defaultValue false + */ ignoreHTTPSErrors?: boolean; + /** + * Sets the viewport for each page. + */ defaultViewport?: Viewport; + /** + * Slows down Puppeteer operations by the specified amount of milliseconds to + * aid debugging. + */ slowMo?: number; } diff --git a/src/node/LaunchOptions.ts b/src/node/LaunchOptions.ts index 0eb99b69808d5..9fb5e96e1d9d0 100644 --- a/src/node/LaunchOptions.ts +++ b/src/node/LaunchOptions.ts @@ -13,16 +13,37 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +import { BrowserOptions } from '../common/BrowserConnector.js'; +import { Product } from '../common/Product.js'; + /** * Launcher options that only apply to Chrome. * * @public */ -export interface ChromeArgOptions { +export interface BrowserArgOptions { + /** + * Whether to run the browser in headless mode. + * @defaultValue true + */ headless?: boolean; - args?: string[]; + /** + * Path to a user data directory. + * {@link https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md | see the Chromium docs} + * for more info. + */ userDataDir?: string; + /** + * Whether to auto-open a DevTools panel for each tab. If this is set to + * `true`, then `headless` will be set to `false` automatically. + * @defaultValue `false` + */ devtools?: boolean; + /** + * Additional command line arguments to pass to the browser instance. + */ + args?: string[]; } /** @@ -30,13 +51,72 @@ export interface ChromeArgOptions { * @public */ export interface LaunchOptions { + /** + * Path to a browser executable to use instead of the bundled Chromium. Note + * that Puppeteer is only guaranteed to work with the bundled Chromium, so use + * this setting at your own risk. + */ executablePath?: string; + /** + * If `true`, do not use `puppeteer.defaultArgs()` when creating a browser. If + * an array is provided, these args will be filtered out. Use this with care - + * you probably want the default arguments Puppeteer uses. + * @defaultValue false + */ ignoreDefaultArgs?: boolean | string[]; + /** + * Close the browser process on `Ctrl+C`. + * @defaultValue `true` + */ handleSIGINT?: boolean; + /** + * Close the browser process on `SIGTERM`. + * @defaultValue `true` + */ handleSIGTERM?: boolean; + /** + * Close the browser process on `SIGHUP`. + * @defaultValue `true` + */ handleSIGHUP?: boolean; + /** + * Maximum time in milliseconds to wait for the browser to start. + * Pass `0` to disable the timeout. + * @defaultValue 30000 (30 seconds). + */ timeout?: number; + /** + * If true, pipes the browser process stdout and stderr to `process.stdout` + * and `process.stderr`. + * @defaultValue false + */ dumpio?: boolean; + /** + * Specify environment variables that will be visible to the browser. + * @defaultValue The contents of `process.env`. + */ env?: Record; + /** + * Connect to a browser over a pipe instead of a WebSocket. + * @defaultValue false + */ pipe?: boolean; + /** + * Which browser to launch. + * @defaultValue `chrome` + */ + product?: Product; + /** + * {@link https://developer.mozilla.org/en-US/docs/Mozilla/Preferences/Preference_reference | Additional preferences } that can be passed when launching with Firefox. + */ + extraPrefsFirefox?: Record; } + +/** + * Utility type exposed to enable users to define options that can be passed to + * `puppeteer.launch` without having to list the set of all types. + * @public + */ +export type AllNodeLaunchOptions = BrowserArgOptions & + LaunchOptions & + BrowserOptions; diff --git a/src/node/Launcher.ts b/src/node/Launcher.ts index bcfb28d5506a6..43502fb7613b8 100644 --- a/src/node/Launcher.ts +++ b/src/node/Launcher.ts @@ -25,8 +25,7 @@ import { promisify } from 'util'; const mkdtempAsync = promisify(fs.mkdtemp); const writeFileAsync = promisify(fs.writeFile); -import { ChromeArgOptions, LaunchOptions } from './LaunchOptions.js'; -import { BrowserOptions } from '../common/BrowserConnector.js'; +import { BrowserArgOptions, AllNodeLaunchOptions } from './LaunchOptions.js'; import { Product } from '../common/Product.js'; /** @@ -34,7 +33,7 @@ import { Product } from '../common/Product.js'; * @public */ export interface ProductLauncher { - launch(object); + launch(object: AllNodeLaunchOptions); executablePath: () => string; defaultArgs(object); product: Product; @@ -58,9 +57,7 @@ class ChromeLauncher implements ProductLauncher { this._isPuppeteerCore = isPuppeteerCore; } - async launch( - options: LaunchOptions & ChromeArgOptions & BrowserOptions = {} - ): Promise { + async launch(options: AllNodeLaunchOptions = {}): Promise { const { ignoreDefaultArgs = false, args = [], @@ -152,11 +149,7 @@ class ChromeLauncher implements ProductLauncher { } } - /** - * @param {!Launcher.ChromeArgOptions=} options - * @returns {!Array} - */ - defaultArgs(options: ChromeArgOptions = {}): string[] { + defaultArgs(options: BrowserArgOptions = {}): string[] { const chromeArguments = [ '--disable-background-networking', '--enable-features=NetworkService,NetworkServiceInProcess', @@ -230,13 +223,7 @@ class FirefoxLauncher implements ProductLauncher { this._isPuppeteerCore = isPuppeteerCore; } - async launch( - options: LaunchOptions & - ChromeArgOptions & - BrowserOptions & { - extraPrefsFirefox?: { [x: string]: unknown }; - } = {} - ): Promise { + async launch(options: AllNodeLaunchOptions = {}): Promise { const { ignoreDefaultArgs = false, args = [], @@ -346,7 +333,7 @@ class FirefoxLauncher implements ProductLauncher { return 'firefox'; } - defaultArgs(options: ChromeArgOptions = {}): string[] { + defaultArgs(options: BrowserArgOptions = {}): string[] { const firefoxArguments = ['--no-remote', '--foreground']; if (os.platform().startsWith('win')) { firefoxArguments.push('--wait-for-browser'); diff --git a/src/node/Puppeteer.ts b/src/node/Puppeteer.ts index 924d2fa96e958..ee6e27d7e1f5e 100644 --- a/src/node/Puppeteer.ts +++ b/src/node/Puppeteer.ts @@ -20,7 +20,7 @@ import { ConnectOptions, } from '../common/Puppeteer.js'; import { BrowserFetcher, BrowserFetcherOptions } from './BrowserFetcher.js'; -import { LaunchOptions, ChromeArgOptions } from './LaunchOptions.js'; +import { LaunchOptions, BrowserArgOptions } from './LaunchOptions.js'; import { BrowserOptions } from '../common/BrowserConnector.js'; import { Browser } from '../common/Browser.js'; import Launcher, { ProductLauncher } from './Launcher.js'; @@ -146,7 +146,7 @@ export class PuppeteerNode extends Puppeteer { */ launch( options: LaunchOptions & - ChromeArgOptions & + BrowserArgOptions & BrowserOptions & { product?: Product; extraPrefsFirefox?: Record; @@ -215,7 +215,7 @@ export class PuppeteerNode extends Puppeteer { * @param options - Set of configurable options to set on the browser. * @returns The default flags that Chromium will be launched with. */ - defaultArgs(options: ChromeArgOptions = {}): string[] { + defaultArgs(options: BrowserArgOptions = {}): string[] { return this._launcher.defaultArgs(options); }