diff --git a/README.md b/README.md
index c8618854..5a851876 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
-###### [API](https://github.com/puppeteer/puppeteer/blob/v5.3.1/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING.md) | [Troubleshooting](https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md)
+###### [API](https://github.com/puppeteer/puppeteer/blob/v5.4.0/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING.md) | [Troubleshooting](https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md)
> Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the [DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/). Puppeteer runs [headless](https://developers.google.com/web/updates/2017/04/headless-chrome) by default, but can be configured to run full (non-headless) Chrome or Chromium.
@@ -37,7 +37,7 @@ npm i puppeteer
# or "yarn add puppeteer"
```
-Note: When you install Puppeteer, it downloads a recent version of Chromium (~170MB Mac, ~282MB Linux, ~280MB Win) that is guaranteed to work with the API. To skip the download, or to download a different browser, see [Environment variables](https://github.com/puppeteer/puppeteer/blob/v5.3.1/docs/api.md#environment-variables).
+Note: When you install Puppeteer, it downloads a recent version of Chromium (~170MB Mac, ~282MB Linux, ~280MB Win) that is guaranteed to work with the API. To skip the download, or to download a different browser, see [Environment variables](https://github.com/puppeteer/puppeteer/blob/v5.4.0/docs/api.md#environment-variables).
### puppeteer-core
@@ -63,7 +63,7 @@ Note: Prior to v1.18.1, Puppeteer required at least Node v6.4.0. Versions from v
Node 8.9.0+. Starting from v3.0.0 Puppeteer starts to rely on Node 10.18.1+. All examples below use async/await which is only supported in Node v7.6.0 or greater.
Puppeteer will be familiar to people using other browser testing frameworks. You create an instance
-of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/puppeteer/puppeteer/blob/v5.3.1/docs/api.md#).
+of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/puppeteer/puppeteer/blob/v5.4.0/docs/api.md#).
**Example** - navigating to https://example.com and saving a screenshot as *example.png*:
@@ -88,7 +88,7 @@ Execute script on the command line
node example.js
```
-Puppeteer sets an initial page size to 800×600px, which defines the screenshot size. The page size can be customized with [`Page.setViewport()`](https://github.com/puppeteer/puppeteer/blob/v5.3.1/docs/api.md#pagesetviewportviewport).
+Puppeteer sets an initial page size to 800×600px, which defines the screenshot size. The page size can be customized with [`Page.setViewport()`](https://github.com/puppeteer/puppeteer/blob/v5.4.0/docs/api.md#pagesetviewportviewport).
**Example** - create a PDF.
@@ -113,7 +113,7 @@ Execute script on the command line
node hn.js
```
-See [`Page.pdf()`](https://github.com/puppeteer/puppeteer/blob/v5.3.1/docs/api.md#pagepdfoptions) for more information about creating pdfs.
+See [`Page.pdf()`](https://github.com/puppeteer/puppeteer/blob/v5.4.0/docs/api.md#pagepdfoptions) for more information about creating pdfs.
**Example** - evaluate script in the context of the page
@@ -148,7 +148,7 @@ Execute script on the command line
node get-dimensions.js
```
-See [`Page.evaluate()`](https://github.com/puppeteer/puppeteer/blob/v5.3.1/docs/api.md#pageevaluatepagefunction-args) for more information on `evaluate` and related methods like `evaluateOnNewDocument` and `exposeFunction`.
+See [`Page.evaluate()`](https://github.com/puppeteer/puppeteer/blob/v5.4.0/docs/api.md#pageevaluatepagefunction-args) for more information on `evaluate` and related methods like `evaluateOnNewDocument` and `exposeFunction`.
@@ -157,7 +157,7 @@ See [`Page.evaluate()`](https://github.com/puppeteer/puppeteer/blob/v5.3.1/docs/
**1. Uses Headless mode**
-Puppeteer launches Chromium in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). To launch a full version of Chromium, set the [`headless` option](https://github.com/puppeteer/puppeteer/blob/v5.3.1/docs/api.md#puppeteerlaunchoptions) when launching a browser:
+Puppeteer launches Chromium in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). To launch a full version of Chromium, set the [`headless` option](https://github.com/puppeteer/puppeteer/blob/v5.4.0/docs/api.md#puppeteerlaunchoptions) when launching a browser:
```js
const browser = await puppeteer.launch({headless: false}); // default is true
@@ -173,7 +173,7 @@ pass in the executable's path when creating a `Browser` instance:
const browser = await puppeteer.launch({executablePath: '/path/to/Chrome'});
```
-You can also use Puppeteer with Firefox Nightly (experimental support). See [`Puppeteer.launch()`](https://github.com/puppeteer/puppeteer/blob/v5.3.1/docs/api.md#puppeteerlaunchoptions) for more information.
+You can also use Puppeteer with Firefox Nightly (experimental support). See [`Puppeteer.launch()`](https://github.com/puppeteer/puppeteer/blob/v5.4.0/docs/api.md#puppeteerlaunchoptions) for more information.
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/+/master/docs/chromium_browser_vs_google_chrome.md) describes some differences for Linux users.
@@ -185,7 +185,7 @@ Puppeteer creates its own browser user profile which it **cleans up on every run
## Resources
-- [API Documentation](https://github.com/puppeteer/puppeteer/blob/v5.3.1/docs/api.md)
+- [API Documentation](https://github.com/puppeteer/puppeteer/blob/v5.4.0/docs/api.md)
- [Examples](https://github.com/puppeteer/puppeteer/tree/main/examples/)
- [Community list of Puppeteer resources](https://github.com/transitive-bullshit/awesome-puppeteer)
@@ -328,7 +328,7 @@ See [Contributing](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING
Official Firefox support is currently experimental. The ongoing collaboration with Mozilla aims to support common end-to-end testing use cases, for which developers expect cross-browser coverage. The Puppeteer team needs input from users to stabilize Firefox support and to bring missing APIs to our attention.
-From Puppeteer v2.1.0 onwards you can specify [`puppeteer.launch({product: 'firefox'})`](https://github.com/puppeteer/puppeteer/blob/v5.3.1/docs/api.md#puppeteerlaunchoptions) to run your Puppeteer scripts in Firefox Nightly, without any additional custom patches. While [an older experiment](https://www.npmjs.com/package/puppeteer-firefox) required a patched version of Firefox, [the current approach](https://wiki.mozilla.org/Remote) works with “stock” Firefox.
+From Puppeteer v2.1.0 onwards you can specify [`puppeteer.launch({product: 'firefox'})`](https://github.com/puppeteer/puppeteer/blob/v5.4.0/docs/api.md#puppeteerlaunchoptions) to run your Puppeteer scripts in Firefox Nightly, without any additional custom patches. While [an older experiment](https://www.npmjs.com/package/puppeteer-firefox) required a patched version of Firefox, [the current approach](https://wiki.mozilla.org/Remote) works with “stock” Firefox.
We will continue to collaborate with other browser vendors to bring Puppeteer support to browsers such as Safari.
This effort includes exploration of a standard for executing cross-browser commands (instead of relying on the non-standard DevTools Protocol used by Chrome).
@@ -424,7 +424,7 @@ await page.evaluate(() => {
You may find that Puppeteer does not behave as expected when controlling pages that incorporate audio and video. (For example, [video playback/screenshots is likely to fail](https://github.com/puppeteer/puppeteer/issues/291).) There are two reasons for this:
-* Puppeteer is bundled with Chromium — not Chrome — and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or H.264. (However, it is possible to force Puppeteer to use a separately-installed version Chrome instead of Chromium via the [`executablePath` option to `puppeteer.launch`](https://github.com/puppeteer/puppeteer/blob/v5.3.1/docs/api.md#puppeteerlaunchoptions). You should only use this configuration if you need an official release of Chrome that supports these media formats.)
+* Puppeteer is bundled with Chromium — not Chrome — and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or H.264. (However, it is possible to force Puppeteer to use a separately-installed version Chrome instead of Chromium via the [`executablePath` option to `puppeteer.launch`](https://github.com/puppeteer/puppeteer/blob/v5.4.0/docs/api.md#puppeteerlaunchoptions). You should only use this configuration if you need an official release of Chrome that supports these media formats.)
* Since Puppeteer (in all configurations) controls a desktop version of Chromium/Chrome, features that are only supported by the mobile version of Chrome are not supported. This means that Puppeteer [does not support HTTP Live Streaming (HLS)](https://caniuse.com/#feat=http-live-streaming).
#### Q: I am having trouble installing / running Puppeteer in my test environment. Where should I look for help?
diff --git a/docs/api.md b/docs/api.md
index 836e2bda..613ba3b3 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -1,11 +1,12 @@
-# Puppeteer API Tip-Of-Tree
+# Puppeteer API v5.4.0
- Interactive Documentation: https://pptr.dev
- API Translations: [中文|Chinese](https://zhaoqize.github.io/puppeteer-api-zh_CN/#/)
- Troubleshooting: [troubleshooting.md](https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md)
- Releases per Chromium Version:
+ * Chromium 87.0.4272.0 - [Puppeteer v5.4.0](https://github.com/puppeteer/puppeteer/blob/v5.4.0/docs/api.md)
* Chromium 86.0.4240.0 - [Puppeteer v5.3.0](https://github.com/puppeteer/puppeteer/blob/v5.3.0/docs/api.md)
* Chromium 85.0.4182.0 - [Puppeteer v5.2.1](https://github.com/puppeteer/puppeteer/blob/v5.2.1/docs/api.md)
* Chromium 84.0.4147.0 - [Puppeteer v5.1.0](https://github.com/puppeteer/puppeteer/blob/v5.1.0/docs/api.md)
@@ -30,14 +31,18 @@
- [Environment Variables](#environment-variables)
- [Working with Chrome Extensions](#working-with-chrome-extensions)
- [class: Puppeteer](#class-puppeteer)
+ * [puppeteer.clearCustomQueryHandlers()](#puppeteerclearcustomqueryhandlers)
* [puppeteer.connect(options)](#puppeteerconnectoptions)
* [puppeteer.createBrowserFetcher([options])](#puppeteercreatebrowserfetcheroptions)
+ * [puppeteer.customQueryHandlerNames()](#puppeteercustomqueryhandlernames)
* [puppeteer.defaultArgs([options])](#puppeteerdefaultargsoptions)
* [puppeteer.devices](#puppeteerdevices)
* [puppeteer.errors](#puppeteererrors)
* [puppeteer.executablePath()](#puppeteerexecutablepath)
* [puppeteer.launch([options])](#puppeteerlaunchoptions)
* [puppeteer.product](#puppeteerproduct)
+ * [puppeteer.registerCustomQueryHandler(name, queryHandler)](#puppeteerregistercustomqueryhandlername-queryhandler)
+ * [puppeteer.unregisterCustomQueryHandler(name)](#puppeteerunregistercustomqueryhandlername)
- [class: BrowserFetcher](#class-browserfetcher)
* [browserFetcher.canDownload(revision)](#browserfetchercandownloadrevision)
* [browserFetcher.download(revision[, progressCallback])](#browserfetcherdownloadrevision-progresscallback)
@@ -354,6 +359,7 @@
* [eventEmitter.once(event, handler)](#eventemitteronceevent-handler)
* [eventEmitter.removeAllListeners([event])](#eventemitterremovealllistenersevent)
* [eventEmitter.removeListener(event, handler)](#eventemitterremovelistenerevent-handler)
+- [interface: CustomQueryHandler](#interface-customqueryhandler)
### Overview
@@ -466,6 +472,8 @@ const puppeteer = require('puppeteer');
await browser.close();
})();
```
+#### puppeteer.clearCustomQueryHandlers()
+Clears all registered handlers.
#### puppeteer.connect(options)
- `options` <[Object]>
@@ -494,6 +502,9 @@ This methods attaches Puppeteer to an existing browser instance.
- `product` <"chrome"|"firefox"> [string] for the product to run. Possible values are: `chrome`, `firefox`. Defaults to `chrome`.
- returns: <[BrowserFetcher]>
+#### puppeteer.customQueryHandlerNames()
+- returns: <[[Array]> A list with the names of all registered custom query handlers.
+
#### puppeteer.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](https://developers.google.com/web/updates/2017/04/headless-chrome). Defaults to `true` unless the `devtools` option is `true`.
@@ -602,6 +613,22 @@ const browser = await puppeteer.launch({
The product is set by the `PUPPETEER_PRODUCT` environment variable or the `product` option in [puppeteer.launch([options])](#puppeteerlaunchoptions) and defaults to `chrome`. Firefox support is experimental and requires to install Puppeteer via `PUPPETEER_PRODUCT=firefox npm i puppeteer`.
+#### puppeteer.registerCustomQueryHandler(name, queryHandler)
+- `name` <[string]> The name that the custom query handler will be registered under.
+- `queryHandler` <[CustomQueryHandler]> The [custom query handler](#interface-customqueryhandler) to register.
+
+Registers a [custom query handler](#interface-customqueryhandler). After registration,
+the handler can be used everywhere where a selector is expected by prepending
+the selection string with `/`. The name is only allowed to consist of
+lower- and upper case latin letters.
+Example:
+```
+puppeteer.registerCustomQueryHandler('text', { … });
+const aHandle = await page.$('text/…');
+```
+
+#### puppeteer.unregisterCustomQueryHandler(name)
+- `name` <[string]> The name of the query handler to unregistered.
### class: BrowserFetcher
@@ -4144,6 +4171,17 @@ This method is identical to `on` and maintained for compatibility with Node's Ev
This method is identical to `off` and maintained for compatibility with Node's EventEmitter. We recommend using `off` by default.
+### interface: CustomQueryHandler
+
+Contains two functions `queryOne` and `queryAll` that can be
+[registered](#puppeteerregistercustomqueryhandler) as
+alternative querying strategies. The functions `queryOne` and `queryAll` are
+executed in the page context. `queryOne` should take an `Element` and a
+selector string as argument and return a single `Element` or `null` if no
+element is found. `queryAll` takes the same arguments but should instead return
+a `NodeListOf` or `Array` with all the elements that match
+the given query selector.
+
[AXNode]: #accessibilitysnapshotoptions "AXNode"
[Accessibility]: #class-accessibility "Accessibility"
[Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array "Array"
@@ -4193,3 +4231,4 @@ This method is identical to `off` and maintained for compatibility with Node's E
[string]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type "String"
[symbol]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Symbol_type "Symbol"
[xpath]: https://developer.mozilla.org/en-US/docs/Web/XPath "xpath"
+[CustomQueryHandler]: #interface-customqueryhandler "CustomQueryHandler"
diff --git a/package.json b/package.json
index 4b4440fd..263f0491 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "puppeteer",
- "version": "5.3.1-post",
+ "version": "5.4.0",
"description": "A high-level API to control headless Chrome over the DevTools Protocol",
"main": "./cjs-entry.js",
"repository": "github:puppeteer/puppeteer",
diff --git a/src/common/Puppeteer.ts b/src/common/Puppeteer.ts
index 87cb272e..0dc40d33 100644
--- a/src/common/Puppeteer.ts
+++ b/src/common/Puppeteer.ts
@@ -139,7 +139,7 @@ export class Puppeteer {
* @param queryHandler - The {@link CustomQueryHandler | custom query handler} to
* register.
*/
- __experimental_registerCustomQueryHandler(
+ registerCustomQueryHandler(
name: string,
queryHandler: CustomQueryHandler
): void {
@@ -149,21 +149,21 @@ export class Puppeteer {
/**
* @param name - The name of the query handler to unregistered.
*/
- __experimental_unregisterCustomQueryHandler(name: string): void {
+ unregisterCustomQueryHandler(name: string): void {
unregisterCustomQueryHandler(name);
}
/**
* @returns a list with the names of all registered custom query handlers.
*/
- __experimental_customQueryHandlerNames(): string[] {
+ customQueryHandlerNames(): string[] {
return customQueryHandlerNames();
}
/**
* Clears all registered handlers.
*/
- __experimental_clearQueryHandlers(): void {
+ clearCustomQueryHandlers(): void {
clearCustomQueryHandlers();
}
}
diff --git a/src/common/QueryHandler.ts b/src/common/QueryHandler.ts
index 70c0d908..b7984067 100644
--- a/src/common/QueryHandler.ts
+++ b/src/common/QueryHandler.ts
@@ -43,7 +43,7 @@ export interface InternalQueryHandler {
/**
* Contains two functions `queryOne` and `queryAll` that can
- * be {@link Puppeteer.__experimental_registerCustomQueryHandler | registered}
+ * be {@link Puppeteer.registerCustomQueryHandler | registered}
* as alternative querying strategies. The functions `queryOne` and `queryAll`
* are executed in the page context. `queryOne` should take an `Element` and a
* selector string as argument and return a single `Element` or `null` if no
diff --git a/test/elementhandle.spec.ts b/test/elementhandle.spec.ts
index edb05e98..592ba8d5 100644
--- a/test/elementhandle.spec.ts
+++ b/test/elementhandle.spec.ts
@@ -286,14 +286,14 @@ describe('ElementHandle specs', function () {
describe('Custom queries', function () {
this.afterEach(() => {
const { puppeteer } = getTestState();
- puppeteer.__experimental_clearQueryHandlers();
+ puppeteer.clearCustomQueryHandlers();
});
it('should register and unregister', async () => {
const { page, puppeteer } = getTestState();
await page.setContent('');
// Register.
- puppeteer.__experimental_registerCustomQueryHandler('getById', {
+ puppeteer.registerCustomQueryHandler('getById', {
queryOne: (element, selector) =>
document.querySelector(`[id="${selector}"]`),
});
@@ -304,9 +304,11 @@ describe('ElementHandle specs', function () {
element
)
).toBe('foo');
+ const handlerNamesAfterRegistering = puppeteer.customQueryHandlerNames();
+ expect(handlerNamesAfterRegistering.includes('getById')).toBeTruthy();
// Unregister.
- puppeteer.__experimental_unregisterCustomQueryHandler('getById');
+ puppeteer.unregisterCustomQueryHandler('getById');
try {
await page.$('getById/foo');
throw new Error('Custom query handler name not set - throw expected');
@@ -317,11 +319,13 @@ describe('ElementHandle specs', function () {
)
);
}
+ const handlerNamesAfterUnregistering = puppeteer.customQueryHandlerNames();
+ expect(handlerNamesAfterUnregistering.includes('getById')).toBeFalsy();
});
it('should throw with invalid query names', () => {
try {
const { puppeteer } = getTestState();
- puppeteer.__experimental_registerCustomQueryHandler('1/2/3', {
+ puppeteer.registerCustomQueryHandler('1/2/3', {
queryOne: () => document.querySelector('foo'),
});
throw new Error(
@@ -338,7 +342,7 @@ describe('ElementHandle specs', function () {
await page.setContent(
'Foo1
Foo2
'
);
- puppeteer.__experimental_registerCustomQueryHandler('getByClass', {
+ puppeteer.registerCustomQueryHandler('getByClass', {
queryAll: (element, selector) =>
document.querySelectorAll(`.${selector}`),
});
@@ -360,7 +364,7 @@ describe('ElementHandle specs', function () {
await page.setContent(
'Foo1
Foo2
'
);
- puppeteer.__experimental_registerCustomQueryHandler('getByClass', {
+ puppeteer.registerCustomQueryHandler('getByClass', {
queryAll: (element, selector) =>
document.querySelectorAll(`.${selector}`),
});
@@ -373,7 +377,7 @@ describe('ElementHandle specs', function () {
});
it('should wait correctly with waitForSelector', async () => {
const { page, puppeteer } = getTestState();
- puppeteer.__experimental_registerCustomQueryHandler('getByClass', {
+ puppeteer.registerCustomQueryHandler('getByClass', {
queryOne: (element, selector) => element.querySelector(`.${selector}`),
});
const waitFor = page.waitForSelector('getByClass/foo');
@@ -391,7 +395,7 @@ describe('ElementHandle specs', function () {
/* page.waitFor is deprecated so we silence the warning to avoid test noise */
sinon.stub(console, 'warn').callsFake(() => {});
const { page, puppeteer } = getTestState();
- puppeteer.__experimental_registerCustomQueryHandler('getByClass', {
+ puppeteer.registerCustomQueryHandler('getByClass', {
queryOne: (element, selector) => element.querySelector(`.${selector}`),
});
const waitFor = page.waitFor('getByClass/foo');
@@ -409,7 +413,7 @@ describe('ElementHandle specs', function () {
await page.setContent(
'Foo2
'
);
- puppeteer.__experimental_registerCustomQueryHandler('getByClass', {
+ puppeteer.registerCustomQueryHandler('getByClass', {
queryOne: (element, selector) => element.querySelector(`.${selector}`),
queryAll: (element, selector) =>
element.querySelectorAll(`.${selector}`),
@@ -426,7 +430,7 @@ describe('ElementHandle specs', function () {
await page.setContent(
'text
content
'
);
- puppeteer.__experimental_registerCustomQueryHandler('getByClass', {
+ puppeteer.registerCustomQueryHandler('getByClass', {
queryOne: (element, selector) => element.querySelector(`.${selector}`),
queryAll: (element, selector) =>
element.querySelectorAll(`.${selector}`),
diff --git a/test/queryselector.spec.ts b/test/queryselector.spec.ts
index 93a62a8f..7a147ddd 100644
--- a/test/queryselector.spec.ts
+++ b/test/queryselector.spec.ts
@@ -411,7 +411,14 @@ describe('querySelector', function () {
};
before(() => {
const { puppeteer } = getTestState();
- puppeteer.__experimental_registerCustomQueryHandler('allArray', handler);
+ puppeteer.registerCustomQueryHandler('allArray', handler);
+ });
+
+ it('should have registered handler', async () => {
+ const { puppeteer } = getTestState();
+ expect(
+ puppeteer.customQueryHandlerNames().includes('allArray')
+ ).toBeTruthy();
});
it('$$ should query existing elements', async () => {
const { page } = getTestState();