diff --git a/docs/api.md b/docs/api.md index b7317c28912f5..90e61a6371d51 100644 --- a/docs/api.md +++ b/docs/api.md @@ -53,14 +53,16 @@ * [event: 'targetcreated'](#event-targetcreated-1) * [event: 'targetdestroyed'](#event-targetdestroyed-1) * [browserContext.browser()](#browsercontextbrowser) - * [browserContext.clearPermissionOverrides()](#browsercontextclearpermissionoverrides) * [browserContext.close()](#browsercontextclose) * [browserContext.isIncognito()](#browsercontextisincognito) * [browserContext.newPage()](#browsercontextnewpage) - * [browserContext.overridePermissions(origin, permissions)](#browsercontextoverridepermissionsorigin-permissions) * [browserContext.pages()](#browsercontextpages) + * [browserContext.permissions](#browsercontextpermissions) * [browserContext.targets()](#browsercontexttargets) * [browserContext.waitForTarget(predicate[, options])](#browsercontextwaitfortargetpredicate-options) +- [class: Permissions](#class-permissions) + * [permissions.clearOverrides()](#permissionsclearoverrides) + * [permissions.override(origin, permissions)](#permissionsoverrideorigin-permissions) - [class: Page](#class-page) * [event: 'close'](#event-close) * [event: 'console'](#event-console) @@ -828,18 +830,6 @@ Emitted when a target inside the browser context is destroyed, for example when The browser this browser context belongs to. -#### browserContext.clearPermissionOverrides() -- returns: <[Promise]> - -Clears all permission overrides for the browser context. - -```js -const context = browser.defaultBrowserContext(); -context.overridePermissions('https://example.com', ['clipboard-read']); -// do stuff .. -context.clearPermissionOverrides(); -``` - #### browserContext.close() - returns: <[Promise]> @@ -861,8 +851,48 @@ The default browser context is the only non-incognito browser context. Creates a new page in the browser context. +#### browserContext.pages() +- returns: <[Promise]<[Array]<[Page]>>> Promise which resolves to an array of all open pages. Non visible pages, such as `"background_page"`, will not be listed here. You can find them using [target.page()](#targetpage). + +An array of all pages inside the browser context. + +#### browserContext.permissions +- returns: <[Permissions]> + +#### browserContext.targets() +- returns: <[Array]<[Target]>> + +An array of all active targets inside the browser context. + +#### browserContext.waitForTarget(predicate[, options]) +- `predicate` <[function]\([Target]\):[boolean]> A function to be run for every target +- `options` <[Object]> + - `timeout` <[number]> Maximum wait time in milliseconds. Pass `0` to disable the timeout. Defaults to 30 seconds. +- returns: <[Promise]<[Target]>> Promise which resolves to the first target found that matches the `predicate` function. + +This searches for a target in this specific browser context. + +An example of finding a target for a page opened via `window.open`: +```js +await page.evaluate(() => window.open('https://www.example.com/')); +const newWindowTarget = await browserContext.waitForTarget(target => target.url() === 'https://www.example.com/'); +``` + +### class: Permissions -#### browserContext.overridePermissions(origin, permissions) +#### permissions.clearOverrides() +- returns: <[Promise]> + +Clears all permission overrides for the browser context. + +```js +const context = browser.defaultBrowserContext(); +context.permissions.override('https://example.com', ['clipboard-read']); +// do stuff .. +context.permissions.clearOverrides(); +``` + +#### permissions.override(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'` @@ -886,32 +916,7 @@ Creates a new page in the browser context. ```js const context = browser.defaultBrowserContext(); -await context.overridePermissions('https://html5demos.com', ['geolocation']); -``` - - -#### browserContext.pages() -- returns: <[Promise]<[Array]<[Page]>>> Promise which resolves to an array of all open pages. Non visible pages, such as `"background_page"`, will not be listed here. You can find them using [target.page()](#targetpage). - -An array of all pages inside the browser context. - -#### browserContext.targets() -- returns: <[Array]<[Target]>> - -An array of all active targets inside the browser context. - -#### browserContext.waitForTarget(predicate[, options]) -- `predicate` <[function]\([Target]\):[boolean]> A function to be run for every target -- `options` <[Object]> - - `timeout` <[number]> Maximum wait time in milliseconds. Pass `0` to disable the timeout. Defaults to 30 seconds. -- returns: <[Promise]<[Target]>> Promise which resolves to the first target found that matches the `predicate` function. - -This searches for a target in this specific browser context. - -An example of finding a target for a page opened via `window.open`: -```js -await page.evaluate(() => window.open('https://www.example.com/')); -const newWindowTarget = await browserContext.waitForTarget(target => target.url() === 'https://www.example.com/'); +await context.permissions.override('https://html5demos.com', ['geolocation']); ``` ### class: Page @@ -1762,7 +1767,7 @@ Sets the page's geolocation. await page.setGeolocation({latitude: 59.95, longitude: 30.31667}); ``` -> **NOTE** Consider using [browserContext.overridePermissions](#browsercontextoverridepermissionsorigin-permissions) to grant permissions for the page to read its geolocation. +> **NOTE** Consider using [browserContext.permissions.override](#permissionsoverrideorigin-permissions) to grant permissions for the page to read its geolocation. #### page.setJavaScriptEnabled(enabled) - `enabled` <[boolean]> Whether or not to enable JavaScript on the page. diff --git a/src/api.ts b/src/api.ts index 1c318b2d6f771..a3a4a1346dbc0 100644 --- a/src/api.ts +++ b/src/api.ts @@ -33,6 +33,7 @@ export = { Mouse: require('./chromium/Input').Mouse, PDF: require('./chromium/features/pdf').PDF, Page: require('./chromium/Page').Page, + Permissions: require('./chromium/features/permissions').Permissions, Playwright: require('./chromium/Playwright').Playwright, Request: require('./chromium/NetworkManager').Request, Response: require('./chromium/NetworkManager').Response, @@ -45,7 +46,7 @@ export = { Workers: require('./chromium/features/workers').Workers, }, Firefox: { - Accessibility: require('./firefox/Accessibility').Accessibility, + Accessibility: require('./firefox/features/accessibility').Accessibility, Browser: require('./firefox/Browser').Browser, BrowserContext: require('./firefox/Browser').BrowserContext, BrowserFetcher: require('./firefox/BrowserFetcher').BrowserFetcher, @@ -60,6 +61,7 @@ export = { Keyboard: require('./firefox/Input').Keyboard, Mouse: require('./firefox/Input').Mouse, Page: require('./firefox/Page').Page, + Permissions: require('./firefox/features/permissions').Permissions, Playwright: require('./firefox/Playwright').Playwright, Request: require('./firefox/NetworkManager').Request, Response: require('./firefox/NetworkManager').Response, diff --git a/src/chromium/BrowserContext.ts b/src/chromium/BrowserContext.ts index 6b491b2bfbaf3..be05086d4f30e 100644 --- a/src/chromium/BrowserContext.ts +++ b/src/chromium/BrowserContext.ts @@ -19,20 +19,21 @@ import { EventEmitter } from 'events'; import { assert } from '../helper'; import { Browser } from './Browser'; import { Connection } from './Connection'; +import { Permissions } from './features/permissions'; import { Page } from './Page'; import { Target } from './Target'; -import { Protocol } from './protocol'; export class BrowserContext extends EventEmitter { - private _connection: Connection; + readonly permissions: Permissions; + private _browser: Browser; private _id: string; constructor(connection: Connection, browser: Browser, contextId: string | null) { super(); - this._connection = connection; this._browser = browser; this._id = contextId; + this.permissions = new Permissions(connection, contextId); } targets(): Target[] { @@ -56,38 +57,6 @@ export class BrowserContext extends EventEmitter { return !!this._id; } - async overridePermissions(origin: string, permissions: string[]) { - const webPermissionToProtocol = new Map([ - ['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', 'clipboardRead'], - ['clipboard-write', 'clipboardWrite'], - ['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._connection.send('Browser.grantPermissions', {origin, browserContextId: this._id || undefined, permissions: filtered}); - } - - async clearPermissionOverrides() { - await this._connection.send('Browser.resetPermissions', {browserContextId: this._id || undefined}); - } - newPage(): Promise { return this._browser._createPageInContext(this._id); } diff --git a/src/chromium/features/permissions.ts b/src/chromium/features/permissions.ts new file mode 100644 index 0000000000000..8189901efa10f --- /dev/null +++ b/src/chromium/features/permissions.ts @@ -0,0 +1,61 @@ +/** + * 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 { Connection } from './../Connection'; + +export class Permissions { + private _client: Connection; + private _browserContextId: string; + + constructor(connection: Connection, browserContextId: string | null) { + this._client = connection; + this._browserContextId = browserContextId; + } + + async override(origin: string, permissions: string[]) { + const webPermissionToProtocol = new Map([ + ['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', 'clipboardRead'], + ['clipboard-write', 'clipboardWrite'], + ['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}); + } +} diff --git a/src/firefox/Browser.ts b/src/firefox/Browser.ts index a49edc85edbb4..009cd9e542993 100644 --- a/src/firefox/Browser.ts +++ b/src/firefox/Browser.ts @@ -15,11 +15,12 @@ * limitations under the License. */ -import {RegisteredListener, helper, assert} from '../helper'; -import {Page, Viewport} from './Page'; -import {EventEmitter} from 'events'; -import {Connection, ConnectionEvents} from './Connection'; -import {Events} from '../Events'; +import { EventEmitter } from 'events'; +import { Events } from '../Events'; +import { assert, helper, RegisteredListener } from '../helper'; +import { Connection, ConnectionEvents } from './Connection'; +import { Permissions } from './features/permissions'; +import { Page, Viewport } from './Page'; export class Browser extends EventEmitter { private _connection: Connection; @@ -262,36 +263,16 @@ export class BrowserContext extends EventEmitter { _connection: Connection; _browser: Browser; _browserContextId: string; + readonly permissions: Permissions; constructor(connection: Connection, browser: Browser, browserContextId: string | null) { super(); this._connection = connection; this._browser = browser; this._browserContextId = browserContextId; + this.permissions = new Permissions(connection, browserContextId); } - - async overridePermissions(origin: string, permissions: Array) { - 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 clearPermissionOverrides() { - await this._connection.send('Browser.resetPermissions', {browserContextId: this._browserContextId || undefined}); - } - - targets(): Array { return this._browser.targets().filter(target => target.browserContext() === this); } diff --git a/src/firefox/Page.ts b/src/firefox/Page.ts index dc16d9bcc6930..a9022b9afe529 100644 --- a/src/firefox/Page.ts +++ b/src/firefox/Page.ts @@ -13,7 +13,7 @@ import {FrameManager, normalizeWaitUntil, FrameManagerEvents} from './FrameManag import {NetworkManager, Request, Response, NetworkManagerEvents} from './NetworkManager'; import {TimeoutSettings} from '../TimeoutSettings'; import {NavigationWatchdog} from './NavigationWatchdog'; -import {Accessibility} from './Accessibility'; +import {Accessibility} from './features/accessibility'; import { Target, BrowserContext } from './Browser'; import { Events } from '../Events'; @@ -26,7 +26,7 @@ export class Page extends EventEmitter { private _keyboard: Keyboard; private _mouse: Mouse; private _touchscreen: Touchscreen; - private _accessibility: Accessibility; + readonly accessibility: Accessibility; private _closed: boolean; private _pageBindings: Map; private _networkManager: NetworkManager; @@ -56,7 +56,7 @@ export class Page extends EventEmitter { this._keyboard = new Keyboard(session); this._mouse = new Mouse(session, this._keyboard); this._touchscreen = new Touchscreen(session, this._keyboard, this._mouse); - this._accessibility = new Accessibility(session); + this.accessibility = new Accessibility(session); this._closed = false; this._pageBindings = new Map(); this._networkManager = new NetworkManager(session); @@ -334,10 +334,6 @@ export class Page extends EventEmitter { return this._frameManager.mainFrame(); } - get accessibility() { - return this._accessibility; - } - get keyboard(){ return this._keyboard; } diff --git a/src/firefox/Accessibility.ts b/src/firefox/features/accessibility.ts similarity index 99% rename from src/firefox/Accessibility.ts rename to src/firefox/features/accessibility.ts index 5ebb7863fd609..0556b4c1feeba 100644 --- a/src/firefox/Accessibility.ts +++ b/src/firefox/features/accessibility.ts @@ -94,6 +94,7 @@ class AXNode { private _name: string; private _role: string; private _cachedHasFocusableChild: boolean|undefined; + constructor(payload) { this._payload = payload; this._children = (payload.children || []).map(x => new AXNode(x)); @@ -105,6 +106,7 @@ class AXNode { this._role = this._payload.role; this._cachedHasFocusableChild; } + _isPlainTextField(): boolean { if (this._richlyEditable) return false; @@ -112,10 +114,12 @@ class AXNode { return true; return this._role === 'entry'; } + _isTextOnlyObject(): boolean { const role = this._role; return (role === 'text leaf' || role === 'text' || role === 'statictext'); } + _hasFocusableChild(): boolean { if (this._cachedHasFocusableChild === undefined) { this._cachedHasFocusableChild = false; @@ -128,6 +132,7 @@ class AXNode { } return this._cachedHasFocusableChild; } + isLeafNode(): boolean { if (!this._children.length) return true; @@ -160,6 +165,7 @@ class AXNode { return true; return false; } + isControl(): boolean { switch (this._role) { case 'checkbutton': @@ -191,6 +197,7 @@ class AXNode { return false; } } + isInteresting(insideControl: boolean): boolean { if (this._focusable || this._richlyEditable) return true; @@ -202,6 +209,7 @@ class AXNode { return false; return this.isLeafNode() && !!this._name.trim(); } + serialize(): SerializedAXNode { const node: {[x in keyof SerializedAXNode]: any} = { role: this._role diff --git a/src/firefox/features/permissions.ts b/src/firefox/features/permissions.ts new file mode 100644 index 0000000000000..43e69ec95f73b --- /dev/null +++ b/src/firefox/features/permissions.ts @@ -0,0 +1,49 @@ +/** + * 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 { Connection } from '../Connection'; + +export class Permissions { + private _connection: Connection; + private _browserContextId: string; + + constructor(connection: Connection, browserContextId: string | null) { + this._connection = connection; + this._browserContextId = browserContextId; + } + + + async override(origin: string, permissions: Array) { + 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}); + } +} diff --git a/src/chromium/features/accessibility.spec.js b/src/tests/accessibility.spec.js similarity index 100% rename from src/chromium/features/accessibility.spec.js rename to src/tests/accessibility.spec.js diff --git a/src/tests/permissions.spec.js b/src/tests/permissions.spec.js new file mode 100644 index 0000000000000..ce87d1d203f09 --- /dev/null +++ b/src/tests/permissions.spec.js @@ -0,0 +1,97 @@ +/** + * Copyright 2017 Google Inc. All rights reserved. + * + * 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. + */ + +const fs = require('fs'); +const path = require('path'); + +module.exports.addTests = function({testRunner, expect, WEBKIT}) { + const {describe, xdescribe, fdescribe} = testRunner; + const {it, fit, xit} = testRunner; + const {beforeAll, beforeEach, afterAll, afterEach} = testRunner; + + // Permissions API is not implemented in WebKit (see https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API) + describe('Permissions', function() { + function getPermission(page, name) { + return page.evaluate(name => navigator.permissions.query({name}).then(result => result.state), name); + } + + it.skip(WEBKIT)('should be prompt by default', async({page, server, context}) => { + await page.goto(server.EMPTY_PAGE); + expect(await getPermission(page, 'geolocation')).toBe('prompt'); + }); + 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, []); + 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); + 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']); + 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']); + expect(await getPermission(page, 'geolocation')).toBe('granted'); + await context.permissions.clearOverrides(); + expect(await getPermission(page, 'geolocation')).toBe('prompt'); + }); + it.skip(WEBKIT)('should trigger permission onchange', async({page, server, context}) => { + await page.goto(server.EMPTY_PAGE); + await page.evaluate(() => { + window['events'] = []; + return navigator.permissions.query({name: 'geolocation'}).then(function(result) { + window['events'].push(result.state); + result.onchange = function() { + window['events'].push(result.state); + }; + }); + }); + expect(await page.evaluate(() => window['events'])).toEqual(['prompt']); + await context.permissions.override(server.EMPTY_PAGE, []); + expect(await page.evaluate(() => window['events'])).toEqual(['prompt', 'denied']); + await context.permissions.override(server.EMPTY_PAGE, ['geolocation']); + expect(await page.evaluate(() => window['events'])).toEqual(['prompt', 'denied', 'granted']); + await context.permissions.clearOverrides(); + expect(await page.evaluate(() => window['events'])).toEqual(['prompt', 'denied', 'granted', 'prompt']); + }); + it.skip(WEBKIT)('should isolate permissions between browser contexs', async({page, server, context, browser}) => { + await page.goto(server.EMPTY_PAGE); + const otherContext = await browser.createIncognitoBrowserContext(); + const otherPage = await otherContext.newPage(); + await otherPage.goto(server.EMPTY_PAGE); + 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']); + expect(await getPermission(page, 'geolocation')).toBe('denied'); + expect(await getPermission(otherPage, 'geolocation')).toBe('granted'); + + await context.permissions.clearOverrides(); + expect(await getPermission(page, 'geolocation')).toBe('prompt'); + expect(await getPermission(otherPage, 'geolocation')).toBe('granted'); + + await otherContext.close(); + }); + }); +}; diff --git a/test/page.spec.js b/test/page.spec.js index 2bd8e87cadad7..58f8461288a7a 100644 --- a/test/page.spec.js +++ b/test/page.spec.js @@ -166,84 +166,12 @@ module.exports.addTests = function({testRunner, expect, headless, playwright, FF }); }); - // Permissions API is not implemented in WebKit (see https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API) - describe('BrowserContext.overridePermissions', function() { - function getPermission(page, name) { - return page.evaluate(name => navigator.permissions.query({name}).then(result => result.state), name); - } - - it.skip(WEBKIT)('should be prompt by default', async({page, server, context}) => { - await page.goto(server.EMPTY_PAGE); - expect(await getPermission(page, 'geolocation')).toBe('prompt'); - }); - it.skip(WEBKIT)('should deny permission when not listed', async({page, server, context}) => { - await page.goto(server.EMPTY_PAGE); - await context.overridePermissions(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 = null; - await context.overridePermissions(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.overridePermissions(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.overridePermissions(server.EMPTY_PAGE, ['geolocation']); - expect(await getPermission(page, 'geolocation')).toBe('granted'); - await context.clearPermissionOverrides(); - expect(await getPermission(page, 'geolocation')).toBe('prompt'); - }); - it.skip(WEBKIT)('should trigger permission onchange', async({page, server, context}) => { - await page.goto(server.EMPTY_PAGE); - await page.evaluate(() => { - window.events = []; - return navigator.permissions.query({name: 'geolocation'}).then(function(result) { - window.events.push(result.state); - result.onchange = function() { - window.events.push(result.state); - }; - }); - }); - expect(await page.evaluate(() => window.events)).toEqual(['prompt']); - await context.overridePermissions(server.EMPTY_PAGE, []); - expect(await page.evaluate(() => window.events)).toEqual(['prompt', 'denied']); - await context.overridePermissions(server.EMPTY_PAGE, ['geolocation']); - expect(await page.evaluate(() => window.events)).toEqual(['prompt', 'denied', 'granted']); - await context.clearPermissionOverrides(); - expect(await page.evaluate(() => window.events)).toEqual(['prompt', 'denied', 'granted', 'prompt']); - }); - it.skip(WEBKIT)('should isolate permissions between browser contexs', async({page, server, context, browser}) => { - await page.goto(server.EMPTY_PAGE); - const otherContext = await browser.createIncognitoBrowserContext(); - const otherPage = await otherContext.newPage(); - await otherPage.goto(server.EMPTY_PAGE); - expect(await getPermission(page, 'geolocation')).toBe('prompt'); - expect(await getPermission(otherPage, 'geolocation')).toBe('prompt'); - - await context.overridePermissions(server.EMPTY_PAGE, []); - await otherContext.overridePermissions(server.EMPTY_PAGE, ['geolocation']); - expect(await getPermission(page, 'geolocation')).toBe('denied'); - expect(await getPermission(otherPage, 'geolocation')).toBe('granted'); - - await context.clearPermissionOverrides(); - expect(await getPermission(page, 'geolocation')).toBe('prompt'); - expect(await getPermission(otherPage, 'geolocation')).toBe('granted'); - - await otherContext.close(); - }); - }); // FIXME: not supported in WebKit (as well as Emulation domain in general). // It was removed from WebKit in https://webkit.org/b/126630 describe.skip(FFOX || WEBKIT)('Page.setGeolocation', function() { it('should work', async({page, server, context}) => { - await context.overridePermissions(server.PREFIX, ['geolocation']); + await context.permissions.override(server.PREFIX, ['geolocation']); await page.goto(server.EMPTY_PAGE); await page.setGeolocation({longitude: 10, latitude: 10}); const geolocation = await page.evaluate(() => new Promise(resolve => navigator.geolocation.getCurrentPosition(position => { diff --git a/test/playwright.spec.js b/test/playwright.spec.js index e582c4e12907e..830317d552267 100644 --- a/test/playwright.spec.js +++ b/test/playwright.spec.js @@ -131,7 +131,9 @@ module.exports.addTests = ({testRunner, product, playwrightPath}) => { // Page-level tests that are given a browser, a context and a page. // Each test is launched in a new browser context. - require('../src/chromium/features/accessibility.spec.js').addTests(testOptions); + require('../src/tests/accessibility.spec.js').addTests(testOptions); + require('../src/tests/permissions.spec.js').addTests(testOptions); + require('../src/chromium/features/workers.spec.js').addTests(testOptions); require('./browser.spec.js').addTests(testOptions); require('./click.spec.js').addTests(testOptions); require('./cookies.spec.js').addTests(testOptions); @@ -154,7 +156,6 @@ module.exports.addTests = ({testRunner, product, playwrightPath}) => { require('./target.spec.js').addTests(testOptions); require('./touchscreen.spec.js').addTests(testOptions); require('./waittask.spec.js').addTests(testOptions); - require('../src/chromium/features/workers.spec.js').addTests(testOptions); if (CHROME) { require('./CDPSession.spec.js').addTests(testOptions); require('../src/chromium/features/coverage.spec.js').addTests(testOptions);