diff --git a/README.md b/README.md index a056018d5d..a1cda4e6f5 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ |Firefox|Chromium|WebKit|all| |---|---|---|---| -|511/649|698/705|325/652|309/649| +|508/634|685/692|325/637|309/634| # Contributing diff --git a/docs/api.md b/docs/api.md index e9bce7ba13..d400e982be 100644 --- a/docs/api.md +++ b/docs/api.md @@ -60,6 +60,8 @@ * [browserContext.permissions](#browsercontextpermissions) * [browserContext.targets()](#browsercontexttargets) * [browserContext.waitForTarget(predicate[, options])](#browsercontextwaitfortargetpredicate-options) +- [class: Geolocation](#class-geolocation) + * [geolocation.set(options)](#geolocationsetoptions) - [class: Permissions](#class-permissions) * [permissions.clearOverrides()](#permissionsclearoverrides) * [permissions.override(origin, permissions)](#permissionsoverrideorigin-permissions) @@ -110,6 +112,7 @@ * [page.fill(selector, value)](#pagefillselector-value) * [page.focus(selector)](#pagefocusselector) * [page.frames()](#pageframes) + * [page.geolocation](#pagegeolocation) * [page.goBack([options])](#pagegobackoptions) * [page.goForward([options])](#pagegoforwardoptions) * [page.goto(url[, options])](#pagegotourl-options) @@ -129,7 +132,6 @@ * [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout) * [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout) * [page.setExtraHTTPHeaders(headers)](#pagesetextrahttpheadersheaders) - * [page.setGeolocation(options)](#pagesetgeolocationoptions) * [page.setJavaScriptEnabled(enabled)](#pagesetjavascriptenabledenabled) * [page.setOfflineMode(enabled)](#pagesetofflinemodeenabled) * [page.setRequestInterception(value)](#pagesetrequestinterceptionvalue) @@ -868,6 +870,24 @@ await page.evaluate(() => window.open('https://www.example.com/')); const newWindowTarget = await browserContext.waitForTarget(target => target.url() === 'https://www.example.com/'); ``` +### class: Geolocation + +#### geolocation.set(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 page.geolocation.set({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: Permissions #### permissions.clearOverrides() @@ -1528,6 +1548,9 @@ Shortcut for [page.mainFrame().focus(selector)](#framefocusselector). #### page.frames() - returns: <[Array]<[Frame]>> An array of all frames attached to the page. +#### page.geolocation +- returns: <[Geolocation]> + #### page.goBack([options]) - `options` <[Object]> Navigation parameters which might have the following properties: - `timeout` <[number]> Maximum navigation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by using the [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout) or [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout) methods. @@ -1744,21 +1767,6 @@ The extra HTTP headers will be sent with every request the page initiates. > **NOTE** page.setExtraHTTPHeaders does not guarantee the order of headers in the outgoing requests. -#### page.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 page.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. - #### page.setJavaScriptEnabled(enabled) - `enabled` <[boolean]> Whether or not to enable JavaScript on the page. - returns: <[Promise]> diff --git a/src/api.ts b/src/api.ts index 6f9d3218eb..a33d157443 100644 --- a/src/api.ts +++ b/src/api.ts @@ -28,6 +28,7 @@ export = { ExecutionContext: require('./chromium/ExecutionContext').ExecutionContext, FileChooser: require('./chromium/Page').FileChooser, Frame: require('./chromium/Frame').Frame, + Geolocation: require('./chromium/features/geolocation').Geolocation, JSHandle: require('./chromium/JSHandle').JSHandle, Keyboard: require('./chromium/Input').Keyboard, Mouse: require('./chromium/Input').Mouse, diff --git a/src/chromium/Page.ts b/src/chromium/Page.ts index 320890f9bd..cbb26c7462 100644 --- a/src/chromium/Page.ts +++ b/src/chromium/Page.ts @@ -39,6 +39,7 @@ import { Protocol } from './protocol'; import { getExceptionMessage, releaseObject, valueFromRemoteObject } from './protocolHelper'; import { Target } from './Target'; import { TaskQueue } from './TaskQueue'; +import { Geolocation } from './features/geolocation'; import { Tracing } from './features/tracing'; import { Workers } from './features/workers'; @@ -65,6 +66,7 @@ export class Page extends EventEmitter { private _emulationManager: EmulationManager; readonly accessibility: Accessibility; readonly coverage: Coverage; + readonly geolocation: Geolocation; readonly pdf: PDF; readonly workers: Workers; readonly tracing: Tracing; @@ -99,6 +101,7 @@ export class Page extends EventEmitter { this.coverage = new Coverage(client); this.pdf = new PDF(client); this.workers = new Workers(client, this._addConsoleMessage.bind(this), this._handleException.bind(this)); + this.geolocation = new Geolocation(client); this._screenshotTaskQueue = screenshotTaskQueue; @@ -176,17 +179,6 @@ export class Page extends EventEmitter { }); } - async setGeolocation(options: { longitude: number; latitude: number; accuracy: (number | undefined); }) { - const { longitude, latitude, accuracy = 0} = options; - if (longitude < -180 || longitude > 180) - throw new Error(`Invalid longitude "${longitude}": precondition -180 <= LONGITUDE <= 180 failed.`); - if (latitude < -90 || latitude > 90) - throw new Error(`Invalid latitude "${latitude}": precondition -90 <= LATITUDE <= 90 failed.`); - if (accuracy < 0) - throw new Error(`Invalid accuracy "${accuracy}": precondition 0 <= ACCURACY failed.`); - await this._client.send('Emulation.setGeolocationOverride', {longitude, latitude, accuracy}); - } - target(): Target { return this._target; } diff --git a/src/chromium/features/geolocation.spec.js b/src/chromium/features/geolocation.spec.js new file mode 100644 index 0000000000..4560514c74 --- /dev/null +++ b/src/chromium/features/geolocation.spec.js @@ -0,0 +1,52 @@ +/** + * 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. + */ + +const utils = require('../../../test/utils'); +const {waitEvent} = utils; + +module.exports.addTests = function ({ testRunner, expect }) { + const {describe, xdescribe, fdescribe} = testRunner; + const {it, fit, xit} = testRunner; + const {beforeAll, beforeEach, afterAll, afterEach} = testRunner; + + // FIXME: not supported in WebKit (as well as Emulation domain in general). + // It was removed from WebKit in https://webkit.org/b/126630 + describe('Geolocation.set', function() { + it('should work', async({page, server, context}) => { + await context.permissions.override(server.PREFIX, ['geolocation']); + await page.goto(server.EMPTY_PAGE); + await page.geolocation.set({longitude: 10, latitude: 10}); + const geolocation = await page.evaluate(() => new Promise(resolve => navigator.geolocation.getCurrentPosition(position => { + resolve({latitude: position.coords.latitude, longitude: position.coords.longitude}); + }))); + expect(geolocation).toEqual({ + latitude: 10, + longitude: 10 + }); + }); + it('should throw when invalid longitude', async({page, server, context}) => { + let error = null; + try { + await page.geolocation.set({longitude: 200, latitude: 10}); + } catch (e) { + error = e; + } + expect(error.message).toContain('Invalid longitude "200"'); + }); + }); + +}; diff --git a/src/chromium/features/geolocation.ts b/src/chromium/features/geolocation.ts new file mode 100644 index 0000000000..a4171ca098 --- /dev/null +++ b/src/chromium/features/geolocation.ts @@ -0,0 +1,37 @@ +/** + * 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 { CDPSession } from '../Connection'; + +export class Geolocation { + private _client: CDPSession; + + constructor(client: CDPSession) { + this._client = client; + } + + async set(options: { longitude: number; latitude: number; accuracy: (number | undefined); }) { + const { longitude, latitude, accuracy = 0} = options; + if (longitude < -180 || longitude > 180) + throw new Error(`Invalid longitude "${longitude}": precondition -180 <= LONGITUDE <= 180 failed.`); + if (latitude < -90 || latitude > 90) + throw new Error(`Invalid latitude "${latitude}": precondition -90 <= LATITUDE <= 90 failed.`); + if (accuracy < 0) + throw new Error(`Invalid accuracy "${accuracy}": precondition 0 <= ACCURACY failed.`); + await this._client.send('Emulation.setGeolocationOverride', {longitude, latitude, accuracy}); + } +} diff --git a/src/chromium/features/workers.spec.js b/src/chromium/features/workers.spec.js index 5cc6c0e469..fecc25fd23 100644 --- a/src/chromium/features/workers.spec.js +++ b/src/chromium/features/workers.spec.js @@ -1,5 +1,22 @@ +/** + * 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. + */ + const utils = require('../../../test/utils'); -const {waitEvent} = utils; +const { waitEvent } = utils; module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) { const {describe, xdescribe, fdescribe} = testRunner; diff --git a/test/page.spec.js b/test/page.spec.js index 58f8461288..78d1a68878 100644 --- a/test/page.spec.js +++ b/test/page.spec.js @@ -166,33 +166,6 @@ module.exports.addTests = function({testRunner, expect, headless, playwright, FF }); }); - - // 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.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 => { - resolve({latitude: position.coords.latitude, longitude: position.coords.longitude}); - }))); - expect(geolocation).toEqual({ - latitude: 10, - longitude: 10 - }); - }); - it('should throw when invalid longitude', async({page, server, context}) => { - let error = null; - try { - await page.setGeolocation({longitude: 200, latitude: 10}); - } catch (e) { - error = e; - } - expect(error.message).toContain('Invalid longitude "200"'); - }); - }); - describe.skip(FFOX || WEBKIT)('Page.setOfflineMode', function() { it('should work', async({page, server}) => { await page.setOfflineMode(true); diff --git a/test/playwright.spec.js b/test/playwright.spec.js index 830317d552..f58987fd14 100644 --- a/test/playwright.spec.js +++ b/test/playwright.spec.js @@ -161,6 +161,7 @@ module.exports.addTests = ({testRunner, product, playwrightPath}) => { require('../src/chromium/features/coverage.spec.js').addTests(testOptions); // Add page-level Chromium-specific tests. require('./chromiumonly.spec.js').addPageTests(testOptions); + require('../src/chromium/features/geolocation.spec.js').addTests(testOptions); require('../src/chromium/features/pdf.spec.js').addTests(testOptions); } });