selenium-webdriver 4.0.0-alpha.8 → 4.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES.md +14 -1
- package/LICENSE +202 -0
- package/NOTICE +2 -0
- package/README.md +0 -0
- package/chrome.js +0 -0
- package/chromium.js +7 -202
- package/devtools/CDPConnection.js +0 -0
- package/edge.js +1 -1
- package/example/chrome_android.js +45 -0
- package/{lib/atoms/make-atoms-module.js → example/chrome_mobile_emulation.js} +26 -15
- package/example/firefox_channels.js +84 -0
- package/example/google_search.js +50 -0
- package/example/google_search_test.js +70 -0
- package/example/headless.js +63 -0
- package/example/logging.js +64 -0
- package/firefox.js +10 -9
- package/http/index.js +0 -0
- package/http/util.js +3 -3
- package/ie.js +0 -0
- package/index.js +2 -2
- package/io/exec.js +0 -0
- package/io/index.js +4 -4
- package/io/zip.js +0 -0
- package/lib/actions.js +16 -15
- package/lib/atoms/find-elements.js +4 -3
- package/lib/atoms/get-attribute.js +0 -0
- package/lib/atoms/is-displayed.js +0 -0
- package/lib/atoms/mutation-listener.js +38 -0
- package/lib/by.js +1 -1
- package/lib/capabilities.js +2 -2
- package/lib/command.js +2 -0
- package/lib/error.js +0 -0
- package/lib/http.js +17 -1
- package/lib/input.js +0 -0
- package/lib/logging.js +0 -0
- package/lib/promise.js +1 -1
- package/lib/proxy.js +0 -0
- package/lib/session.js +0 -0
- package/lib/symbols.js +0 -0
- package/lib/until.js +17 -15
- package/lib/webdriver.js +322 -50
- package/net/index.js +0 -0
- package/net/portprober.js +8 -8
- package/opera.js +0 -0
- package/package.json +8 -8
- package/proxy.js +0 -0
- package/remote/index.js +0 -0
- package/safari.js +0 -0
- package/testing/index.js +509 -0
- package/.eslintrc.js +0 -27
- package/.prettierrc +0 -4
- package/devtools/generator/protocol-dts-generator.js +0 -429
- package/lib/README +0 -5
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Licensed to the Software Freedom Conservancy (SFC) under one
|
|
2
|
+
// or more contributor license agreements. See the NOTICE file
|
|
3
|
+
// distributed with this work for additional information
|
|
4
|
+
// regarding copyright ownership. The SFC licenses this file
|
|
5
|
+
// to you under the Apache License, Version 2.0 (the
|
|
6
|
+
// "License"); you may not use this file except in compliance
|
|
7
|
+
// with the License. You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing,
|
|
12
|
+
// software distributed under the License is distributed on an
|
|
13
|
+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
// KIND, either express or implied. See the License for the
|
|
15
|
+
// specific language governing permissions and limitations
|
|
16
|
+
// under the License.
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @fileoverview This is an example of working with the different Firefox
|
|
20
|
+
* release channels. Before running this example, you will need to have
|
|
21
|
+
* installed Firefox's release, nightly, and developer editions:
|
|
22
|
+
*
|
|
23
|
+
* - https://www.mozilla.org/en-US/firefox/channel/desktop/#aurora
|
|
24
|
+
* - https://www.mozilla.org/en-US/firefox/channel/desktop/#nightly
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
'use strict'
|
|
28
|
+
|
|
29
|
+
const { Builder, By, Key, promise, until } = require('..')
|
|
30
|
+
const { Channel, Options } = require('../firefox')
|
|
31
|
+
|
|
32
|
+
let i = 0
|
|
33
|
+
function resposition(driver) {
|
|
34
|
+
return driver
|
|
35
|
+
.manage()
|
|
36
|
+
.window()
|
|
37
|
+
.setRect({
|
|
38
|
+
width: 600,
|
|
39
|
+
height: 400,
|
|
40
|
+
x: 300 * i++,
|
|
41
|
+
y: 0,
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function doSearch(driver) {
|
|
46
|
+
try {
|
|
47
|
+
// Start on the base about page.
|
|
48
|
+
await driver.get('about:')
|
|
49
|
+
// Reposition so users can see the three windows.
|
|
50
|
+
await resposition(driver)
|
|
51
|
+
// Pause so users can see the magic.
|
|
52
|
+
await promise.delayed(750)
|
|
53
|
+
// Now do the rest.
|
|
54
|
+
await driver.get('http://www.google.com/ncr')
|
|
55
|
+
await driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN)
|
|
56
|
+
await driver.wait(until.titleIs('webdriver - Google Search'), 1000)
|
|
57
|
+
console.log('Success!')
|
|
58
|
+
} catch (ex) {
|
|
59
|
+
console.log('An error occured! ' + ex)
|
|
60
|
+
} finally {
|
|
61
|
+
await driver.quit()
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function createDriver(channel) {
|
|
66
|
+
let options = new Options().setBinary(channel)
|
|
67
|
+
return new Builder().forBrowser('firefox').setFirefoxOptions(options).build()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
Promise.all([
|
|
71
|
+
doSearch(createDriver(Channel.RELEASE)),
|
|
72
|
+
doSearch(createDriver(Channel.AURORA)), // Developer Edition.
|
|
73
|
+
doSearch(createDriver(Channel.NIGHTLY)),
|
|
74
|
+
]).then(
|
|
75
|
+
(_) => {
|
|
76
|
+
console.log('All done!')
|
|
77
|
+
},
|
|
78
|
+
(err) => {
|
|
79
|
+
console.error('An error occured! ' + err)
|
|
80
|
+
setTimeout(() => {
|
|
81
|
+
throw err
|
|
82
|
+
}, 0)
|
|
83
|
+
}
|
|
84
|
+
)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Licensed to the Software Freedom Conservancy (SFC) under one
|
|
2
|
+
// or more contributor license agreements. See the NOTICE file
|
|
3
|
+
// distributed with this work for additional information
|
|
4
|
+
// regarding copyright ownership. The SFC licenses this file
|
|
5
|
+
// to you under the Apache License, Version 2.0 (the
|
|
6
|
+
// "License"); you may not use this file except in compliance
|
|
7
|
+
// with the License. You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing,
|
|
12
|
+
// software distributed under the License is distributed on an
|
|
13
|
+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
// KIND, either express or implied. See the License for the
|
|
15
|
+
// specific language governing permissions and limitations
|
|
16
|
+
// under the License.
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @fileoverview An example WebDriver script.
|
|
20
|
+
*
|
|
21
|
+
* Before running this script, ensure that Mozilla's geckodriver is present on
|
|
22
|
+
* your system PATH: <https://github.com/mozilla/geckodriver/releases>
|
|
23
|
+
*
|
|
24
|
+
* Usage:
|
|
25
|
+
* // Default behavior
|
|
26
|
+
* node selenium-webdriver/example/google_search.js
|
|
27
|
+
*
|
|
28
|
+
* // Target Chrome locally; the chromedriver must be on your PATH
|
|
29
|
+
* SELENIUM_BROWSER=chrome node selenium-webdriver/example/google_search.js
|
|
30
|
+
*
|
|
31
|
+
* // Use a local copy of the standalone Selenium server
|
|
32
|
+
* SELENIUM_SERVER_JAR=/path/to/selenium-server-standalone.jar \
|
|
33
|
+
* node selenium-webdriver/example/google_search.js
|
|
34
|
+
*
|
|
35
|
+
* // Target a remote Selenium server
|
|
36
|
+
* SELENIUM_REMOTE_URL=http://www.example.com:4444/wd/hub \
|
|
37
|
+
* node selenium-webdriver/example/google_search.js
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
const { Builder, By, Key, until } = require('..')
|
|
41
|
+
|
|
42
|
+
var driver = new Builder().forBrowser('firefox').build()
|
|
43
|
+
|
|
44
|
+
driver
|
|
45
|
+
.get('http://www.google.com/ncr')
|
|
46
|
+
.then((_) =>
|
|
47
|
+
driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN)
|
|
48
|
+
)
|
|
49
|
+
.then((_) => driver.wait(until.titleIs('webdriver - Google Search'), 1000))
|
|
50
|
+
.then((_) => driver.quit())
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Licensed to the Software Freedom Conservancy (SFC) under one
|
|
2
|
+
// or more contributor license agreements. See the NOTICE file
|
|
3
|
+
// distributed with this work for additional information
|
|
4
|
+
// regarding copyright ownership. The SFC licenses this file
|
|
5
|
+
// to you under the Apache License, Version 2.0 (the
|
|
6
|
+
// "License"); you may not use this file except in compliance
|
|
7
|
+
// with the License. You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing,
|
|
12
|
+
// software distributed under the License is distributed on an
|
|
13
|
+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
// KIND, either express or implied. See the License for the
|
|
15
|
+
// specific language governing permissions and limitations
|
|
16
|
+
// under the License.
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @fileoverview An example test that may be run using Mocha.
|
|
20
|
+
*
|
|
21
|
+
* This example uses the `selenium-webdriver/testing.suite` function, which will
|
|
22
|
+
* automatically run tests against every available WebDriver browser on the
|
|
23
|
+
* current system. Alternatively, you may use the `SELENIUM_BROWSER`
|
|
24
|
+
* environment variable to narrow the scope at runtime.
|
|
25
|
+
*
|
|
26
|
+
* Usage:
|
|
27
|
+
*
|
|
28
|
+
* # Automatically determine which browsers to run against.
|
|
29
|
+
* mocha -t 10000 selenium-webdriver/example/google_search_test.js
|
|
30
|
+
*
|
|
31
|
+
* # Configure tests to only run against Google Chrome.
|
|
32
|
+
* SELENIUM_BROWSER=chrome \
|
|
33
|
+
* mocha -t 10000 selenium-webdriver/example/google_search_test.js
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
const { Browser, By, Key, until } = require('..')
|
|
37
|
+
const { ignore, suite } = require('../testing')
|
|
38
|
+
|
|
39
|
+
suite(function (env) {
|
|
40
|
+
describe('Google Search', function () {
|
|
41
|
+
let driver
|
|
42
|
+
|
|
43
|
+
before(async function () {
|
|
44
|
+
// env.builder() returns a Builder instance preconfigured for the
|
|
45
|
+
// envrionment's target browser (you may still define browser specific
|
|
46
|
+
// options if necessary (i.e. firefox.Options or chrome.Options)).
|
|
47
|
+
driver = await env.builder().build()
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('demo', async function () {
|
|
51
|
+
await driver.get('https://www.google.com/ncr')
|
|
52
|
+
await driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN)
|
|
53
|
+
await driver.wait(until.titleIs('webdriver - Google Search'), 1000)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
// The ignore function returns wrappers around describe & it that will
|
|
57
|
+
// suppress tests if the provided predicate returns true. You may provide
|
|
58
|
+
// any synchronous predicate. The env.browsers(...) function generates a
|
|
59
|
+
// predicate that will suppress tests if the env targets one of the
|
|
60
|
+
// specified browsers.
|
|
61
|
+
//
|
|
62
|
+
// This example is always configured to skip Chrome.
|
|
63
|
+
ignore(env.browsers(Browser.CHROME)).it('demo 2', async function () {
|
|
64
|
+
await driver.get('https://www.google.com/ncr')
|
|
65
|
+
await driver.wait(until.urlIs('https://www.google.com/'), 1500)
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
after(() => driver && driver.quit())
|
|
69
|
+
})
|
|
70
|
+
})
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Licensed to the Software Freedom Conservancy (SFC) under one
|
|
2
|
+
// or more contributor license agreements. See the NOTICE file
|
|
3
|
+
// distributed with this work for additional information
|
|
4
|
+
// regarding copyright ownership. The SFC licenses this file
|
|
5
|
+
// to you under the Apache License, Version 2.0 (the
|
|
6
|
+
// "License"); you may not use this file except in compliance
|
|
7
|
+
// with the License. You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing,
|
|
12
|
+
// software distributed under the License is distributed on an
|
|
13
|
+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
// KIND, either express or implied. See the License for the
|
|
15
|
+
// specific language governing permissions and limitations
|
|
16
|
+
// under the License.
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @fileoverview An example of running Chrome or Firefox in headless mode.
|
|
20
|
+
*
|
|
21
|
+
* To run with Chrome, ensure you have Chrome 59+ installed and that
|
|
22
|
+
* chromedriver 2.30+ is present on your system PATH:
|
|
23
|
+
* <https://chromedriver.chromium.org/downloads>
|
|
24
|
+
*
|
|
25
|
+
* SELENIUM_BROWSER=chrome node selenium-webdriver/example/headless.js
|
|
26
|
+
*
|
|
27
|
+
* To run with Firefox, ensure you have Firefox 57+ installed and that
|
|
28
|
+
* geckodriver 0.19.0+ is present on your system PATH:
|
|
29
|
+
* <https://github.com/mozilla/geckodriver/releases>
|
|
30
|
+
*
|
|
31
|
+
* SELENIUM_BROWSER=firefox node selenium-webdriver/example/headless.js
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
const chrome = require('../chrome')
|
|
35
|
+
const firefox = require('../firefox')
|
|
36
|
+
const { Builder, By, Key, until } = require('..')
|
|
37
|
+
|
|
38
|
+
const width = 640
|
|
39
|
+
const height = 480
|
|
40
|
+
|
|
41
|
+
let driver = new Builder()
|
|
42
|
+
.forBrowser('chrome')
|
|
43
|
+
.setChromeOptions(
|
|
44
|
+
new chrome.Options().headless().windowSize({ width, height })
|
|
45
|
+
)
|
|
46
|
+
.setFirefoxOptions(
|
|
47
|
+
new firefox.Options().headless().windowSize({ width, height })
|
|
48
|
+
)
|
|
49
|
+
.build()
|
|
50
|
+
|
|
51
|
+
driver
|
|
52
|
+
.get('http://www.google.com/ncr')
|
|
53
|
+
.then((_) =>
|
|
54
|
+
driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN)
|
|
55
|
+
)
|
|
56
|
+
.then((_) => driver.wait(until.titleIs('webdriver - Google Search'), 1000))
|
|
57
|
+
.then(
|
|
58
|
+
(_) => driver.quit(),
|
|
59
|
+
(e) =>
|
|
60
|
+
driver.quit().then(() => {
|
|
61
|
+
throw e
|
|
62
|
+
})
|
|
63
|
+
)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Licensed to the Software Freedom Conservancy (SFC) under one
|
|
2
|
+
// or more contributor license agreements. See the NOTICE file
|
|
3
|
+
// distributed with this work for additional information
|
|
4
|
+
// regarding copyright ownership. The SFC licenses this file
|
|
5
|
+
// to you under the Apache License, Version 2.0 (the
|
|
6
|
+
// "License"); you may not use this file except in compliance
|
|
7
|
+
// with the License. You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing,
|
|
12
|
+
// software distributed under the License is distributed on an
|
|
13
|
+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
// KIND, either express or implied. See the License for the
|
|
15
|
+
// specific language governing permissions and limitations
|
|
16
|
+
// under the License.
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @fileoverview Demonstrates how to use WebDriver's logging sysem.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
'use strict'
|
|
23
|
+
|
|
24
|
+
const chrome = require('../chrome')
|
|
25
|
+
const firefox = require('../firefox')
|
|
26
|
+
const edge = require('../edge')
|
|
27
|
+
const { Builder, By, Key, logging, until } = require('..')
|
|
28
|
+
|
|
29
|
+
logging.installConsoleHandler()
|
|
30
|
+
logging.getLogger('webdriver.http').setLevel(logging.Level.ALL)
|
|
31
|
+
;(async function () {
|
|
32
|
+
let driver
|
|
33
|
+
try {
|
|
34
|
+
driver = await new Builder()
|
|
35
|
+
// Default to using Firefox. This can be overridden at runtime by
|
|
36
|
+
// setting the SELENIUM_BROWSER environment variable:
|
|
37
|
+
//
|
|
38
|
+
// SELENIUM_BROWSER=chrome node selenium-webdriver/example/logging.js
|
|
39
|
+
.forBrowser('firefox')
|
|
40
|
+
// Configure the service for each browser to enable verbose logging and
|
|
41
|
+
// to inherit the stdio settings from the current process. The builder
|
|
42
|
+
// will only start the service if needed for the selected browser.
|
|
43
|
+
.setChromeService(
|
|
44
|
+
new chrome.ServiceBuilder().enableVerboseLogging().setStdio('inherit')
|
|
45
|
+
)
|
|
46
|
+
.setEdgeService(
|
|
47
|
+
process.platform === 'win32'
|
|
48
|
+
? new edge.ServiceBuilder().enableVerboseLogging().setStdio('inherit')
|
|
49
|
+
: null
|
|
50
|
+
)
|
|
51
|
+
.setFirefoxService(
|
|
52
|
+
new firefox.ServiceBuilder().enableVerboseLogging().setStdio('inherit')
|
|
53
|
+
)
|
|
54
|
+
.build()
|
|
55
|
+
|
|
56
|
+
await driver.get('http://www.google.com/ncr')
|
|
57
|
+
await driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN)
|
|
58
|
+
await driver.wait(until.titleIs('webdriver - Google Search'), 1000)
|
|
59
|
+
} finally {
|
|
60
|
+
if (driver) {
|
|
61
|
+
await driver.quit()
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
})()
|
package/firefox.js
CHANGED
|
@@ -124,6 +124,7 @@ const io = require('./io')
|
|
|
124
124
|
const remote = require('./remote')
|
|
125
125
|
const webdriver = require('./lib/webdriver')
|
|
126
126
|
const zip = require('./io/zip')
|
|
127
|
+
const cdp = require('./devtools/CDPConnection')
|
|
127
128
|
const { Browser, Capabilities } = require('./lib/capabilities')
|
|
128
129
|
const { Zip } = require('./io/zip')
|
|
129
130
|
|
|
@@ -222,7 +223,7 @@ async function buildProfile(template, extensions) {
|
|
|
222
223
|
dir = await io.tmpDir()
|
|
223
224
|
if (template) {
|
|
224
225
|
await io.copyDir(
|
|
225
|
-
/** @type {string} */
|
|
226
|
+
/** @type {string} */(template),
|
|
226
227
|
dir,
|
|
227
228
|
/(parent\.lock|lock|\.parentlock)/
|
|
228
229
|
)
|
|
@@ -432,11 +433,11 @@ function findGeckoDriver() {
|
|
|
432
433
|
if (!exe) {
|
|
433
434
|
throw Error(
|
|
434
435
|
'The ' +
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
436
|
+
GECKO_DRIVER_EXE +
|
|
437
|
+
' executable could not be found on the current ' +
|
|
438
|
+
'PATH. Please download the latest version from ' +
|
|
439
|
+
'https://github.com/mozilla/geckodriver/releases/ ' +
|
|
440
|
+
'and ensure it can be found on your PATH.'
|
|
440
441
|
)
|
|
441
442
|
}
|
|
442
443
|
return exe
|
|
@@ -457,8 +458,8 @@ function findInProgramFiles(file) {
|
|
|
457
458
|
return exists
|
|
458
459
|
? files[0]
|
|
459
460
|
: io.exists(files[1]).then(function (exists) {
|
|
460
|
-
|
|
461
|
-
|
|
461
|
+
return exists ? files[1] : null
|
|
462
|
+
})
|
|
462
463
|
})
|
|
463
464
|
}
|
|
464
465
|
|
|
@@ -592,7 +593,7 @@ class Driver extends webdriver.WebDriver {
|
|
|
592
593
|
* implementation.
|
|
593
594
|
* @override
|
|
594
595
|
*/
|
|
595
|
-
setFileDetector() {}
|
|
596
|
+
setFileDetector() { }
|
|
596
597
|
|
|
597
598
|
/**
|
|
598
599
|
* Get the context that is currently in effect.
|
package/http/index.js
CHANGED
|
File without changes
|
package/http/util.js
CHANGED
|
@@ -35,9 +35,9 @@ const Executor = require('./index').Executor,
|
|
|
35
35
|
* a hash of the server status.
|
|
36
36
|
*/
|
|
37
37
|
function getStatus(url) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
const client = new HttpClient(url)
|
|
39
|
+
const executor = new Executor(client)
|
|
40
|
+
const command = new Command(CommandName.GET_SERVER_STATUS)
|
|
41
41
|
return executor.execute(command)
|
|
42
42
|
}
|
|
43
43
|
|
package/ie.js
CHANGED
|
File without changes
|
package/index.js
CHANGED
|
@@ -598,9 +598,9 @@ class Builder {
|
|
|
598
598
|
build() {
|
|
599
599
|
// Create a copy for any changes we may need to make based on the current
|
|
600
600
|
// environment.
|
|
601
|
-
|
|
601
|
+
const capabilities = new Capabilities(this.capabilities_)
|
|
602
602
|
|
|
603
|
-
|
|
603
|
+
let browser
|
|
604
604
|
if (!this.ignoreEnv_ && process.env.SELENIUM_BROWSER) {
|
|
605
605
|
this.log_.fine(`SELENIUM_BROWSER=${process.env.SELENIUM_BROWSER}`)
|
|
606
606
|
browser = process.env.SELENIUM_BROWSER.split(/:/, 3)
|
package/io/exec.js
CHANGED
|
File without changes
|
package/io/index.js
CHANGED
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
|
|
18
18
|
'use strict'
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
const fs = require('fs')
|
|
21
|
+
const path = require('path')
|
|
22
|
+
const rimraf = require('rimraf')
|
|
23
|
+
const tmp = require('tmp')
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* @param {!Function} fn .
|
package/io/zip.js
CHANGED
|
File without changes
|
package/lib/actions.js
CHANGED
|
@@ -26,9 +26,9 @@ const input = require('./input')
|
|
|
26
26
|
* @return {!Array} .
|
|
27
27
|
*/
|
|
28
28
|
function flatten(args) {
|
|
29
|
-
|
|
29
|
+
const result = []
|
|
30
30
|
for (let i = 0; i < args.length; i++) {
|
|
31
|
-
|
|
31
|
+
const element = args[i]
|
|
32
32
|
if (Array.isArray(element)) {
|
|
33
33
|
result.push.apply(result, flatten(element))
|
|
34
34
|
} else {
|
|
@@ -119,8 +119,8 @@ class LegacyActionSequence {
|
|
|
119
119
|
// Make a protected copy of the scheduled actions. This will protect against
|
|
120
120
|
// users defining additional commands before this sequence is actually
|
|
121
121
|
// executed.
|
|
122
|
-
|
|
123
|
-
for (
|
|
122
|
+
const actions = this.actions_.concat()
|
|
123
|
+
for (const action of actions) {
|
|
124
124
|
await this.driver_.execute(action.command)
|
|
125
125
|
}
|
|
126
126
|
}
|
|
@@ -141,7 +141,7 @@ class LegacyActionSequence {
|
|
|
141
141
|
* @return {!LegacyActionSequence} A self reference.
|
|
142
142
|
*/
|
|
143
143
|
mouseMove(location, opt_offset) {
|
|
144
|
-
|
|
144
|
+
const cmd = new command.Command(command.Name.LEGACY_ACTION_MOUSE_MOVE)
|
|
145
145
|
|
|
146
146
|
if (typeof location.x === 'number') {
|
|
147
147
|
setOffset(/** @type {{x: number, y: number}} */ (location))
|
|
@@ -389,8 +389,9 @@ class LegacyActionSequence {
|
|
|
389
389
|
* @return {!LegacyActionSequence} A self reference.
|
|
390
390
|
* @throws {Error} If the key is not a valid modifier key.
|
|
391
391
|
*/
|
|
392
|
-
sendKeys(
|
|
393
|
-
|
|
392
|
+
sendKeys(_var_args) {
|
|
393
|
+
// eslint-disable-line
|
|
394
|
+
const keys = flatten(arguments)
|
|
394
395
|
return this.scheduleKeyboardAction_('sendKeys', keys)
|
|
395
396
|
}
|
|
396
397
|
}
|
|
@@ -481,7 +482,7 @@ class LegacyTouchSequence {
|
|
|
481
482
|
* @return {!LegacyTouchSequence} A self reference.
|
|
482
483
|
*/
|
|
483
484
|
doubleTap(elem) {
|
|
484
|
-
|
|
485
|
+
const cmd = new command.Command(
|
|
485
486
|
command.Name.LEGACY_ACTION_TOUCH_DOUBLE_TAP
|
|
486
487
|
).setParameter('element', elem.getId())
|
|
487
488
|
|
|
@@ -496,7 +497,7 @@ class LegacyTouchSequence {
|
|
|
496
497
|
* @return {!LegacyTouchSequence} A self reference.
|
|
497
498
|
*/
|
|
498
499
|
longPress(elem) {
|
|
499
|
-
|
|
500
|
+
const cmd = new command.Command(
|
|
500
501
|
command.Name.LEGACY_ACTION_TOUCH_LONG_PRESS
|
|
501
502
|
).setParameter('element', elem.getId())
|
|
502
503
|
|
|
@@ -511,7 +512,7 @@ class LegacyTouchSequence {
|
|
|
511
512
|
* @return {!LegacyTouchSequence} A self reference.
|
|
512
513
|
*/
|
|
513
514
|
tapAndHold(location) {
|
|
514
|
-
|
|
515
|
+
const cmd = new command.Command(command.Name.LEGACY_ACTION_TOUCH_DOWN)
|
|
515
516
|
.setParameter('x', location.x)
|
|
516
517
|
.setParameter('y', location.y)
|
|
517
518
|
|
|
@@ -526,7 +527,7 @@ class LegacyTouchSequence {
|
|
|
526
527
|
* @return {!LegacyTouchSequence} A self reference.
|
|
527
528
|
*/
|
|
528
529
|
move(location) {
|
|
529
|
-
|
|
530
|
+
const cmd = new command.Command(command.Name.LEGACY_ACTION_TOUCH_MOVE)
|
|
530
531
|
.setParameter('x', location.x)
|
|
531
532
|
.setParameter('y', location.y)
|
|
532
533
|
|
|
@@ -556,7 +557,7 @@ class LegacyTouchSequence {
|
|
|
556
557
|
* @return {!LegacyTouchSequence} A self reference.
|
|
557
558
|
*/
|
|
558
559
|
scroll(offset) {
|
|
559
|
-
|
|
560
|
+
const cmd = new command.Command(command.Name.LEGACY_ACTION_TOUCH_SCROLL)
|
|
560
561
|
.setParameter('xoffset', offset.x)
|
|
561
562
|
.setParameter('yoffset', offset.y)
|
|
562
563
|
|
|
@@ -573,7 +574,7 @@ class LegacyTouchSequence {
|
|
|
573
574
|
* @return {!LegacyTouchSequence} A self reference.
|
|
574
575
|
*/
|
|
575
576
|
scrollFromElement(elem, offset) {
|
|
576
|
-
|
|
577
|
+
const cmd = new command.Command(command.Name.LEGACY_ACTION_TOUCH_SCROLL)
|
|
577
578
|
.setParameter('element', elem.getId())
|
|
578
579
|
.setParameter('xoffset', offset.x)
|
|
579
580
|
.setParameter('yoffset', offset.y)
|
|
@@ -590,7 +591,7 @@ class LegacyTouchSequence {
|
|
|
590
591
|
* @return {!LegacyTouchSequence} A self reference.
|
|
591
592
|
*/
|
|
592
593
|
flick(speed) {
|
|
593
|
-
|
|
594
|
+
const cmd = new command.Command(command.Name.LEGACY_ACTION_TOUCH_FLICK)
|
|
594
595
|
.setParameter('xspeed', speed.xspeed)
|
|
595
596
|
.setParameter('yspeed', speed.yspeed)
|
|
596
597
|
|
|
@@ -607,7 +608,7 @@ class LegacyTouchSequence {
|
|
|
607
608
|
* @return {!LegacyTouchSequence} A self reference.
|
|
608
609
|
*/
|
|
609
610
|
flickElement(elem, offset, speed) {
|
|
610
|
-
|
|
611
|
+
const cmd = new command.Command(command.Name.LEGACY_ACTION_TOUCH_FLICK)
|
|
611
612
|
.setParameter('element', elem.getId())
|
|
612
613
|
.setParameter('xoffset', offset.x)
|
|
613
614
|
.setParameter('yoffset', offset.y)
|
|
@@ -115,9 +115,10 @@ b.push(c+a)}function gd(a){if(Pc){if("relative"==V(a,"position"))return 1;a=V(a,
|
|
|
115
115
|
function sd(a,b,c,d,e){if(3==a.nodeType&&c)qd(a,b,d,e);else if(S(a))if(S(a,"CONTENT")||S(a,"SLOT")){for(var f=a;f.parentNode;)f=f.parentNode;f instanceof ShadowRoot?(a=S(a,"CONTENT")?a.getDistributedNodes():a.assignedNodes(),q(a,function(g){sd(g,b,c,d,e)})):md(a,b)}else if(S(a,"SHADOW")){for(f=a;f.parentNode;)f=f.parentNode;if(f instanceof ShadowRoot&&(a=f))for(a=a.olderShadowRoot;a;)q(a.childNodes,function(g){sd(g,b,c,d,e)}),a=a.olderShadowRoot}else md(a,b)}
|
|
116
116
|
function md(a,b){a.shadowRoot&&q(a.shadowRoot.childNodes,function(c){sd(c,b,!0,null,null)});od(a,b,function(c,d,e,f,g){var h=null;1==c.nodeType?h=c:3==c.nodeType&&(h=c);null!=h&&(null!=h.assignedSlot||h.getDestinationInsertionPoints&&0<h.getDestinationInsertionPoints().length)||sd(c,d,e,f,g)})};var td={C:function(a,b){return!(!a.querySelectorAll||!a.querySelector)&&!/^\d.*/.test(b)},o:function(a,b){var c=eb(b),d="string"===typeof a?c.a.getElementById(a):a;return d?Xc(d,"id")==a&&b!=d&&hb(b,d)?d:ta(mb(c,"*"),function(e){return Xc(e,"id")==a&&b!=e&&hb(b,e)}):null},j:function(a,b){if(!a)return[];if(td.C(b,a))try{return b.querySelectorAll("#"+td.T(a))}catch(c){return[]}b=mb(eb(b),"*",null,b);return oa(b,function(c){return Xc(c,"id")==a})},T:function(a){return a.replace(/([\s'"\\#.:;,!?+<>=~*^$|%&@`{}\-\/\[\]\(\)])/g,
|
|
117
117
|
"\\$1")}};var Y={},ud={};Y.N=function(a,b,c){try{var d=Qc.j("a",b)}catch(e){d=mb(eb(b),"A",null,b)}return ta(d,function(e){e=ld(e);e=e.replace(/^[\s]+|[\s]+$/g,"");return c&&-1!=e.indexOf(a)||e==a})};Y.K=function(a,b,c){try{var d=Qc.j("a",b)}catch(e){d=mb(eb(b),"A",null,b)}return oa(d,function(e){e=ld(e);e=e.replace(/^[\s]+|[\s]+$/g,"");return c&&-1!=e.indexOf(a)||e==a})};Y.o=function(a,b){return Y.N(a,b,!1)};Y.j=function(a,b){return Y.K(a,b,!1)};ud.o=function(a,b){return Y.N(a,b,!0)};
|
|
118
|
-
ud.j=function(a,b){return Y.K(a,b,!0)};var Z={F:function(a,b){return function(c){var d=Z.u(a);d=W(d);c=W(c);return b.call(null,d,c)}},R:function(a){return Z.F(a,function(b,c){return c.b+c.height<b.b})},S:function(a){return Z.F(a,function(b,c){return b.b+b.height<c.b})},V:function(a){return Z.F(a,function(b,c){return c.a+c.width<b.a})},aa:function(a){return Z.F(a,function(b,c){return b.a+b.width<c.a})},W:function(a,b){
|
|
119
|
-
|
|
120
|
-
JSON.stringify(a));}};Z.P={left:Z.V,right:Z.aa,above:Z.R,below:Z.S,near:Z.W};Z.O={left:Z.u,right:Z.u,above:Z.u,below:Z.u,near:Z.u};
|
|
118
|
+
ud.j=function(a,b){return Y.K(a,b,!0)};var Z={F:function(a,b){return function(c){var d=Z.u(a);d=W(d);c=W(c);return b.call(null,d,c)}},R:function(a){return Z.F(a,function(b,c){return c.b+c.height<b.b})},S:function(a){return Z.F(a,function(b,c){return b.b+b.height<c.b})},V:function(a){return Z.F(a,function(b,c){return c.a+c.width<b.a})},aa:function(a){return Z.F(a,function(b,c){return b.a+b.width<c.a})},W:function(a,b){var c;b?c=b:"number"==typeof a.distance&&(c=a.distance);c||(c=100);return function(d){var e=Z.u(a);if(e===d)return!1;e=
|
|
119
|
+
W(e);d=W(d);var f=Math.abs(e.a+e.width-d.a),g=Math.abs(e.b+e.height-d.b);g=Math.abs(e.b-(d.b+d.height))<=c||g<=c;return(Math.abs(e.a-(d.a+d.width))<=c||f<=c)&&g?!0:Math.sqrt(Math.pow(Math.abs(e.a+e.width/2-(d.a+d.width/2)),2)+Math.pow(Math.abs(e.b+e.height/2-(d.b+d.height/2)),2))<=c}},u:function(a){if(ea(a)&&1==a.nodeType)return a;if(da(a))return Z.u(a.call(null));if(ea(a)){var b;a:{if(b=vd(a)){var c=wd[b];if(c&&da(c.o)){b=c.o(a[b],Bc.document);break a}}throw new P(61,"Unsupported locator strategy: "+
|
|
120
|
+
b);}if(!b)throw new P(7,"No element has been found by "+JSON.stringify(a));return b}throw new P(61,"Selector is of wrong type: "+JSON.stringify(a));}};Z.P={left:Z.V,right:Z.aa,above:Z.R,below:Z.S,near:Z.W};Z.O={left:Z.u,right:Z.u,above:Z.u,below:Z.u,near:Z.u};
|
|
121
|
+
Z.U=function(a,b){var c=[];q(a,function(e){e&&sa(b,function(f){var g=f.kind,h=Z.P[g];if(!h)throw new P(61,"Cannot find filter suitable for "+g);return h.apply(null,f.args)(e)},null)&&c.push(e)},null);a=b[b.length-1];var d=Z.O[a?a.kind:"unknown"];return d?(a=d.apply(null,a.args))?Z.ba(a,c):c:c};
|
|
121
122
|
Z.ba=function(a,b){function c(f){f=W(f);return Math.sqrt(Math.pow(d-(f.a+Math.max(1,f.width)/2),2)+Math.pow(e-(f.b+Math.max(1,f.height)/2),2))}a=W(a);var d=a.a+Math.max(1,a.width)/2,e=a.b+Math.max(1,a.height)/2;wa(b,function(f,g){return c(f)-c(g)});return b};Z.o=function(a,b){a=Z.j(a,b);return 0==a.length?null:a[0]};
|
|
122
123
|
Z.j=function(a,b){if(!a.hasOwnProperty("root")||!a.hasOwnProperty("filters"))throw new P(61,"Locator not suitable for relative locators: "+JSON.stringify(a));var c=a.filters,d=ca(c);if("array"!=d&&("object"!=d||"number"!=typeof c.length))throw new P(61,"Targets should be an array: "+JSON.stringify(a));var e;S(a.root)?e=[a.root]:e=xd(a.root,b);return 0==e.length?[]:Z.U(e,a.filters)};var yd={o:function(a,b){if(""===a)throw new P(32,'Unable to locate an element with the tagName ""');return b.getElementsByTagName(a)[0]||null},j:function(a,b){if(""===a)throw new P(32,'Unable to locate an element with the tagName ""');return b.getElementsByTagName(a)}};var wd={className:Dc,"class name":Dc,css:Qc,"css selector":Qc,relative:Z,id:td,linkText:Y,"link text":Y,name:{o:function(a,b){b=mb(eb(b),"*",null,b);return ta(b,function(c){return Xc(c,"name")==a})},j:function(a,b){b=mb(eb(b),"*",null,b);return oa(b,function(c){return Xc(c,"name")==a})}},partialLinkText:ud,"partial link text":ud,tagName:yd,"tag name":yd,xpath:T};function vd(a){for(var b in a)if(a.hasOwnProperty(b))return b;return null}
|
|
123
124
|
function xd(a,b){var c=vd(a);if(c){var d=wd[c];if(d&&da(d.j))return d.j(a[c],b||Bc.document)}throw new P(61,"Unsupported locator strategy: "+c);};ba("_",xd);; return this._.apply(null,arguments);}).apply({navigator:typeof window!='undefined'?window.navigator:null,document:typeof window!='undefined'?window.document:null}, arguments);};
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
const observer = new MutationObserver((mutations) => {
|
|
3
|
+
for (const mutation of mutations) {
|
|
4
|
+
switch (mutation.type) {
|
|
5
|
+
case 'attributes':
|
|
6
|
+
// Don't report our own attribute has changed.
|
|
7
|
+
if (mutation.attributeName === "data-__webdriver_id") {
|
|
8
|
+
break;
|
|
9
|
+
}
|
|
10
|
+
const curr = mutation.target.getAttribute(mutation.attributeName);
|
|
11
|
+
var id = mutation.target.dataset.__webdriver_id
|
|
12
|
+
if (!id) {
|
|
13
|
+
id = Math.random().toString(36).substring(2) + Date.now().toString(36);
|
|
14
|
+
mutation.target.dataset.__webdriver_id = id;
|
|
15
|
+
}
|
|
16
|
+
const json = JSON.stringify({
|
|
17
|
+
'target': id,
|
|
18
|
+
'name': mutation.attributeName,
|
|
19
|
+
'value': curr,
|
|
20
|
+
'oldValue': mutation.oldValue
|
|
21
|
+
});
|
|
22
|
+
__webdriver_attribute(json);
|
|
23
|
+
break;
|
|
24
|
+
default:
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
observer.observe(document, {
|
|
31
|
+
'attributes': true,
|
|
32
|
+
'attributeOldValue': true,
|
|
33
|
+
'characterData': true,
|
|
34
|
+
'characterDataOldValue': true,
|
|
35
|
+
'childList': true,
|
|
36
|
+
'subtree': true
|
|
37
|
+
});
|
|
38
|
+
})();
|
package/lib/by.js
CHANGED
package/lib/capabilities.js
CHANGED
|
@@ -84,7 +84,7 @@ const Platform = {
|
|
|
84
84
|
*
|
|
85
85
|
* @record
|
|
86
86
|
*/
|
|
87
|
-
function Timeouts() {}
|
|
87
|
+
function Timeouts() { }
|
|
88
88
|
|
|
89
89
|
/**
|
|
90
90
|
* Defines when, in milliseconds, to interrupt a script that is being
|
|
@@ -264,7 +264,7 @@ class Capabilities {
|
|
|
264
264
|
* @return {!Capabilities} A basic set of capabilities for Firefox.
|
|
265
265
|
*/
|
|
266
266
|
static firefox() {
|
|
267
|
-
return new Capabilities().setBrowserName(Browser.FIREFOX)
|
|
267
|
+
return new Capabilities().setBrowserName(Browser.FIREFOX).set("moz:debuggerAddress", true)
|
|
268
268
|
}
|
|
269
269
|
|
|
270
270
|
/**
|
package/lib/command.js
CHANGED
|
@@ -140,6 +140,8 @@ const Name = {
|
|
|
140
140
|
EXECUTE_ASYNC_SCRIPT: 'executeAsyncScript',
|
|
141
141
|
|
|
142
142
|
GET_ELEMENT_TEXT: 'getElementText',
|
|
143
|
+
GET_COMPUTED_ROLE: 'getAriaRole',
|
|
144
|
+
GET_COMPUTED_LABEL: 'getAccessibleName',
|
|
143
145
|
GET_ELEMENT_TAG_NAME: 'getElementTagName',
|
|
144
146
|
IS_ELEMENT_SELECTED: 'isElementSelected',
|
|
145
147
|
IS_ELEMENT_ENABLED: 'isElementEnabled',
|
package/lib/error.js
CHANGED
|
File without changes
|