mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
feat: move permissions back into the context (#320)
This commit is contained in:
parent
dd6ba432ab
commit
ad22a46fde
377
docs/api.md
377
docs/api.md
@ -19,6 +19,14 @@
|
||||
* [chromiumPlaywright.errors](#chromiumplaywrighterrors)
|
||||
* [chromiumPlaywright.executablePath()](#chromiumplaywrightexecutablepath)
|
||||
* [chromiumPlaywright.launch([options])](#chromiumplaywrightlaunchoptions)
|
||||
- [class: Browser](#class-browser)
|
||||
* [event: 'disconnected'](#event-disconnected)
|
||||
* [browser.browserContexts()](#browserbrowsercontexts)
|
||||
* [browser.close()](#browserclose)
|
||||
* [browser.defaultContext()](#browserdefaultcontext)
|
||||
* [browser.disconnect()](#browserdisconnect)
|
||||
* [browser.isConnected()](#browserisconnected)
|
||||
* [browser.newContext(options)](#browsernewcontextoptions)
|
||||
- [class: BrowserFetcher](#class-browserfetcher)
|
||||
* [browserFetcher.canDownload(revision)](#browserfetchercandownloadrevision)
|
||||
* [browserFetcher.download(revision[, progressCallback])](#browserfetcherdownloadrevision-progresscallback)
|
||||
@ -32,18 +40,9 @@
|
||||
* [browserServer.process()](#browserserverprocess)
|
||||
* [browserServer.wsEndpoint()](#browserserverwsendpoint)
|
||||
- [class: ChromiumBrowser](#class-chromiumbrowser)
|
||||
* [event: 'disconnected'](#event-disconnected)
|
||||
* [event: 'targetchanged'](#event-targetchanged)
|
||||
* [event: 'targetcreated'](#event-targetcreated)
|
||||
* [event: 'targetdestroyed'](#event-targetdestroyed)
|
||||
* [chromiumBrowser.browserContexts()](#chromiumbrowserbrowsercontexts)
|
||||
* [chromiumBrowser.chromium](#chromiumbrowserchromium)
|
||||
* [chromiumBrowser.close()](#chromiumbrowserclose)
|
||||
* [chromiumBrowser.defaultContext()](#chromiumbrowserdefaultcontext)
|
||||
* [chromiumBrowser.disconnect()](#chromiumbrowserdisconnect)
|
||||
* [chromiumBrowser.isConnected()](#chromiumbrowserisconnected)
|
||||
* [chromiumBrowser.newContext(options)](#chromiumbrowsernewcontextoptions)
|
||||
* [chromiumBrowser.process()](#chromiumbrowserprocess)
|
||||
* [chromiumBrowser.browserTarget()](#chromiumbrowserbrowsertarget)
|
||||
* [chromiumBrowser.pageTarget(page)](#chromiumbrowserpagetargetpage)
|
||||
* [chromiumBrowser.serviceWorker(target)](#chromiumbrowserserviceworkertarget)
|
||||
@ -53,16 +52,15 @@
|
||||
* [chromiumBrowser.waitForTarget(predicate[, options])](#chromiumbrowserwaitfortargetpredicate-options)
|
||||
- [class: BrowserContext](#class-browsercontext)
|
||||
* [browserContext.clearCookies()](#browsercontextclearcookies)
|
||||
* [browserContext.clearPermissions()](#browsercontextclearpermissions)
|
||||
* [browserContext.close()](#browsercontextclose)
|
||||
* [browserContext.cookies([...urls])](#browsercontextcookiesurls)
|
||||
* [browserContext.newPage()](#browsercontextnewpage)
|
||||
* [browserContext.pages()](#browsercontextpages)
|
||||
* [browserContext.setCookies(cookies)](#browsercontextsetcookiescookies)
|
||||
* [browserContext.setPermissions(origin, permissions[])](#browsercontextsetpermissionsorigin-permissions)
|
||||
- [class: ChromiumOverrides](#class-chromiumoverrides)
|
||||
* [chromiumOverrides.setGeolocation(options)](#chromiumoverridessetgeolocationoptions)
|
||||
- [class: ChromiumPermissions](#class-chromiumpermissions)
|
||||
* [chromiumPermissions.clearOverrides()](#chromiumpermissionsclearoverrides)
|
||||
* [chromiumPermissions.override(origin, permissions)](#chromiumpermissionsoverrideorigin-permissions)
|
||||
- [class: Page](#class-page)
|
||||
* [event: 'close'](#event-close)
|
||||
* [event: 'console'](#event-console)
|
||||
@ -159,7 +157,7 @@
|
||||
- [class: ChromiumPDF](#class-chromiumpdf)
|
||||
* [chromiumPDF.generate([options])](#chromiumpdfgenerateoptions)
|
||||
- [class: FirefoxBrowser](#class-firefoxbrowser)
|
||||
* [firefoxBrowser.wsEndpoint()](#firefoxbrowserwsendpoint)
|
||||
- [class: WebKitBrowser](#class-webkitbrowser)
|
||||
- [class: Dialog](#class-dialog)
|
||||
* [dialog.accept([promptText])](#dialogacceptprompttext)
|
||||
* [dialog.defaultValue()](#dialogdefaultvalue)
|
||||
@ -227,22 +225,14 @@
|
||||
* [elementHandle.$$eval(selector, pageFunction[, ...args])](#elementhandleevalselector-pagefunction-args)
|
||||
* [elementHandle.$eval(selector, pageFunction[, ...args])](#elementhandleevalselector-pagefunction-args-1)
|
||||
* [elementHandle.$x(expression)](#elementhandlexexpression)
|
||||
* [elementHandle.asElement()](#elementhandleaselement)
|
||||
* [elementHandle.boundingBox()](#elementhandleboundingbox)
|
||||
* [elementHandle.click([options])](#elementhandleclickoptions)
|
||||
* [elementHandle.contentFrame()](#elementhandlecontentframe)
|
||||
* [elementHandle.dblclick([options])](#elementhandledblclickoptions)
|
||||
* [elementHandle.dispose()](#elementhandledispose)
|
||||
* [elementHandle.evaluate(pageFunction[, ...args])](#elementhandleevaluatepagefunction-args)
|
||||
* [elementHandle.evaluateHandle(pageFunction[, ...args])](#elementhandleevaluatehandlepagefunction-args)
|
||||
* [elementHandle.executionContext()](#elementhandleexecutioncontext)
|
||||
* [elementHandle.fill(value)](#elementhandlefillvalue)
|
||||
* [elementHandle.focus()](#elementhandlefocus)
|
||||
* [elementHandle.getProperties()](#elementhandlegetproperties)
|
||||
* [elementHandle.getProperty(propertyName)](#elementhandlegetpropertypropertyname)
|
||||
* [elementHandle.hover([options])](#elementhandlehoveroptions)
|
||||
* [elementHandle.isIntersectingViewport()](#elementhandleisintersectingviewport)
|
||||
* [elementHandle.jsonValue()](#elementhandlejsonvalue)
|
||||
* [elementHandle.press(key[, options])](#elementhandlepresskey-options)
|
||||
* [elementHandle.screenshot([options])](#elementhandlescreenshotoptions)
|
||||
* [elementHandle.select(...values)](#elementhandleselectvalues)
|
||||
@ -454,6 +444,102 @@ const browser = await playwright.launch({
|
||||
>
|
||||
> 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.
|
||||
|
||||
### class: Browser
|
||||
|
||||
* 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).
|
||||
|
||||
An example of using a [Browser] to create a [Page]:
|
||||
```js
|
||||
const playwright = require('playwright');
|
||||
|
||||
(async () => {
|
||||
const browser = await playwright.launch();
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
await page.goto('https://example.com');
|
||||
await browser.close();
|
||||
})();
|
||||
```
|
||||
|
||||
An example of disconnecting from and reconnecting to a [Browser]:
|
||||
```js
|
||||
const playwright = require('playwright');
|
||||
|
||||
(async () => {
|
||||
const browserServer = await playwright.launchServer();
|
||||
const browserWSEndpoint = browserServer.wsEndpoint();
|
||||
// Use the endpoint to establish a connection
|
||||
const browser = await playwright.connect({browserWSEndpoint});
|
||||
// Close Chromium
|
||||
await browser.close();
|
||||
})();
|
||||
```
|
||||
|
||||
#### event: 'disconnected'
|
||||
Emitted when Playwright gets disconnected from the Chromium instance. This might happen because of one of the following:
|
||||
- Chromium is closed or crashed
|
||||
- The [`browser.disconnect`](#browserdisconnect) method was called
|
||||
|
||||
#### browser.browserContexts()
|
||||
- returns: <[Array]<[BrowserContext]>>
|
||||
|
||||
Returns an array of all open browser contexts. In a newly created browser, this will return
|
||||
a single instance of [BrowserContext].
|
||||
|
||||
#### browser.close()
|
||||
- returns: <[Promise]>
|
||||
|
||||
Closes Chromium and all of its pages (if any were opened). The [Browser] object itself is considered to be disposed and cannot be used anymore.
|
||||
|
||||
#### browser.defaultContext()
|
||||
- returns: <[BrowserContext]>
|
||||
|
||||
Returns the default browser context. The default browser context can not be closed.
|
||||
|
||||
#### browser.disconnect()
|
||||
|
||||
Disconnects Playwright from the browser, but leaves the Chromium process running. After calling `disconnect`, the [Browser] object is considered disposed and cannot be used anymore.
|
||||
|
||||
#### browser.isConnected()
|
||||
|
||||
- returns: <[boolean]>
|
||||
|
||||
Indicates that the browser is connected.
|
||||
|
||||
#### browser.newContext(options)
|
||||
- `options` <[Object]>
|
||||
- `ignoreHTTPSErrors` <?[boolean]> Whether to ignore HTTPS errors during navigation. Defaults to `false`.
|
||||
- `bypassCSP` <?[boolean]> Toggles bypassing page's Content-Security-Policy.
|
||||
- `viewport` <?[Object]> Sets a consistent viewport for each page. Defaults to an 800x600 viewport. `null` disables the default viewport.
|
||||
- `width` <[number]> page width in pixels.
|
||||
- `height` <[number]> page height in pixels.
|
||||
- `deviceScaleFactor` <[number]> Specify device scale factor (can be thought of as dpr). Defaults to `1`.
|
||||
- `isMobile` <[boolean]> Whether the `meta viewport` tag is taken into account. Defaults to `false`.
|
||||
- `hasTouch`<[boolean]> Specifies if viewport supports touch events. Defaults to `false`
|
||||
- `isLandscape` <[boolean]> Specifies if viewport is in landscape mode. Defaults to `false`.
|
||||
- `userAgent` <?[string]> Specific user agent to use in this page
|
||||
- `mediaType` <?[string]> Changes the CSS media type of the page. The only allowed values are `'screen'`, `'print'` and `null`. Passing `null` disables CSS media emulation.
|
||||
- `colorScheme` <?"dark"|"light"|"no-preference"> Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`.
|
||||
- `javaScriptEnabled` <?[boolean]> Whether or not to enable or disable JavaScript in the page. Defaults to true.
|
||||
- `timezoneId` <?[string]> Changes the timezone of the page. See [ICU’s `metaZones.txt`](https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1) for a list of supported timezone IDs.
|
||||
- returns: <[Promise]<[BrowserContext]>>
|
||||
|
||||
Creates a new browser context. It won't share cookies/cache with other browser contexts.
|
||||
|
||||
```js
|
||||
(async () => {
|
||||
const browser = await playwright.launch();
|
||||
// Create a new incognito browser context.
|
||||
const context = await browser.newContext();
|
||||
// Create a new page in a pristine context.
|
||||
const page = await context.newPage();
|
||||
// Do stuff
|
||||
await page.goto('https://example.com');
|
||||
})();
|
||||
```
|
||||
|
||||
### class: BrowserFetcher
|
||||
|
||||
BrowserFetcher can download and manage different versions of Chromium.
|
||||
@ -535,51 +621,17 @@ Learn more about the [devtools protocol](https://chromedevtools.github.io/devtoo
|
||||
|
||||
### class: ChromiumBrowser
|
||||
|
||||
* extends: [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter)
|
||||
|
||||
A Browser is created when Playwright connects to a Chromium instance, either through [`playwright.launch`](#playwrightlaunchoptions) or [`playwright.connect`](#playwrightconnectoptions).
|
||||
|
||||
An example of using a [Browser] to create a [Page]:
|
||||
```js
|
||||
const playwright = require('playwright');
|
||||
|
||||
(async () => {
|
||||
const browser = await playwright.launch();
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
await page.goto('https://example.com');
|
||||
await browser.close();
|
||||
})();
|
||||
```
|
||||
|
||||
An example of disconnecting from and reconnecting to a [Browser]:
|
||||
```js
|
||||
const playwright = require('playwright');
|
||||
|
||||
(async () => {
|
||||
const browserServer = await playwright.launchServer();
|
||||
const browserWSEndpoint = browserServer.wsEndpoint();
|
||||
// Use the endpoint to establish a connection
|
||||
const browser = await playwright.connect({browserWSEndpoint});
|
||||
// Close Chromium
|
||||
await browser.close();
|
||||
})();
|
||||
```
|
||||
* extends: [Browser]
|
||||
|
||||
Chromium-specific features including Tracing, service worker support, etc.
|
||||
You can use [`chromium.startTracing`](#chromiumstarttracingpage-options) and [`chromium.stopTracing`](#chromiumstoptracing) to create a trace file which can be opened in Chrome DevTools or [timeline viewer](https://chromedevtools.github.io/timeline-viewer/).
|
||||
You can use [`chromiumBrowser.startTracing`](#chromiumbrowserstarttracingpage-options) and [`chromiumBrowser.stopTracing`](#chromiumbrowserstoptracing) to create a trace file which can be opened in Chrome DevTools or [timeline viewer](https://chromedevtools.github.io/timeline-viewer/).
|
||||
|
||||
```js
|
||||
await browser.chromium.startTracing(page, {path: 'trace.json'});
|
||||
await browser.startTracing(page, {path: 'trace.json'});
|
||||
await page.goto('https://www.google.com');
|
||||
await browser.chromium.stopTracing();
|
||||
await browser.stopTracing();
|
||||
```
|
||||
|
||||
#### event: 'disconnected'
|
||||
Emitted when Playwright gets disconnected from the Chromium instance. This might happen because of one of the following:
|
||||
- Chromium is closed or crashed
|
||||
- The [`browser.disconnect`](#browserdisconnect) method was called
|
||||
|
||||
#### event: 'targetchanged'
|
||||
- <[Target]>
|
||||
|
||||
@ -602,71 +654,6 @@ Emitted when a target is destroyed, for example when a page is closed.
|
||||
|
||||
> **NOTE** This includes target destructions in incognito browser contexts.
|
||||
|
||||
#### chromiumBrowser.browserContexts()
|
||||
- returns: <[Array]<[BrowserContext]>>
|
||||
|
||||
Returns an array of all open browser contexts. In a newly created browser, this will return
|
||||
a single instance of [BrowserContext].
|
||||
|
||||
#### chromiumBrowser.chromium
|
||||
- returns: <[Chromium]>
|
||||
|
||||
#### chromiumBrowser.close()
|
||||
- returns: <[Promise]>
|
||||
|
||||
Closes Chromium and all of its pages (if any were opened). The [Browser] object itself is considered to be disposed and cannot be used anymore.
|
||||
|
||||
#### chromiumBrowser.defaultContext()
|
||||
- returns: <[BrowserContext]>
|
||||
|
||||
Returns the default browser context. The default browser context can not be closed.
|
||||
|
||||
#### chromiumBrowser.disconnect()
|
||||
|
||||
Disconnects Playwright from the browser, but leaves the Chromium process running. After calling `disconnect`, the [Browser] object is considered disposed and cannot be used anymore.
|
||||
|
||||
#### chromiumBrowser.isConnected()
|
||||
|
||||
- returns: <[boolean]>
|
||||
|
||||
Indicates that the browser is connected.
|
||||
|
||||
#### chromiumBrowser.newContext(options)
|
||||
- `options` <[Object]>
|
||||
- `ignoreHTTPSErrors` <?[boolean]> Whether to ignore HTTPS errors during navigation. Defaults to `false`.
|
||||
- `bypassCSP` <?[boolean]> Toggles bypassing page's Content-Security-Policy.
|
||||
- `viewport` <?[Object]> Sets a consistent viewport for each page. Defaults to an 800x600 viewport. `null` disables the default viewport.
|
||||
- `width` <[number]> page width in pixels.
|
||||
- `height` <[number]> page height in pixels.
|
||||
- `deviceScaleFactor` <[number]> Specify device scale factor (can be thought of as dpr). Defaults to `1`.
|
||||
- `isMobile` <[boolean]> Whether the `meta viewport` tag is taken into account. Defaults to `false`.
|
||||
- `hasTouch`<[boolean]> Specifies if viewport supports touch events. Defaults to `false`
|
||||
- `isLandscape` <[boolean]> Specifies if viewport is in landscape mode. Defaults to `false`.
|
||||
- `userAgent` <?[string]> Specific user agent to use in this page
|
||||
- `mediaType` <?[string]> Changes the CSS media type of the page. The only allowed values are `'screen'`, `'print'` and `null`. Passing `null` disables CSS media emulation.
|
||||
- `colorScheme` <?"dark"|"light"|"no-preference"> Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`.
|
||||
- `javaScriptEnabled` <?[boolean]> Whether or not to enable or disable JavaScript in the page. Defaults to true.
|
||||
- `timezoneId` <?[string]> Changes the timezone of the page. See [ICU’s `metaZones.txt`](https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1) for a list of supported timezone IDs.
|
||||
|
||||
- returns: <[Promise]<[BrowserContext]>>
|
||||
|
||||
Creates a new browser context. It won't share cookies/cache with other browser contexts.
|
||||
|
||||
```js
|
||||
(async () => {
|
||||
const browser = await playwright.launch();
|
||||
// Create a new incognito browser context.
|
||||
const context = await browser.newContext();
|
||||
// Create a new page in a pristine context.
|
||||
const page = await context.newPage();
|
||||
// Do stuff
|
||||
await page.goto('https://example.com');
|
||||
})();
|
||||
```
|
||||
|
||||
#### chromiumBrowser.process()
|
||||
- returns: <?[ChildProcess]> Spawned browser process. Returns `null` if the browser instance was created with [`playwright.connect`](#playwrightconnectoptions) method.
|
||||
|
||||
#### chromiumBrowser.browserTarget()
|
||||
- returns: <[Target]>
|
||||
|
||||
@ -744,6 +731,18 @@ await context.close();
|
||||
|
||||
Clears context bookies.
|
||||
|
||||
#### browserContext.clearPermissions()
|
||||
- returns: <[Promise]>
|
||||
|
||||
Clears all permission overrides for the browser context.
|
||||
|
||||
```js
|
||||
const context = browser.defaultContext();
|
||||
context.setPermissions('https://example.com', ['clipboard-read']);
|
||||
// do stuff ..
|
||||
context.clearPermissions();
|
||||
```
|
||||
|
||||
#### browserContext.close()
|
||||
- returns: <[Promise]>
|
||||
|
||||
@ -798,38 +797,7 @@ An array of all pages inside the browser context.
|
||||
await browserContext.setCookies([cookieObject1, cookieObject2]);
|
||||
```
|
||||
|
||||
### class: ChromiumOverrides
|
||||
|
||||
#### chromiumOverrides.setGeolocation(options)
|
||||
- `options` <[Object]>
|
||||
- `latitude` <[number]> Latitude between -90 and 90.
|
||||
- `longitude` <[number]> Longitude between -180 and 180.
|
||||
- `accuracy` <[number]> Optional non-negative accuracy value.
|
||||
- returns: <[Promise]>
|
||||
|
||||
Sets the page's geolocation.
|
||||
|
||||
```js
|
||||
await browserContext.overrides.setGeolocation({latitude: 59.95, longitude: 30.31667});
|
||||
```
|
||||
|
||||
> **NOTE** Consider using [browserContext.permissions.override](#permissionsoverrideorigin-permissions) to grant permissions for the page to read its geolocation.
|
||||
|
||||
### class: ChromiumPermissions
|
||||
|
||||
#### chromiumPermissions.clearOverrides()
|
||||
- returns: <[Promise]>
|
||||
|
||||
Clears all permission overrides for the browser context.
|
||||
|
||||
```js
|
||||
const context = browser.defaultContext();
|
||||
context.permissions.override('https://example.com', ['clipboard-read']);
|
||||
// do stuff ..
|
||||
context.permissions.clearOverrides();
|
||||
```
|
||||
|
||||
#### chromiumPermissions.override(origin, permissions)
|
||||
#### browserContext.setPermissions(origin, permissions[])
|
||||
- `origin` <[string]> The [origin] to grant permissions to, e.g. "https://example.com".
|
||||
- `permissions` <[Array]<[string]>> An array of permissions to grant. All permissions that are not listed here will be automatically denied. Permissions can be one of the following values:
|
||||
- `'geolocation'`
|
||||
@ -853,9 +821,26 @@ context.permissions.clearOverrides();
|
||||
|
||||
```js
|
||||
const context = browser.defaultContext();
|
||||
await context.permissions.override('https://html5demos.com', ['geolocation']);
|
||||
await context.setPermissions('https://html5demos.com', ['geolocation']);
|
||||
```
|
||||
|
||||
### class: ChromiumOverrides
|
||||
|
||||
#### chromiumOverrides.setGeolocation(options)
|
||||
- `options` <[Object]>
|
||||
- `latitude` <[number]> Latitude between -90 and 90.
|
||||
- `longitude` <[number]> Longitude between -180 and 180.
|
||||
- `accuracy` <[number]> Optional non-negative accuracy value.
|
||||
- returns: <[Promise]>
|
||||
|
||||
Sets the page's geolocation.
|
||||
|
||||
```js
|
||||
await browserContext.overrides.setGeolocation({latitude: 59.95, longitude: 30.31667});
|
||||
```
|
||||
|
||||
> **NOTE** Consider using [browserContext.setPermissions](#browsercontextsetpermissions-permissions) to grant permissions for the page to read its geolocation.
|
||||
|
||||
### class: Page
|
||||
|
||||
* extends: [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter)
|
||||
@ -2180,12 +2165,15 @@ The `format` options are:
|
||||
|
||||
### class: FirefoxBrowser
|
||||
|
||||
* extends: [Browser]
|
||||
|
||||
Firefox-specific features.
|
||||
|
||||
#### firefoxBrowser.wsEndpoint()
|
||||
- returns: <[string]> Browser websocket url.
|
||||
### class: WebKitBrowser
|
||||
|
||||
Browser websocket endpoint which can be used as an argument to [playwright.connect](#playwrightconnectoptions).
|
||||
* extends: [Browser]
|
||||
|
||||
WebKit-specific features.
|
||||
|
||||
### class: Dialog
|
||||
|
||||
@ -3045,9 +3033,6 @@ expect(await tweetHandle.$eval('.retweets', node => node.innerText)).toBe('10');
|
||||
|
||||
The method evaluates the XPath expression relative to the elementHandle. If there are no such elements, the method will resolve to an empty array.
|
||||
|
||||
#### elementHandle.asElement()
|
||||
- returns: <[ElementHandle]>
|
||||
|
||||
#### elementHandle.boundingBox()
|
||||
- returns: <[Promise]<?[Object]>>
|
||||
- x <[number]> the x coordinate of the element in pixels.
|
||||
@ -3091,42 +3076,6 @@ Bear in mind that if the first click of the `dblclick()` triggers a navigation e
|
||||
|
||||
> **NOTE** `elementHandle.dblclick()` dispatches two `click` events and a single `dblclick` event.
|
||||
|
||||
#### elementHandle.dispose()
|
||||
- returns: <[Promise]> Promise which resolves when the element handle is successfully disposed.
|
||||
|
||||
The `elementHandle.dispose` method stops referencing the element handle.
|
||||
|
||||
#### elementHandle.evaluate(pageFunction[, ...args])
|
||||
- `pageFunction` <[function]\([Object]\)> Function to be evaluated in browser context
|
||||
- `...args` <...[Serializable]|[JSHandle]> Arguments to pass to `pageFunction`
|
||||
- returns: <[Promise]<[Serializable]>> Promise which resolves to the return value of `pageFunction`
|
||||
|
||||
This method passes this handle as the first argument to `pageFunction`.
|
||||
|
||||
If `pageFunction` returns a [Promise], then `handle.evaluate` would wait for the promise to resolve and return its value.
|
||||
|
||||
Examples:
|
||||
```js
|
||||
const tweetHandle = await page.$('.tweet .retweets');
|
||||
expect(await tweetHandle.evaluate(node => node.innerText)).toBe('10');
|
||||
```
|
||||
|
||||
#### elementHandle.evaluateHandle(pageFunction[, ...args])
|
||||
- `pageFunction` <[function]|[string]> Function to be evaluated
|
||||
- `...args` <...[Serializable]|[JSHandle]> Arguments to pass to `pageFunction`
|
||||
- returns: <[Promise]<[JSHandle]>> Promise which resolves to the return value of `pageFunction` as in-page object (JSHandle)
|
||||
|
||||
This method passes this handle as the first argument to `pageFunction`.
|
||||
|
||||
The only difference between `evaluateHandle.evaluate` and `evaluateHandle.evaluateHandle` is that `executionContext.evaluateHandle` returns in-page object (JSHandle).
|
||||
|
||||
If the function passed to the `evaluateHandle.evaluateHandle` returns a [Promise], then `evaluateHandle.evaluateHandle` would wait for the promise to resolve and return its value.
|
||||
|
||||
See [Page.evaluateHandle](#pageevaluatehandlepagefunction-args) for more details.
|
||||
|
||||
#### elementHandle.executionContext()
|
||||
- returns: <[ExecutionContext]>
|
||||
|
||||
#### elementHandle.fill(value)
|
||||
- `value` <[string]> Value to set for the `<input>`, `<textarea>` or `[contenteditable]` element.
|
||||
- returns: <[Promise]> Promise which resolves when the element is successfully filled.
|
||||
@ -3139,29 +3088,6 @@ If element is not a text `<input>`, `<textarea>` or `[contenteditable]` element,
|
||||
|
||||
Calls [focus](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) on the element.
|
||||
|
||||
#### elementHandle.getProperties()
|
||||
- returns: <[Promise]<[Map]<[string], [JSHandle]>>>
|
||||
|
||||
The method returns a map with property names as keys and JSHandle instances for the property values.
|
||||
|
||||
```js
|
||||
const listHandle = await page.evaluateHandle(() => document.body.children);
|
||||
const properties = await listHandle.getProperties();
|
||||
const children = [];
|
||||
for (const property of properties.values()) {
|
||||
const element = property.asElement();
|
||||
if (element)
|
||||
children.push(element);
|
||||
}
|
||||
children; // holds elementHandles to all children of document.body
|
||||
```
|
||||
|
||||
#### elementHandle.getProperty(propertyName)
|
||||
- `propertyName` <[string]> property to get
|
||||
- returns: <[Promise]<[JSHandle]>>
|
||||
|
||||
Fetches a single property from the objectHandle.
|
||||
|
||||
#### elementHandle.hover([options])
|
||||
- `options` <[Object]>
|
||||
- `relativePoint` <[Object]> A point to hover relative to the top-left corner of element padding box. If not specified, hovers over some visible point of the element.
|
||||
@ -3176,13 +3102,6 @@ If the element is detached from DOM, the method throws an error.
|
||||
#### elementHandle.isIntersectingViewport()
|
||||
- returns: <[Promise]<[boolean]>> Resolves to true if the element is visible in the current viewport.
|
||||
|
||||
#### elementHandle.jsonValue()
|
||||
- returns: <[Promise]<[Object]>>
|
||||
|
||||
Returns a JSON representation of the object. The JSON is generated by running [`JSON.stringify`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) on the object in page and consequent [`JSON.parse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse) in playwright.
|
||||
|
||||
> **NOTE** The method will throw if the referenced object is not stringifiable.
|
||||
|
||||
#### elementHandle.press(key[, options])
|
||||
- `key` <[string]> Name of key to press, such as `ArrowLeft`. See [USKeyboardLayout] for a list of all key names.
|
||||
- `options` <[Object]>
|
||||
|
@ -3,15 +3,16 @@
|
||||
|
||||
import { BrowserContext, BrowserContextOptions } from './browserContext';
|
||||
import { ChildProcess } from 'child_process';
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
export interface Browser {
|
||||
newContext(options?: BrowserContextOptions): Promise<BrowserContext>;
|
||||
disconnect(): void;
|
||||
isConnected(): boolean;
|
||||
export class Browser extends EventEmitter {
|
||||
newContext(options?: BrowserContextOptions): Promise<BrowserContext> { throw new Error('Not implemented'); }
|
||||
browserContexts(): BrowserContext[] { throw new Error('Not implemented'); }
|
||||
defaultContext(): BrowserContext { throw new Error('Not implemented'); }
|
||||
|
||||
browserContexts(): BrowserContext[];
|
||||
defaultContext(): BrowserContext;
|
||||
close(): Promise<void>;
|
||||
disconnect(): void { throw new Error('Not implemented'); }
|
||||
isConnected(): boolean { throw new Error('Not implemented'); }
|
||||
close(): Promise<void> { throw new Error('Not implemented'); }
|
||||
}
|
||||
|
||||
export class BrowserServer<T extends Browser> {
|
||||
|
@ -24,9 +24,13 @@ export interface BrowserContextDelegate {
|
||||
pages(): Promise<Page[]>;
|
||||
newPage(): Promise<Page>;
|
||||
close(): Promise<void>;
|
||||
|
||||
cookies(): Promise<network.NetworkCookie[]>;
|
||||
clearCookies(): Promise<void>;
|
||||
setCookies(cookies: network.SetNetworkCookieParam[]): Promise<void>;
|
||||
clearCookies(): Promise<void>;
|
||||
|
||||
setPermissions(origin: string, permissions: string[]): Promise<void>;
|
||||
clearPermissions(): Promise<void>;
|
||||
}
|
||||
|
||||
export type BrowserContextOptions = {
|
||||
@ -64,12 +68,20 @@ export class BrowserContext {
|
||||
return network.filterCookies(await this._delegate.cookies(), urls);
|
||||
}
|
||||
|
||||
async setCookies(cookies: network.SetNetworkCookieParam[]) {
|
||||
await this._delegate.setCookies(network.rewriteCookies(cookies));
|
||||
}
|
||||
|
||||
async clearCookies() {
|
||||
await this._delegate.clearCookies();
|
||||
}
|
||||
|
||||
async setCookies(cookies: network.SetNetworkCookieParam[]) {
|
||||
await this._delegate.setCookies(network.rewriteCookies(cookies));
|
||||
async setPermissions(origin: string, permissions: string[]): Promise<void> {
|
||||
await this._delegate.setPermissions(origin, permissions);
|
||||
}
|
||||
|
||||
async clearPermissions() {
|
||||
await this._delegate.clearPermissions();
|
||||
}
|
||||
|
||||
async close() {
|
||||
|
@ -10,5 +10,4 @@ export { CRCoverage as ChromiumCoverage } from './features/crCoverage';
|
||||
export { CRInterception as ChromiumInterception } from './features/crInterception';
|
||||
export { CROverrides as ChromiumOverrides } from './features/crOverrides';
|
||||
export { CRPDF as ChromiumPDF } from './features/crPdf';
|
||||
export { CRPermissions as ChromiumPermissions } from './features/crPermissions';
|
||||
export { CRWorker as ChromiumWorker, CRWorkers as ChromiumWorkers } from './features/crWorkers';
|
||||
|
@ -27,13 +27,12 @@ import { Protocol } from './protocol';
|
||||
import { CRFrameManager } from './crFrameManager';
|
||||
import * as browser from '../browser';
|
||||
import * as network from '../network';
|
||||
import { CRPermissions } from './features/crPermissions';
|
||||
import { CROverrides } from './features/crOverrides';
|
||||
import { CRWorker } from './features/crWorkers';
|
||||
import { ConnectionTransport } from '../transport';
|
||||
import { readProtocolStream } from './crProtocolHelper';
|
||||
|
||||
export class CRBrowser extends EventEmitter implements browser.Browser {
|
||||
export class CRBrowser extends browser.Browser {
|
||||
_connection: CRConnection;
|
||||
_client: CRSession;
|
||||
private _defaultContext: BrowserContext;
|
||||
@ -129,9 +128,41 @@ export class CRBrowser extends EventEmitter implements browser.Browser {
|
||||
setCookies: async (cookies: network.SetNetworkCookieParam[]): Promise<void> => {
|
||||
await this._client.send('Storage.setCookies', { cookies, browserContextId: contextId || undefined });
|
||||
},
|
||||
|
||||
setPermissions: async (origin: string, permissions: string[]): Promise<void> => {
|
||||
const webPermissionToProtocol = new Map<string, Protocol.Browser.PermissionType>([
|
||||
['geolocation', 'geolocation'],
|
||||
['midi', 'midi'],
|
||||
['notifications', 'notifications'],
|
||||
['camera', 'videoCapture'],
|
||||
['microphone', 'audioCapture'],
|
||||
['background-sync', 'backgroundSync'],
|
||||
['ambient-light-sensor', 'sensors'],
|
||||
['accelerometer', 'sensors'],
|
||||
['gyroscope', 'sensors'],
|
||||
['magnetometer', 'sensors'],
|
||||
['accessibility-events', 'accessibilityEvents'],
|
||||
['clipboard-read', 'clipboardReadWrite'],
|
||||
['clipboard-write', 'clipboardSanitizedWrite'],
|
||||
['payment-handler', 'paymentHandler'],
|
||||
// chrome-specific permissions we have.
|
||||
['midi-sysex', 'midiSysex'],
|
||||
]);
|
||||
const filtered = permissions.map(permission => {
|
||||
const protocolPermission = webPermissionToProtocol.get(permission);
|
||||
if (!protocolPermission)
|
||||
throw new Error('Unknown permission: ' + permission);
|
||||
return protocolPermission;
|
||||
});
|
||||
await this._client.send('Browser.grantPermissions', { origin, browserContextId: contextId || undefined, permissions: filtered });
|
||||
},
|
||||
|
||||
clearPermissions: async () => {
|
||||
await this._client.send('Browser.resetPermissions', { browserContextId: contextId || undefined });
|
||||
}
|
||||
|
||||
}, options);
|
||||
overrides = new CROverrides(context);
|
||||
(context as any).permissions = new CRPermissions(this._client, contextId);
|
||||
(context as any).overrides = overrides;
|
||||
return context;
|
||||
}
|
||||
@ -161,7 +192,7 @@ export class CRBrowser extends EventEmitter implements browser.Browser {
|
||||
this._targets.set(event.targetInfo.targetId, target);
|
||||
|
||||
if (target._isInitialized || await target._initializedPromise)
|
||||
this.emit(Events.Browser.TargetCreated, target);
|
||||
this.emit(Events.CRBrowser.TargetCreated, target);
|
||||
}
|
||||
|
||||
async _targetDestroyed(event: { targetId: string; }) {
|
||||
@ -170,7 +201,7 @@ export class CRBrowser extends EventEmitter implements browser.Browser {
|
||||
this._targets.delete(event.targetId);
|
||||
target._didClose();
|
||||
if (await target._initializedPromise)
|
||||
this.emit(Events.Browser.TargetDestroyed, target);
|
||||
this.emit(Events.CRBrowser.TargetDestroyed, target);
|
||||
}
|
||||
|
||||
_targetInfoChanged(event: Protocol.Target.targetInfoChangedPayload) {
|
||||
@ -180,7 +211,7 @@ export class CRBrowser extends EventEmitter implements browser.Browser {
|
||||
const wasInitialized = target._isInitialized;
|
||||
target._targetInfoChanged(event.targetInfo);
|
||||
if (wasInitialized && previousURL !== target.url())
|
||||
this.emit(Events.Browser.TargetChanged, target);
|
||||
this.emit(Events.CRBrowser.TargetChanged, target);
|
||||
}
|
||||
|
||||
async _closePage(page: Page) {
|
||||
@ -204,15 +235,15 @@ export class CRBrowser extends EventEmitter implements browser.Browser {
|
||||
return existingTarget;
|
||||
let resolve: (target: CRTarget) => void;
|
||||
const targetPromise = new Promise<CRTarget>(x => resolve = x);
|
||||
this.on(Events.Browser.TargetCreated, check);
|
||||
this.on(Events.Browser.TargetChanged, check);
|
||||
this.on(Events.CRBrowser.TargetCreated, check);
|
||||
this.on(Events.CRBrowser.TargetChanged, check);
|
||||
try {
|
||||
if (!timeout)
|
||||
return await targetPromise;
|
||||
return await helper.waitWithTimeout(targetPromise, 'target', timeout);
|
||||
} finally {
|
||||
this.removeListener(Events.Browser.TargetCreated, check);
|
||||
this.removeListener(Events.Browser.TargetChanged, check);
|
||||
this.removeListener(Events.CRBrowser.TargetCreated, check);
|
||||
this.removeListener(Events.CRBrowser.TargetChanged, check);
|
||||
}
|
||||
|
||||
function check(target: CRTarget) {
|
||||
|
@ -16,13 +16,13 @@
|
||||
*/
|
||||
|
||||
export const Events = {
|
||||
Browser: {
|
||||
CRBrowser: {
|
||||
TargetCreated: 'targetcreated',
|
||||
TargetDestroyed: 'targetdestroyed',
|
||||
TargetChanged: 'targetchanged',
|
||||
},
|
||||
|
||||
Workers: {
|
||||
CRWorkers: {
|
||||
WorkerCreated: 'workercreated',
|
||||
WorkerDestroyed: 'workerdestroyed',
|
||||
}
|
||||
|
@ -1,61 +0,0 @@
|
||||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
* Modifications 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 { Protocol } from '../protocol';
|
||||
import { CRSession } from '../crConnection';
|
||||
|
||||
export class CRPermissions {
|
||||
private _client: CRSession;
|
||||
private _browserContextId: string;
|
||||
|
||||
constructor(client: CRSession, browserContextId: string | null) {
|
||||
this._client = client;
|
||||
this._browserContextId = browserContextId;
|
||||
}
|
||||
|
||||
async override(origin: string, permissions: string[]) {
|
||||
const webPermissionToProtocol = new Map<string, Protocol.Browser.PermissionType>([
|
||||
['geolocation', 'geolocation'],
|
||||
['midi', 'midi'],
|
||||
['notifications', 'notifications'],
|
||||
['camera', 'videoCapture'],
|
||||
['microphone', 'audioCapture'],
|
||||
['background-sync', 'backgroundSync'],
|
||||
['ambient-light-sensor', 'sensors'],
|
||||
['accelerometer', 'sensors'],
|
||||
['gyroscope', 'sensors'],
|
||||
['magnetometer', 'sensors'],
|
||||
['accessibility-events', 'accessibilityEvents'],
|
||||
['clipboard-read', 'clipboardReadWrite'],
|
||||
['clipboard-write', 'clipboardSanitizedWrite'],
|
||||
['payment-handler', 'paymentHandler'],
|
||||
// chrome-specific permissions we have.
|
||||
['midi-sysex', 'midiSysex'],
|
||||
]);
|
||||
const filtered = permissions.map(permission => {
|
||||
const protocolPermission = webPermissionToProtocol.get(permission);
|
||||
if (!protocolPermission)
|
||||
throw new Error('Unknown permission: ' + permission);
|
||||
return protocolPermission;
|
||||
});
|
||||
await this._client.send('Browser.grantPermissions', {origin, browserContextId: this._browserContextId || undefined, permissions: filtered});
|
||||
}
|
||||
|
||||
async clearOverrides() {
|
||||
await this._client.send('Browser.resetPermissions', {browserContextId: this._browserContextId || undefined});
|
||||
}
|
||||
}
|
@ -41,13 +41,13 @@ export class CRWorkers extends EventEmitter {
|
||||
const session = CRConnection.fromSession(client).session(event.sessionId);
|
||||
const worker = new CRWorker(session, event.targetInfo.url, addToConsole, handleException);
|
||||
this._workers.set(event.sessionId, worker);
|
||||
this.emit(Events.Workers.WorkerCreated, worker);
|
||||
this.emit(Events.CRWorkers.WorkerCreated, worker);
|
||||
});
|
||||
client.on('Target.detachedFromTarget', event => {
|
||||
const worker = this._workers.get(event.sessionId);
|
||||
if (!worker)
|
||||
return;
|
||||
this.emit(Events.Workers.WorkerDestroyed, worker);
|
||||
this.emit(Events.CRWorkers.WorkerDestroyed, worker);
|
||||
this._workers.delete(event.sessionId);
|
||||
});
|
||||
}
|
||||
|
@ -1,49 +0,0 @@
|
||||
/**
|
||||
* Copyright 2018 Google Inc. All rights reserved.
|
||||
* Modifications 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 { FFConnection } from '../ffConnection';
|
||||
|
||||
export class FFPermissions {
|
||||
private _connection: FFConnection;
|
||||
private _browserContextId: string;
|
||||
|
||||
constructor(connection: FFConnection, browserContextId: string | null) {
|
||||
this._connection = connection;
|
||||
this._browserContextId = browserContextId;
|
||||
}
|
||||
|
||||
|
||||
async override(origin: string, permissions: Array<string>) {
|
||||
const webPermissionToProtocol = new Map([
|
||||
['geolocation', 'geo'],
|
||||
['microphone', 'microphone'],
|
||||
['camera', 'camera'],
|
||||
['notifications', 'desktop-notifications'],
|
||||
]);
|
||||
permissions = permissions.map(permission => {
|
||||
const protocolPermission = webPermissionToProtocol.get(permission);
|
||||
if (!protocolPermission)
|
||||
throw new Error('Unknown permission: ' + permission);
|
||||
return protocolPermission;
|
||||
});
|
||||
await this._connection.send('Browser.grantPermissions', {origin, browserContextId: this._browserContextId || undefined, permissions});
|
||||
}
|
||||
|
||||
async clearOverrides() {
|
||||
await this._connection.send('Browser.resetPermissions', {browserContextId: this._browserContextId || undefined});
|
||||
}
|
||||
}
|
@ -2,6 +2,5 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export { FFInterception as FirefoxInterception } from './features/ffInterception';
|
||||
export { FFPermissions as FirefoxPermissions } from './features/ffPermissions';
|
||||
export { FFBrowser as FirefoxBrowser } from './ffBrowser';
|
||||
export { FFPlaywright as Firefox } from './ffPlaywright';
|
||||
|
@ -15,19 +15,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { EventEmitter } from 'events';
|
||||
import { helper, RegisteredListener, assert } from '../helper';
|
||||
import { FFConnection, ConnectionEvents, FFSessionEvents } from './ffConnection';
|
||||
import { Events } from '../events';
|
||||
import { FFPermissions } from './features/ffPermissions';
|
||||
import { Page } from '../page';
|
||||
import { FFFrameManager } from './ffFrameManager';
|
||||
import * as browser from '../browser';
|
||||
import * as network from '../network';
|
||||
import { BrowserContext, BrowserContextOptions } from '../browserContext';
|
||||
import { Events } from '../events';
|
||||
import { assert, helper, RegisteredListener } from '../helper';
|
||||
import * as network from '../network';
|
||||
import { Page } from '../page';
|
||||
import { ConnectionTransport } from '../transport';
|
||||
import { ConnectionEvents, FFConnection, FFSessionEvents } from './ffConnection';
|
||||
import { FFFrameManager } from './ffFrameManager';
|
||||
|
||||
export class FFBrowser extends EventEmitter implements browser.Browser {
|
||||
export class FFBrowser extends browser.Browser {
|
||||
_connection: FFConnection;
|
||||
_targets: Map<string, Target>;
|
||||
private _defaultContext: BrowserContext;
|
||||
@ -196,8 +194,28 @@ export class FFBrowser extends EventEmitter implements browser.Browser {
|
||||
setCookies: async (cookies: network.SetNetworkCookieParam[]): Promise<void> => {
|
||||
await this._connection.send('Browser.setCookies', { browserContextId: browserContextId || undefined, cookies });
|
||||
},
|
||||
|
||||
setPermissions: async (origin: string, permissions: string[]): Promise<void> => {
|
||||
const webPermissionToProtocol = new Map([
|
||||
['geolocation', 'geo'],
|
||||
['microphone', 'microphone'],
|
||||
['camera', 'camera'],
|
||||
['notifications', 'desktop-notifications'],
|
||||
]);
|
||||
const filtered = permissions.map(permission => {
|
||||
const protocolPermission = webPermissionToProtocol.get(permission);
|
||||
if (!protocolPermission)
|
||||
throw new Error('Unknown permission: ' + permission);
|
||||
return protocolPermission;
|
||||
});
|
||||
await this._connection.send('Browser.grantPermissions', {origin, browserContextId: browserContextId || undefined, permissions: filtered});
|
||||
},
|
||||
|
||||
clearPermissions: async () => {
|
||||
await this._connection.send('Browser.resetPermissions', { browserContextId: browserContextId || undefined });
|
||||
}
|
||||
|
||||
}, options);
|
||||
(context as any).permissions = new FFPermissions(this._connection, browserContextId);
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ import { Events } from '../events';
|
||||
import { BrowserContext, BrowserContextOptions } from '../browserContext';
|
||||
import { ConnectionTransport } from '../transport';
|
||||
|
||||
export class WKBrowser extends EventEmitter implements browser.Browser {
|
||||
export class WKBrowser extends browser.Browser {
|
||||
readonly _connection: WKConnection;
|
||||
private _defaultContext: BrowserContext;
|
||||
private _contexts = new Map<string, BrowserContext>();
|
||||
@ -206,6 +206,14 @@ export class WKBrowser extends EventEmitter implements browser.Browser {
|
||||
const cc = cookies.map(c => ({ ...c, session: c.expires === -1 || c.expires === undefined })) as Protocol.Browser.SetCookieParam[];
|
||||
await this._connection.send('Browser.setCookies', { cookies: cc, browserContextId });
|
||||
},
|
||||
|
||||
setPermissions: async (origin: string, permissions: string[]): Promise<void> => {
|
||||
throw new Error('Permissions are not supported in WebKit');
|
||||
},
|
||||
|
||||
clearPermissions: async () => {
|
||||
throw new Error('Permissions are not supported in WebKit');
|
||||
}
|
||||
}, options);
|
||||
return context;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ module.exports.describe = function ({ testRunner, expect }) {
|
||||
// It was removed from WebKit in https://webkit.org/b/126630
|
||||
describe('Overrides.setGeolocation', function() {
|
||||
it('should work', async({page, server, context}) => {
|
||||
await context.permissions.override(server.PREFIX, ['geolocation']);
|
||||
await context.setPermissions(server.PREFIX, ['geolocation']);
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await context.overrides.setGeolocation({longitude: 10, latitude: 10});
|
||||
const geolocation = await page.evaluate(() => new Promise(resolve => navigator.geolocation.getCurrentPosition(position => {
|
||||
|
@ -35,25 +35,25 @@ module.exports.describe = function({testRunner, expect, WEBKIT}) {
|
||||
});
|
||||
it.skip(WEBKIT)('should deny permission when not listed', async({page, server, context}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await context.permissions.override(server.EMPTY_PAGE, []);
|
||||
await context.setPermissions(server.EMPTY_PAGE, []);
|
||||
expect(await getPermission(page, 'geolocation')).toBe('denied');
|
||||
});
|
||||
it.skip(WEBKIT)('should fail when bad permission is given', async({page, server, context}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
let error = {};
|
||||
await context.permissions.override(server.EMPTY_PAGE, ['foo']).catch(e => error = e);
|
||||
await context.setPermissions(server.EMPTY_PAGE, ['foo']).catch(e => error = e);
|
||||
expect(error.message).toBe('Unknown permission: foo');
|
||||
});
|
||||
it.skip(WEBKIT)('should grant permission when listed', async({page, server, context}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await context.permissions.override(server.EMPTY_PAGE, ['geolocation']);
|
||||
await context.setPermissions(server.EMPTY_PAGE, ['geolocation']);
|
||||
expect(await getPermission(page, 'geolocation')).toBe('granted');
|
||||
});
|
||||
it.skip(WEBKIT)('should reset permissions', async({page, server, context}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await context.permissions.override(server.EMPTY_PAGE, ['geolocation']);
|
||||
await context.setPermissions(server.EMPTY_PAGE, ['geolocation']);
|
||||
expect(await getPermission(page, 'geolocation')).toBe('granted');
|
||||
await context.permissions.clearOverrides();
|
||||
await context.clearPermissions();
|
||||
expect(await getPermission(page, 'geolocation')).toBe('prompt');
|
||||
});
|
||||
it.skip(WEBKIT)('should trigger permission onchange', async({page, server, context}) => {
|
||||
@ -68,11 +68,11 @@ module.exports.describe = function({testRunner, expect, WEBKIT}) {
|
||||
});
|
||||
});
|
||||
expect(await page.evaluate(() => window['events'])).toEqual(['prompt']);
|
||||
await context.permissions.override(server.EMPTY_PAGE, []);
|
||||
await context.setPermissions(server.EMPTY_PAGE, []);
|
||||
expect(await page.evaluate(() => window['events'])).toEqual(['prompt', 'denied']);
|
||||
await context.permissions.override(server.EMPTY_PAGE, ['geolocation']);
|
||||
await context.setPermissions(server.EMPTY_PAGE, ['geolocation']);
|
||||
expect(await page.evaluate(() => window['events'])).toEqual(['prompt', 'denied', 'granted']);
|
||||
await context.permissions.clearOverrides();
|
||||
await context.clearPermissions();
|
||||
expect(await page.evaluate(() => window['events'])).toEqual(['prompt', 'denied', 'granted', 'prompt']);
|
||||
});
|
||||
it.skip(WEBKIT)('should isolate permissions between browser contexs', async({page, server, context, newContext}) => {
|
||||
@ -83,12 +83,12 @@ module.exports.describe = function({testRunner, expect, WEBKIT}) {
|
||||
expect(await getPermission(page, 'geolocation')).toBe('prompt');
|
||||
expect(await getPermission(otherPage, 'geolocation')).toBe('prompt');
|
||||
|
||||
await context.permissions.override(server.EMPTY_PAGE, []);
|
||||
await otherContext.permissions.override(server.EMPTY_PAGE, ['geolocation']);
|
||||
await context.setPermissions(server.EMPTY_PAGE, []);
|
||||
await otherContext.setPermissions(server.EMPTY_PAGE, ['geolocation']);
|
||||
expect(await getPermission(page, 'geolocation')).toBe('denied');
|
||||
expect(await getPermission(otherPage, 'geolocation')).toBe('granted');
|
||||
|
||||
await context.permissions.clearOverrides();
|
||||
await context.clearPermissions();
|
||||
expect(await getPermission(page, 'geolocation')).toBe('prompt');
|
||||
expect(await getPermission(otherPage, 'geolocation')).toBe('granted');
|
||||
});
|
||||
|
@ -37,6 +37,12 @@ Documentation.Class = class {
|
||||
constructor(name, membersArray, extendsName = null, comment = '') {
|
||||
this.name = name;
|
||||
this.membersArray = membersArray;
|
||||
this.comment = comment;
|
||||
this.extends = extendsName;
|
||||
this.index();
|
||||
}
|
||||
|
||||
index() {
|
||||
/** @type {!Map<string, !Documentation.Member>} */
|
||||
this.members = new Map();
|
||||
/** @type {!Map<string, !Documentation.Member>} */
|
||||
@ -51,9 +57,8 @@ Documentation.Class = class {
|
||||
this.events = new Map();
|
||||
/** @type {!Array<!Documentation.Member>} */
|
||||
this.eventsArray = [];
|
||||
this.comment = comment;
|
||||
this.extends = extendsName;
|
||||
for (const member of membersArray) {
|
||||
|
||||
for (const member of this.membersArray) {
|
||||
this.members.set(member.name, member);
|
||||
if (member.kind === 'method') {
|
||||
this.methods.set(member.name, member);
|
||||
|
@ -27,9 +27,9 @@ module.exports = { checkSources, expandPrefix };
|
||||
function checkSources(sources) {
|
||||
// special treatment for Events.js
|
||||
const classEvents = new Map();
|
||||
const eventsSource = sources.find(source => source.name().startsWith('events.'));
|
||||
if (eventsSource) {
|
||||
const {Events} = eventsSource.filePath().endsWith('.js') ? require(eventsSource.filePath()) : require(path.join(eventsSource.filePath(), '..', '..', '..', 'lib', 'chromium', 'events.js'));
|
||||
const eventsSources = sources.filter(source => source.name().startsWith('events.ts'));
|
||||
for (const eventsSource of eventsSources) {
|
||||
const {Events} = require(eventsSource.filePath().endsWith('.js') ? eventsSource.filePath() : eventsSource.filePath().replace('/src/', '/lib/').replace('.ts', '.js'));
|
||||
for (const [className, events] of Object.entries(Events))
|
||||
classEvents.set(className, Array.from(Object.values(events)).filter(e => typeof e === 'string').map(e => Documentation.Member.createEvent(e)));
|
||||
}
|
||||
|
@ -299,6 +299,23 @@ module.exports = async function(page, sources) {
|
||||
errors.push(...outline.errors);
|
||||
}
|
||||
const documentation = new Documentation(classes);
|
||||
|
||||
|
||||
// Push base class documentation to derived classes.
|
||||
for (const [name, clazz] of documentation.classes.entries()) {
|
||||
if (!clazz.extends || clazz.extends === 'EventEmitter' || clazz.extends === 'Error')
|
||||
continue;
|
||||
const superClass = documentation.classes.get(clazz.extends);
|
||||
if (!superClass) {
|
||||
errors.push(`Undefined superclass: ${superClass} in ${name}`);
|
||||
continue;
|
||||
}
|
||||
for (const memberName of clazz.members.keys()) {
|
||||
if (superClass.members.has(memberName))
|
||||
errors.push(`Member documentation overrides base: ${name}.${memberName} over ${clazz.extends}.${memberName}`);
|
||||
}
|
||||
clazz.membersArray = [...clazz.membersArray, ...superClass.membersArray];
|
||||
clazz.index();
|
||||
}
|
||||
return { documentation, errors };
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user