From 78b25d83ea48d07ea786ccb1888d2f61f62e1768 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Fri, 24 Jan 2020 14:33:21 -0800 Subject: [PATCH] Rename engine -> browserType. --- README.md | 28 +-- docs/api.md | 240 +++++++++++++------- docs/web.md | 2 +- download-browser.js | 6 +- index.d.ts | 8 +- index.js | 18 +- prepare.js | 3 +- src/api.ts | 2 +- src/server/browserType.ts | 50 ++++ src/server/{crPlaywright.ts => chromium.ts} | 4 +- src/server/{ffPlaywright.ts => firefox.ts} | 4 +- src/server/playwright.ts | 46 ++-- src/server/{wkPlaywright.ts => webkit.ts} | 4 +- 13 files changed, 269 insertions(+), 146 deletions(-) create mode 100644 src/server/browserType.ts rename src/server/{crPlaywright.ts => chromium.ts} (98%) rename src/server/{ffPlaywright.ts => firefox.ts} (99%) rename src/server/{wkPlaywright.ts => webkit.ts} (98%) diff --git a/README.md b/README.md index 452575af68..f759cbd139 100644 --- a/README.md +++ b/README.md @@ -39,15 +39,15 @@ Playwright can be used to create a browser instance, open pages, and then manipu This code snippet navigates to whatsmyuseragent.org in Chromium, Firefox and WebKit, and saves 3 screenshots. ```js -const pw = require('playwright'); +const playwright = require('playwright'); (async () => { - for (const name of ['chromium', 'firefox', 'webkit']) { - const browser = await pw[name].launch(); + for (const browserType of ['chromium', 'firefox', 'webkit']) { + const browser = await playwright[browserType].launch(); const context = await browser.newContext(); const page = await context.newPage('http://whatsmyuseragent.org/'); - - await page.screenshot({ path: `example-${name}.png` }); + + await page.screenshot({ path: `example-${browserType}.png` }); await browser.close(); } })(); @@ -58,11 +58,11 @@ const pw = require('playwright'); This snippet emulates Mobile Safari on a device at a given geolocation, navigates to maps.google.com, performs action and takes a screenshot. ```js -const pw = require('playwright'); -const iPhone11 = pw.devices['iPhone 11 Pro']; +const { webkit, devices } = require('playwright'); +const iPhone11 = devices['iPhone 11 Pro']; (async () => { - const browser = await pw.webkit.launch(); + const browser = await webkit.launch(); const context = await browser.newContext({ viewport: iPhone11.viewport, userAgent: iPhone11.userAgent, @@ -73,7 +73,7 @@ const iPhone11 = pw.devices['iPhone 11 Pro']; const page = await context.newPage('https://maps.google.com'); await page.click('text="Your location"'); await page.waitForRequest(/.*preview\/pwa/); - await page.screenshot({ path: 'colosseum-iphone.png' }); + await page.screenshot({ path: 'colosseum-iphone.png' }); await browser.close(); })(); ``` @@ -81,11 +81,11 @@ const iPhone11 = pw.devices['iPhone 11 Pro']; And here is the same script for Chrome on Android. ```js -const pw = require('playwright'); -const pixel2 = pw.devices['Pixel 2']; +const { chromium, devices } = require('playwright'); +const pixel2 = devices['Pixel 2']; (async () => { - const browser = await pw.chromium.launch(); + const browser = await chromium.launch(); const context = await browser.newContext({ viewport: pixel2.viewport, userAgent: pixel2.userAgent, @@ -106,10 +106,10 @@ const pixel2 = pw.devices['Pixel 2']; This code snippet navigates to example.com in Firefox, and executes a script in the page context. ```js -const pw = require('playwright'); +const { firefox } = require('playwright'); (async () => { - const browser = await pw.firefox.launch(); // or 'chromium', 'webkit' + const browser = await firefox.launch(); const context = await browser.newContext(); const page = await context.newPage(); diff --git a/docs/api.md b/docs/api.md index b04416b3b2..0cabbc8c2e 100644 --- a/docs/api.md +++ b/docs/api.md @@ -5,7 +5,8 @@ ##### Table of Contents -- [class: Playwright](#class-playwright) +- [Playwright module](#playwright-module) +- [class: BrowserType](#class-browsertype) - [class: Browser](#class-browser) - [class: BrowserApp](#class-browserapp) - [class: BrowserContext](#class-browsercontext) @@ -34,15 +35,15 @@ - [Downloaded browsers](#downloaded-browsers) -### class: Playwright +### Playwright module Playwright module provides a method to launch a browser instance. The following is a typical example of using Playwright to drive automation: ```js -const playwright = require('playwright').chromium; // Or 'firefox' or 'webkit'. +const { chromium, firefox, webkit } = require('playwright'); (async () => { - const browser = await playwright.launch(); + const browser = await chromium.launch(); // Or 'firefox' or 'webkit'. const context = await browser.newContext(); const page = await context.newPage('http://example.com'); // other actions... @@ -53,34 +54,17 @@ const playwright = require('playwright').chromium; // Or 'firefox' or 'webkit'. Playwright automatically downloads browser executables during installation, see [Downloaded browsers](#downloaded-browsers) for more information. -- [playwright.connect(options)](#playwrightconnectoptions) -- [playwright.defaultArgs([options])](#playwrightdefaultargsoptions) +- [playwright.chromium](#playwrightchromium) - [playwright.devices](#playwrightdevices) - [playwright.errors](#playwrighterrors) -- [playwright.executablePath()](#playwrightexecutablepath) -- [playwright.launch([options])](#playwrightlaunchoptions) -- [playwright.launchBrowserApp([options])](#playwrightlaunchbrowserappoptions) +- [playwright.firefox](#playwrightfirefox) +- [playwright.webkit](#playwrightwebkit) -#### playwright.connect(options) -- `options` <[Object]> - - `browserWSEndpoint` A browser websocket endpoint to connect to. - - `slowMo` <[number]> Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on. - - `browserURL` **Chromium-only** A browser url to connect to, in format `http://${host}:${port}`. Use interchangeably with `browserWSEndpoint` to let Playwright fetch it from [metadata endpoint](https://chromedevtools.github.io/devtools-protocol/#how-do-i-access-the-browser-target). - - `transport` <[ConnectionTransport]> **Experimental** Specify a custom transport object for Playwright to use. -- returns: <[Promise]<[Browser]>> +#### playwright.chromium +- returns: <[BrowserType]> -This methods attaches Playwright to an existing browser instance. - -#### playwright.defaultArgs([options]) -- `options` <[Object]> Set of configurable options to set on the browser. Can have the following fields: - - `headless` <[boolean]> Whether to run browser in headless mode. More details for [Chromium](https://developers.google.com/web/updates/2017/04/headless-chrome) and [Firefox](https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Headless_mode). Defaults to `true` unless the `devtools` option is `true`. - - `args` <[Array]<[string]>> Additional arguments to pass to the browser instance. The list of Chromium flags can be found [here](http://peter.sh/experiments/chromium-command-line-switches/). - - `userDataDir` <[string]> Path to a [User Data Directory](https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md). - - `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`. -- returns: <[Array]<[string]>> - -The default flags that browser will be launched with. +This object can be used to launch or connect to Chromium, returning instances of [ChromiumBrowser]. #### playwright.devices - returns: <[Object]> @@ -89,11 +73,11 @@ Returns a list of devices to be used with [`page.emulate(options)`](#pageemulate devices can be found in [src/deviceDescriptors.ts](https://github.com/Microsoft/playwright/blob/master/src/deviceDescriptors.ts). ```js -const playwright = require('playwright').firefox; // Or 'chromium' or 'webkit'. -const iPhone = playwright.devices['iPhone 6']; +const { webkit, devices } = require('playwright'); +const iPhone = devices['iPhone 6']; (async () => { - const browser = await playwright.launch(); + const browser = await webkit.launch(); const context = await browser.newContext({ viewport: iPhone.viewport, userAgent: iPhone.userAgent @@ -112,7 +96,7 @@ Playwright methods might throw errors if they are unable to fulfill a request. F might fail if the selector doesn't match any nodes during the given timeframe. For certain types of errors Playwright uses specific error classes. -These classes are available via [`playwright.errors`](#playwrighterrors). +These classes are available via [`browserType.errors`](#browsertypeerrors) or [`playwright.errors`](#playwrighterrors). An example of handling a timeout error: ```js @@ -125,16 +109,116 @@ try { } ``` -#### playwright.executablePath() +#### playwright.firefox +- returns: <[BrowserType]> + +This object can be used to launch or connect to Firefox, returning instances of [FirefoxBrowser]. + +#### playwright.webkit +- returns: <[BrowserType]> + +This object can be used to launch or connect to WebKit, returning instances of [WebKitBrowser]. + +### class: BrowserType + +BrowserType provides methods to launch a specific browser instance or connect to an existing one. +The following is a typical example of using Playwright to drive automation: +```js +const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'. + +(async () => { + const browser = await chromium.launch(); + const context = await browser.newContext(); + const page = await context.newPage('http://example.com'); + // other actions... + await browser.close(); +})(); +``` + + +- [browserType.connect(options)](#browsertypeconnectoptions) +- [browserType.defaultArgs([options])](#browsertypedefaultargsoptions) +- [browserType.devices](#browsertypedevices) +- [browserType.errors](#browsertypeerrors) +- [browserType.executablePath()](#browsertypeexecutablepath) +- [browserType.launch([options])](#browsertypelaunchoptions) +- [browserType.launchBrowserApp([options])](#browsertypelaunchbrowserappoptions) + + +#### browserType.connect(options) +- `options` <[Object]> + - `browserWSEndpoint` A browser websocket endpoint to connect to. + - `slowMo` <[number]> Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on. + - `browserURL` **Chromium-only** A browser url to connect to, in format `http://${host}:${port}`. Use interchangeably with `browserWSEndpoint` to let Playwright fetch it from [metadata endpoint](https://chromedevtools.github.io/devtools-protocol/#how-do-i-access-the-browser-target). + - `transport` <[ConnectionTransport]> **Experimental** Specify a custom transport object for Playwright to use. +- returns: <[Promise]<[Browser]>> + +This methods attaches Playwright to an existing browser instance. + +#### browserType.defaultArgs([options]) +- `options` <[Object]> Set of configurable options to set on the browser. Can have the following fields: + - `headless` <[boolean]> Whether to run browser in headless mode. More details for [Chromium](https://developers.google.com/web/updates/2017/04/headless-chrome) and [Firefox](https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Headless_mode). Defaults to `true` unless the `devtools` option is `true`. + - `args` <[Array]<[string]>> Additional arguments to pass to the browser instance. The list of Chromium flags can be found [here](http://peter.sh/experiments/chromium-command-line-switches/). + - `userDataDir` <[string]> Path to a [User Data Directory](https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md). + - `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`. +- returns: <[Array]<[string]>> + +The default flags that browser will be launched with. + +#### browserType.devices +- returns: <[Object]> + +Returns a list of devices to be used with [`page.emulate(options)`](#pageemulateoptions). Actual list of +devices can be found in [src/deviceDescriptors.ts](https://github.com/Microsoft/playwright/blob/master/src/deviceDescriptors.ts). + +```js +const { webkit } = require('playwright'); +const iPhone = webkit.devices['iPhone 6']; + +(async () => { + const browser = await webkit.launch(); + const context = await browser.newContext({ + viewport: iPhone.viewport, + userAgent: iPhone.userAgent + }); + const page = await context.newPage('http://example.com'); + // other actions... + await browser.close(); +})(); +``` + +#### browserType.errors +- returns: <[Object]> + - `TimeoutError` <[function]> A class of [TimeoutError]. + +Playwright methods might throw errors if they are unable to fulfill a request. For example, [page.waitForSelector(selector[, options])](#pagewaitforselectorselector-options) +might fail if the selector doesn't match any nodes during the given timeframe. + +For certain types of errors Playwright uses specific error classes. +These classes are available via [`browserType.errors`](#browsertypeerrors) or [`playwright.errors`](#playwrighterrors). + +An example of handling a timeout error: +```js +const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'. +try { + await page.waitForSelector('.foo'); +} catch (e) { + if (e instanceof webkit.errors.TimeoutError) { + // Do something if this is a timeout. + } +} +``` + +#### browserType.executablePath() - returns: <[string]> A path where Playwright expects to find a bundled browser. -#### playwright.launch([options]) +#### browserType.launch([options]) - `options` <[Object]> Set of configurable options to set on the browser. Can have the following fields: - `headless` <[boolean]> Whether to run browser in headless mode. More details for [Chromium](https://developers.google.com/web/updates/2017/04/headless-chrome) and [Firefox](https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Headless_mode). Defaults to `true` unless the `devtools` option is `true`. - `executablePath` <[string]> Path to a browser executable to run instead of the bundled one. If `executablePath` is a relative path, then it is resolved relative to [current working directory](https://nodejs.org/api/process.html#process_process_cwd). **BEWARE**: Playwright is only [guaranteed to work](https://github.com/Microsoft/playwright/#q-why-doesnt-playwright-vxxx-work-with-chromium-vyyy) with the bundled Chromium, Firefox or WebKit, use at your own risk. - `slowMo` <[number]> Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on. - `args` <[Array]<[string]>> Additional arguments to pass to the browser instance. The list of Chromium flags can be found [here](http://peter.sh/experiments/chromium-command-line-switches/). - - `ignoreDefaultArgs` <[boolean]|[Array]<[string]>> If `true`, then do not use [`playwright.defaultArgs()`](#playwrightdefaultargsoptions). If an array is given, then filter out the given default arguments. Dangerous option; use with care. Defaults to `false`. + - `ignoreDefaultArgs` <[boolean]|[Array]<[string]>> If `true`, then do not use [`browserType.defaultArgs()`](#browsertypedefaultargsoptions). If an array is given, then filter out the given default arguments. Dangerous option; use with care. Defaults to `false`. - `handleSIGINT` <[boolean]> Close the browser process on Ctrl-C. Defaults to `true`. - `handleSIGTERM` <[boolean]> Close the browser process on SIGTERM. Defaults to `true`. - `handleSIGHUP` <[boolean]> Close the browser process on SIGHUP. Defaults to `true`. @@ -149,7 +233,7 @@ try { You can use `ignoreDefaultArgs` to filter out `--mute-audio` from default arguments: ```js -const browser = await playwright.launch({ +const browser = await chromium.launch({ // Or 'firefox' or 'webkit'. ignoreDefaultArgs: ['--mute-audio'] }); ``` @@ -158,17 +242,17 @@ const browser = await playwright.launch({ > > If Google Chrome (rather than Chromium) is preferred, a [Chrome Canary](https://www.google.com/chrome/browser/canary.html) or [Dev Channel](https://www.chromium.org/getting-involved/dev-channel) build is suggested. > -> In [playwright.launch([options])](#playwrightlaunchoptions) above, any mention of Chromium also applies to Chrome. +> In [browserType.launch([options])](#browsertypelaunchoptions) above, any mention of Chromium also applies to Chrome. > > See [`this article`](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/) for a description of the differences between Chromium and Chrome. [`This article`](https://chromium.googlesource.com/chromium/src/+/lkgr/docs/chromium_browser_vs_google_chrome.md) describes some differences for Linux users. -#### playwright.launchBrowserApp([options]) +#### browserType.launchBrowserApp([options]) - `options` <[Object]> Set of configurable options to set on the browser. Can have the following fields: - `headless` <[boolean]> Whether to run browser in headless mode. More details for [Chromium](https://developers.google.com/web/updates/2017/04/headless-chrome) and [Firefox](https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Headless_mode). Defaults to `true` unless the `devtools` option is `true`. - `executablePath` <[string]> Path to a browser executable to run instead of the bundled one. If `executablePath` is a relative path, then it is resolved relative to [current working directory](https://nodejs.org/api/process.html#process_process_cwd). **BEWARE**: Playwright is only [guaranteed to work](https://github.com/Microsoft/playwright/#q-why-doesnt-playwright-vxxx-work-with-chromium-vyyy) with the bundled Chromium, Firefox or WebKit, use at your own risk. - `slowMo` <[number]> Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on. - `args` <[Array]<[string]>> Additional arguments to pass to the browser instance. The list of Chromium flags can be found [here](http://peter.sh/experiments/chromium-command-line-switches/). - - `ignoreDefaultArgs` <[boolean]|[Array]<[string]>> If `true`, then do not use [`playwright.defaultArgs()`](#playwrightdefaultargsoptions). If an array is given, then filter out the given default arguments. Dangerous option; use with care. Defaults to `false`. + - `ignoreDefaultArgs` <[boolean]|[Array]<[string]>> If `true`, then do not use [`browserType.defaultArgs()`](#browsertypedefaultargsoptions). If an array is given, then filter out the given default arguments. Dangerous option; use with care. Defaults to `false`. - `handleSIGINT` <[boolean]> Close the browser process on Ctrl-C. Defaults to `true`. - `handleSIGTERM` <[boolean]> Close the browser process on SIGTERM. Defaults to `true`. - `handleSIGHUP` <[boolean]> Close the browser process on SIGHUP. Defaults to `true`. @@ -184,14 +268,14 @@ const browser = await playwright.launch({ * extends: [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter) -A Browser is created when Playwright connects to a browser instance, either through [`playwright.launch`](#playwrightlaunchoptions) or [`playwright.connect`](#playwrightconnectoptions). +A Browser is created when Playwright connects to a browser instance, either through [`browserType.launch`](#browsertypelaunchoptions) or [`browserType.connect`](#browsertypeconnectoptions). An example of using a [Browser] to create a [Page]: ```js -const playwright = require('playwright').firefox; // Or 'chromium' or 'webkit'. +const { firefox } = require('playwright'); // Or 'chromium' or 'webkit'. (async () => { - const browser = await playwright.launch(); + const browser = await firefox.launch(); const context = await browser.newContext(); const page = await context.newPage('https://example.com'); await browser.close(); @@ -200,19 +284,19 @@ const playwright = require('playwright').firefox; // Or 'chromium' or 'webkit'. An example of launching a browser executable and connecting to a [Browser] later: ```js -const playwright = require('playwright').webkit; // Or 'chromium' or 'firefox'. +const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'. (async () => { - const browserApp = await playwright.launchBrowserApp({ webSocket: true }); + const browserApp = await webkit.launchBrowserApp({ webSocket: true }); const connectOptions = browserApp.connectOptions(); // Use connect options later to establish a connection. - const browser = await playwright.connect(connectOptions); + const browser = await webkit.connect(connectOptions); // Close browser instance. await browserApp.close(); })(); ``` -See [ChromiumBrowser], [FirefoxBrowser] and [WebKitBrowser] for browser-specific features. Note that [playwright.connect(options)](#playwrightconnectoptions) and [playwright.launch(options)](#playwrightlaunchoptions) always return a specific browser instance, based on the browser being connected to or launched. +See [ChromiumBrowser], [FirefoxBrowser] and [WebKitBrowser] for browser-specific features. Note that [browserType.connect(options)](#browsertypeconnectoptions) and [browserType.launch(options)](#browsertypelaunchoptions) always return a specific browser instance, based on the browser being connected to or launched. - [event: 'disconnected'](#event-disconnected) @@ -225,9 +309,9 @@ See [ChromiumBrowser], [FirefoxBrowser] and [WebKitBrowser] for browser-specific #### event: 'disconnected' -Emitted when Playwright gets disconnected from the browser instance. This might happen because of one of the following: -- Browser is closed or crashed -- The [`browser.disconnect`](#browserdisconnect) method was called +Emitted when Browser gets disconnected from the browser application. This might happen because of one of the following: +- Browser application is closed or crashed. +- The [`browser.disconnect`](#browserdisconnect) method was called. #### browser.browserContexts() - returns: <[Array]<[BrowserContext]>> @@ -248,7 +332,7 @@ Returns the default browser context. The default browser context can not be clos #### browser.disconnect() - returns: <[Promise]> -Disconnects Playwright from the browser, but leaves the browser process running. After calling `disconnect`, the [Browser] object is considered disposed and cannot be used anymore. +Disconnects Browser from the browser application, but leaves the application process running. After calling `disconnect`, the [Browser] object is considered disposed and cannot be used anymore. #### browser.isConnected() @@ -279,7 +363,7 @@ Creates a new browser context. It won't share cookies/cache with other browser c ```js (async () => { - const browser = await playwright.launch(); + const browser = await playwright.firefox.launch(); // Or 'chromium' or 'webkit'. // Create a new incognito browser context. const context = await browser.newContext(); // Create a new page in a pristine context. @@ -307,7 +391,7 @@ Closes the browser gracefully and makes sure the process is terminated. - `slowMo` <[number]> - `transport` <[ConnectionTransport]> **Experimental** A custom transport object which should be used to connect. -This options object can be passed to [playwright.connect(options)](#playwrightconnectoptions) to establish connection to the browser. +This options object can be passed to [browserType.connect(options)](#browsertypeconnectoptions) to establish connection to the browser. #### browserApp.process() - returns: Spawned browser application process. @@ -315,7 +399,7 @@ This options object can be passed to [playwright.connect(options)](#playwrightco #### browserApp.wsEndpoint() - returns: Browser websocket url. -Browser websocket endpoint which can be used as an argument to [playwright.connect(options)] to establish connection to the browser. +Browser websocket endpoint which can be used as an argument to [browserType.connect(options)] to establish connection to the browser. ### class: BrowserContext @@ -498,10 +582,10 @@ One of the following values: `'log'`, `'debug'`, `'info'`, `'error'`, `'warning' An example of using `Dialog` class: ```js -const playwright = require('playwright').chromium; // Or 'firefox' or 'webkit'. +const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'. (async () => { - const browser = await playwright.launch(); + const browser = await chromium.launch(); const context = await browser.newContext(); const page = await context.newPage(); page.on('dialog', async dialog => { @@ -543,10 +627,10 @@ const playwright = require('playwright').chromium; // Or 'firefox' or 'webkit'. ElementHandle represents an in-page DOM element. ElementHandles can be created with the [page.$](#pageselector) method. ```js -const playwright = require('playwright').chromium; // Or 'firefox' or 'webkit'. +const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'. (async () => { - const browser = await playwright.launch(); + const browser = await chromium.launch(); const context = await browser.newContext(); const page = await context.newPage('https://example.com'); const hrefElement = await page.$('a'); @@ -828,10 +912,10 @@ At every point of time, page exposes its current frame tree via the [page.mainFr An example of dumping frame tree: ```js -const playwright = require('playwright').firefox; // Or 'chromium' or 'webkit'. +const { firefox } = require('playwright'); // Or 'chromium' or 'webkit'. (async () => { - const browser = await playwright.launch(); + const browser = await firefox.launch(); const context = await browser.newContext(); const page = await context.newPage('https://www.google.com/chrome/browser/canary.html'); dumpFrameTree(page.mainFrame(), ''); @@ -1287,10 +1371,10 @@ await page.waitFor(selector => !!document.querySelector(selector), {}, selector) The `waitForFunction` can be used to observe viewport size change: ```js -const playwright = require('playwright').firefox; // Or 'chromium' or 'webkit'. +const { firefox } = require('playwright'); // Or 'chromium' or 'webkit'. (async () => { - const browser = await playwright.launch(); + const browser = await firefox.launch(); const context = await browser.newContext(); const page = await context.newPage(); const watchDog = page.mainFrame().waitForFunction('window.innerWidth < 100'); @@ -1362,10 +1446,10 @@ immediately. If the selector doesn't appear after the `timeout` milliseconds of This method works across navigations: ```js -const playwright = require('playwright').webkit; // Or 'chromium' or 'firefox'. +const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'. (async () => { - const browser = await playwright.launch(); + const browser = await webkit.launch(); const context = await browser.newContext(); const page = await context.newPage(); let currentURL; @@ -1671,10 +1755,10 @@ Page provides methods to interact with a single tab or [extension background pag This example creates a page, navigates it to a URL, and then saves a screenshot: ```js -const playwright = require('playwright').webkit; // Or 'chromium' or 'firefox'. +const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'. (async () => { - const browser = await playwright.launch(); + const browser = await webkit.launch(); const context = await browser.newContext(); const page = await context.newPage('https://example.com'); await page.screenshot({path: 'screenshot.png'}); @@ -2214,11 +2298,11 @@ If the `playwrightFunction` returns a [Promise], it will be awaited. An example of adding an `md5` function into the page: ```js -const playwright = require('playwright').firefox; // Or 'chromium' or 'webkit'. +const { firefox } = require('playwright'); // Or 'chromium' or 'webkit'. const crypto = require('crypto'); (async () => { - const browser = await playwright.launch(); + const browser = await firefox.launch(); const context = await browser.newContext(); const page = await context.newPage(); page.on('console', msg => console.log(msg.text())); @@ -2238,11 +2322,11 @@ const crypto = require('crypto'); An example of adding a `window.readfile` function into the page: ```js -const playwright = require('playwright').chromium; // Or 'firefox' or 'webkit'. +const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'. const fs = require('fs'); (async () => { - const browser = await playwright.launch(); + const browser = await chromium.launch(); const context = await browser.newContext(); const page = await context.newPage(); page.on('console', msg => console.log(msg.text())); @@ -2734,10 +2818,10 @@ Waits for event to fire and passes its value into the predicate function. Resolv The `waitForFunction` can be used to observe viewport size change: ```js -const playwright = require('playwright').webkit; // Or 'chromium' or 'firefox'. +const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'. (async () => { - const browser = await playwright.launch(); + const browser = await webkit.launch(); const context = await browser.newContext(); const page = await context.newPage(); const watchDog = page.waitForFunction('window.innerWidth < 100'); @@ -2842,10 +2926,10 @@ immediately. If the selector doesn't appear after the `timeout` milliseconds of This method works across navigations: ```js -const playwright = require('playwright').chromium; // Or 'firefox' or 'webkit'. +const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'. (async () => { - const browser = await playwright.launch(); + const browser = await chromium.launch(); const context = await browser.newContext(); const page = await context.newPage(); let currentURL; @@ -3159,7 +3243,7 @@ Contains the URL of the WebSocket. * extends: [Error] -TimeoutError is emitted whenever certain operations are terminated due to timeout, e.g. [page.waitForSelector(selector[, options])](#pagewaitforselectorselector-options) or [playwright.launch([options])](#playwrightlaunchoptions). +TimeoutError is emitted whenever certain operations are terminated due to timeout, e.g. [page.waitForSelector(selector[, options])](#pagewaitforselectorselector-options) or [browserType.launch([options])](#browsertypelaunchoptions). ### class: Accessibility @@ -3268,9 +3352,6 @@ for (const entry of coverage) { console.log(`Bytes used: ${usedBytes / totalBytes * 100}%`); ``` -_To output coverage in a form consumable by [Istanbul](https://github.com/istanbuljs), - see [playwright-to-istanbul](https://github.com/istanbuljs/playwright-to-istanbul)._ - - [coverage.startCSSCoverage([options])](#coveragestartcsscoverageoptions) - [coverage.startJSCoverage([options])](#coveragestartjscoverageoptions) @@ -3587,18 +3668,18 @@ Playwright can be used for testing Chrome Extensions. The following is code for getting a handle to the [background page](https://developer.chrome.com/extensions/background_pages) of an extension whose source is located in `./my-extension`: ```js -const playwright = require('playwright').chromium; +const { chromium } = require('playwright'); (async () => { const pathToExtension = require('path').join(__dirname, 'my-extension'); - const browser = await playwright.launch({ + const browser = await chromium.launch({ headless: false, args: [ `--disable-extensions-except=${pathToExtension}`, `--load-extension=${pathToExtension}` ] }); - const targets = await browser.chromium.targets(); + const targets = await browser.targets(); const backgroundPageTarget = targets.find(target => target.type() === 'background_page'); const backgroundPage = await backgroundPageTarget.page(); // Test the background page as you would any other page. @@ -3625,6 +3706,7 @@ During installation Playwright downloads browser executables, according to revis [Body]: #class-body "Body" [BrowserApp]: #class-browserapp "BrowserApp" [BrowserContext]: #class-browsercontext "BrowserContext" +[BrowserType]: #class-browsertype "BrowserType" [Browser]: #class-browser "Browser" [Buffer]: https://nodejs.org/api/buffer.html#buffer_class_buffer "Buffer" [ChildProcess]: https://nodejs.org/api/child_process.html "ChildProcess" diff --git a/docs/web.md b/docs/web.md index 19d926e35b..50d2c65b65 100644 --- a/docs/web.md +++ b/docs/web.md @@ -4,7 +4,7 @@ Playwright contains a version bundled for web browsers under `playwright/web.js` installs playwright under `window.playwrightweb`. You can use it in the web page to drive another browser instance. -API consists of a single `connect` function, similar to [playwright.connect(options)](api.md#playwrightconnectoptions). +API consists of a single `connect` function, similar to [browserType.connect(options)](api.md#browsertypeconnectoptions). ```html diff --git a/download-browser.js b/download-browser.js index 5c7d7502fc..5cbb6ba5ca 100644 --- a/download-browser.js +++ b/download-browser.js @@ -15,13 +15,13 @@ */ async function downloadBrowser(browser) { - const playwright = require('.')[browser]; + const browserType = require('.')[browser]; let progressBar = null; let lastDownloadedBytes = 0; function onProgress(downloadedBytes, totalBytes) { if (!progressBar) { const ProgressBar = require('progress'); - progressBar = new ProgressBar(`Downloading ${browser} ${playwright._revision} - ${toMegabytes(totalBytes)} [:bar] :percent :etas `, { + progressBar = new ProgressBar(`Downloading ${browser} ${browserType._revision} - ${toMegabytes(totalBytes)} [:bar] :percent :etas `, { complete: '=', incomplete: ' ', width: 20, @@ -33,7 +33,7 @@ async function downloadBrowser(browser) { progressBar.tick(delta); } - const fetcher = playwright._createBrowserFetcher(); + const fetcher = browserType._createBrowserFetcher(); const revisionInfo = fetcher.revisionInfo(); // Do nothing if the revision is already downloaded. if (revisionInfo.local) diff --git a/index.d.ts b/index.d.ts index dabb017171..3142b386cd 100644 --- a/index.d.ts +++ b/index.d.ts @@ -15,7 +15,9 @@ */ export * from './lib/api'; -export const chromium: import('./lib/server/crPlaywright').CRPlaywright; -export const firefox: import('./lib/server/ffPlaywright').FFPlaywright; -export const webkit: import('./lib/server/wkPlaywright').WKPlaywright; +export const devices: typeof import('./lib/deviceDescriptors').DeviceDescriptors; +export const errors: { TimeoutError: typeof import('./lib/errors').TimeoutError }; +export const chromium: import('./lib/api').Chromium; +export const firefox: import('./lib/api').Firefox; +export const webkit: import('./lib/api').WebKit; export type PlaywrightWeb = typeof import('./lib/web'); diff --git a/index.js b/index.js index 677ad987b5..4d745cee49 100644 --- a/index.js +++ b/index.js @@ -17,10 +17,11 @@ const { helper } = require('./lib/helper'); const api = require('./lib/api'); const packageJson = require('./package.json'); -const { DeviceDescriptors } = require('./lib/deviceDescriptors'); -const CRPlaywright = require('./lib/server/crPlaywright').CRPlaywright; -const FFPlaywright = require('./lib/server/ffPlaywright').FFPlaywright; -const WKPlaywright = require('./lib/server/wkPlaywright').WKPlaywright; +const DeviceDescriptors = require('./lib/deviceDescriptors'); +const { TimeoutError } = require('./lib/errors'); +const { Chromium } = require('./lib/server/chromium'); +const { Firefox } = require('./lib/server/firefox'); +const { WebKit } = require('./lib/server/webkit'); for (const className in api) { if (typeof api[className] === 'function') @@ -28,8 +29,9 @@ for (const className in api) { } module.exports = { - chromium: new CRPlaywright(__dirname, packageJson.playwright.chromium_revision), - firefox: new FFPlaywright(__dirname, packageJson.playwright.firefox_revision), - webkit: new WKPlaywright(__dirname, packageJson.playwright.webkit_revision), devices: DeviceDescriptors, -}; + errors: { TimeoutError }, + chromium: new Chromium(__dirname, packageJson.playwright.chromium_revision), + firefox: new Firefox(__dirname, packageJson.playwright.firefox_revision), + webkit: new WebKit(__dirname, packageJson.playwright.webkit_revision), +} diff --git a/prepare.js b/prepare.js index 2ada94891e..d9aab333ff 100644 --- a/prepare.js +++ b/prepare.js @@ -54,8 +54,7 @@ async function downloadAndCleanup(browser) { const revisionInfo = await downloadBrowser(browser); // Remove previous revisions. - const playwright = require('.')[browser]; - const fetcher = playwright._createBrowserFetcher(); + const fetcher = require('.')[browser]._createBrowserFetcher(); const localRevisions = await fetcher.localRevisions(); const cleanupOldVersions = localRevisions.filter(revision => revision !== revisionInfo.revision).map(revision => fetcher.remove(revision)); await Promise.all([...cleanupOldVersions]); diff --git a/src/api.ts b/src/api.ts index f253cec0c9..ea74b6c647 100644 --- a/src/api.ts +++ b/src/api.ts @@ -35,5 +35,5 @@ export { FFBrowser as FirefoxBrowser } from './firefox/ffBrowser'; export { WKBrowser as WebKitBrowser } from './webkit/wkBrowser'; -export { Playwright } from './server/playwright'; +export { BrowserType } from './server/browserType'; export { BrowserApp } from './server/browserApp'; diff --git a/src/server/browserType.ts b/src/server/browserType.ts new file mode 100644 index 0000000000..a12921db09 --- /dev/null +++ b/src/server/browserType.ts @@ -0,0 +1,50 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as types from '../types'; +import { TimeoutError } from '../errors'; +import { Browser, ConnectOptions } from '../browser'; +import { BrowserApp } from './browserApp'; + +export type BrowserArgOptions = { + headless?: boolean, + args?: string[], + userDataDir?: string, + devtools?: boolean, +}; + +export type LaunchOptions = BrowserArgOptions & { + executablePath?: string, + ignoreDefaultArgs?: boolean | string[], + handleSIGINT?: boolean, + handleSIGTERM?: boolean, + handleSIGHUP?: boolean, + timeout?: number, + dumpio?: boolean, + env?: {[key: string]: string} | undefined, + webSocket?: boolean, + slowMo?: number, // TODO: we probably don't want this in launchBrowserApp. +}; + +export interface BrowserType { + executablePath(): string; + launchBrowserApp(options?: LaunchOptions): Promise; + launch(options?: LaunchOptions): Promise; + defaultArgs(options?: BrowserArgOptions): string[]; + connect(options: ConnectOptions & { browserURL?: string }): Promise; + devices: types.Devices; + errors: { TimeoutError: typeof TimeoutError }; +} diff --git a/src/server/crPlaywright.ts b/src/server/chromium.ts similarity index 98% rename from src/server/crPlaywright.ts rename to src/server/chromium.ts index 835caa56e3..cd794798be 100644 --- a/src/server/crPlaywright.ts +++ b/src/server/chromium.ts @@ -29,11 +29,11 @@ import { TimeoutError } from '../errors'; import { launchProcess, waitForLine } from '../server/processLauncher'; import { kBrowserCloseMessageId } from '../chromium/crConnection'; import { PipeTransport } from './pipeTransport'; -import { Playwright, LaunchOptions, BrowserArgOptions } from './playwright'; +import { LaunchOptions, BrowserArgOptions, BrowserType } from './browserType'; import { createTransport, ConnectOptions } from '../browser'; import { BrowserApp } from './browserApp'; -export class CRPlaywright implements Playwright { +export class Chromium implements BrowserType { private _projectRoot: string; readonly _revision: string; diff --git a/src/server/ffPlaywright.ts b/src/server/firefox.ts similarity index 99% rename from src/server/ffPlaywright.ts rename to src/server/firefox.ts index ab48d06fca..80db28f035 100644 --- a/src/server/ffPlaywright.ts +++ b/src/server/firefox.ts @@ -28,11 +28,11 @@ import * as path from 'path'; import * as util from 'util'; import { TimeoutError } from '../errors'; import { assert } from '../helper'; -import { Playwright, LaunchOptions, BrowserArgOptions } from './playwright'; +import { LaunchOptions, BrowserArgOptions, BrowserType } from './browserType'; import { createTransport, ConnectOptions } from '../browser'; import { BrowserApp } from './browserApp'; -export class FFPlaywright implements Playwright { +export class Firefox implements BrowserType { private _projectRoot: string; readonly _revision: string; diff --git a/src/server/playwright.ts b/src/server/playwright.ts index 3b273fb810..6547196c62 100644 --- a/src/server/playwright.ts +++ b/src/server/playwright.ts @@ -16,35 +16,23 @@ import * as types from '../types'; import { TimeoutError } from '../errors'; -import { Browser, ConnectOptions } from '../browser'; -import { BrowserApp } from './browserApp'; +import { DeviceDescriptors } from '../deviceDescriptors'; +import { Chromium } from './chromium'; +import { WebKit } from './webkit'; +import { Firefox } from './firefox'; -export type BrowserArgOptions = { - headless?: boolean, - args?: string[], - userDataDir?: string, - devtools?: boolean, -}; +export class Playwright { + readonly devices: types.Devices; + readonly errors: { TimeoutError: typeof TimeoutError }; + readonly chromium: Chromium; + readonly firefox: Firefox; + readonly webkit: WebKit; -export type LaunchOptions = BrowserArgOptions & { - executablePath?: string, - ignoreDefaultArgs?: boolean | string[], - handleSIGINT?: boolean, - handleSIGTERM?: boolean, - handleSIGHUP?: boolean, - timeout?: number, - dumpio?: boolean, - env?: {[key: string]: string} | undefined, - webSocket?: boolean, - slowMo?: number, // TODO: we probably don't want this in launchBrowserApp. -}; - -export interface Playwright { - executablePath(): string; - launchBrowserApp(options?: LaunchOptions): Promise; - launch(options?: LaunchOptions): Promise; - defaultArgs(options?: BrowserArgOptions): string[]; - connect(options: ConnectOptions & { browserURL?: string }): Promise; - devices: types.Devices; - errors: { TimeoutError: typeof TimeoutError }; + constructor(projectRoot: string, revisions: { chromium_revision: string, firefox_revision: string, webkit_revision: string }) { + this.devices = DeviceDescriptors; + this.errors = { TimeoutError }; + this.chromium = new Chromium(projectRoot, revisions.chromium_revision); + this.firefox = new Firefox(projectRoot, revisions.firefox_revision); + this.webkit = new WebKit(projectRoot, revisions.webkit_revision); + } } diff --git a/src/server/wkPlaywright.ts b/src/server/webkit.ts similarity index 98% rename from src/server/wkPlaywright.ts rename to src/server/webkit.ts index d68aa2644d..318b56f08b 100644 --- a/src/server/wkPlaywright.ts +++ b/src/server/webkit.ts @@ -30,14 +30,14 @@ import * as util from 'util'; import * as os from 'os'; import { assert } from '../helper'; import { kBrowserCloseMessageId } from '../webkit/wkConnection'; -import { Playwright, BrowserArgOptions, LaunchOptions } from './playwright'; +import { LaunchOptions, BrowserArgOptions, BrowserType } from './browserType'; import { ConnectionTransport } from '../transport'; import * as ws from 'ws'; import * as uuidv4 from 'uuid/v4'; import { ConnectOptions } from '../browser'; import { BrowserApp } from './browserApp'; -export class WKPlaywright implements Playwright { +export class WebKit implements BrowserType { private _projectRoot: string; readonly _revision: string;