selenium-webdriver 3.0.1 → 3.5.0
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 +92 -0
- package/NOTICE +1 -1
- package/README.md +11 -14
- package/chrome.js +125 -36
- package/edge.js +3 -3
- package/example/async_await_test.js +68 -0
- package/example/chrome_headless.js +47 -0
- package/example/chrome_mobile_emulation.js +1 -1
- package/example/firefox_channels.js +73 -0
- package/example/google_search_test.js +1 -1
- package/firefox/binary.js +114 -57
- package/firefox/extension.js +118 -81
- package/firefox/index.js +67 -135
- package/firefox/profile.js +13 -49
- package/ie.js +2 -2
- package/index.js +6 -3
- package/io/index.js +59 -0
- package/io/zip.js +214 -0
- package/lib/README +2 -3
- package/lib/actions.js +4 -4
- package/lib/atoms/getAttribute.js +9 -11
- package/lib/atoms/is-displayed.js +102 -0
- package/lib/by.js +9 -1
- package/lib/capabilities.js +5 -5
- package/lib/command.js +2 -0
- package/lib/error.js +29 -4
- package/lib/events.js +1 -1
- package/lib/firefox/webdriver.json +2 -1
- package/lib/http.js +84 -69
- package/lib/input.js +1 -1
- package/lib/promise.js +205 -81
- package/lib/symbols.js +1 -1
- package/lib/test/data/click_tests/disabled_element.html +12 -0
- package/lib/test/data/firefox/webextension.xpi +0 -0
- package/lib/test/data/key_logger.html +34 -0
- package/lib/test/data/nestedElements.html +10 -1
- package/lib/test/data/single_text_input.html +12 -0
- package/lib/test/index.js +9 -35
- package/lib/until.js +1 -1
- package/lib/webdriver.js +130 -34
- package/net/portprober.js +1 -1
- package/opera.js +2 -2
- package/package.json +2 -2
- package/phantomjs.js +2 -2
- package/remote/index.js +17 -11
- package/safari.js +47 -8
- package/test/firefox/extension_test.js +41 -17
- package/test/firefox/firefox_test.js +70 -23
- package/test/firefox/profile_test.js +14 -59
- package/test/http/http_test.js +18 -0
- package/test/{io_test.js → io/io_test.js} +40 -1
- package/test/io/zip_test.js +128 -0
- package/test/lib/by_test.js +21 -0
- package/test/lib/error_test.js +20 -1
- package/test/lib/http_test.js +41 -2
- package/test/lib/promise_test.js +19 -0
- package/test/lib/until_test.js +28 -13
- package/test/lib/webdriver_test.js +107 -3
- package/test/page_loading_test.js +0 -6
- package/test/rect_test.js +60 -0
- package/test/remote_test.js +3 -3
- package/test/session_test.js +68 -23
- package/testing/index.js +16 -5
- package/lib/atoms/isDisplayed.js +0 -106
- package/lib/firefox/amd64/libnoblur64.so +0 -0
- package/lib/firefox/i386/libnoblur.so +0 -0
- package/lib/firefox/webdriver.xpi +0 -0
package/lib/symbols.js
CHANGED
|
@@ -30,7 +30,7 @@ module.exports = {
|
|
|
30
30
|
* available, the serialize method will return a promise that will be resolved
|
|
31
31
|
* with the serialized form.
|
|
32
32
|
*
|
|
33
|
-
* Note that the described method is
|
|
33
|
+
* Note that the described method is analogous to objects that define a
|
|
34
34
|
* `toJSON()` method, except the serialized result may be a promise, or
|
|
35
35
|
* another object with a promised property.
|
|
36
36
|
*/
|
|
Binary file
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
4
|
+
<head>
|
|
5
|
+
<title>Testing Key Events</title>
|
|
6
|
+
<script type="text/javascript">
|
|
7
|
+
function appendMessage(message) {
|
|
8
|
+
document.getElementById('resultParagraph').innerHTML += message + " ";
|
|
9
|
+
}
|
|
10
|
+
</script>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<div id="resultContainer" height="30">
|
|
14
|
+
<div id="result" style="width:300;height:60">
|
|
15
|
+
<p id="resultParagraph"> </p>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<div>
|
|
20
|
+
<form action="resultPage.html" id="on-form">
|
|
21
|
+
<input id="theworks"
|
|
22
|
+
onfocus="appendMessage('focus')"
|
|
23
|
+
onkeydown="appendMessage('keydown')"
|
|
24
|
+
onkeypress="appendMessage('keypress')"
|
|
25
|
+
onkeyup="appendMessage('keyup')"
|
|
26
|
+
onblur="appendMessage('blur')"
|
|
27
|
+
onchange="appendMessage('change')"
|
|
28
|
+
/>
|
|
29
|
+
</form>
|
|
30
|
+
</div>
|
|
31
|
+
</body>
|
|
32
|
+
</html>
|
|
33
|
+
|
|
34
|
+
|
|
@@ -5,6 +5,15 @@
|
|
|
5
5
|
<div id="test_id_div">
|
|
6
6
|
<p id="test_id">inside</p>
|
|
7
7
|
</div>
|
|
8
|
+
<div id="test_special_chars">
|
|
9
|
+
<p id="white space">space</p>
|
|
10
|
+
<p id="css#.chars">css escapes</p>
|
|
11
|
+
</div>
|
|
12
|
+
<div id="test_special_chars_2">
|
|
13
|
+
<p id="white space">second copy for testing plural findElements</p>
|
|
14
|
+
<p id="css#.chars">second copy</p>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
8
17
|
<form method="get" action="resultPage.html" name="form1" style="display: block">
|
|
9
18
|
Here's a checkbox: <input type="checkbox" id="checky" name="checky" value="furrfu"/><br/>
|
|
10
19
|
<select name="selectomatic" id="1">
|
|
@@ -152,4 +161,4 @@
|
|
|
152
161
|
<span class="oneother">But not me</span>
|
|
153
162
|
</div>
|
|
154
163
|
</body>
|
|
155
|
-
</html>
|
|
164
|
+
</html>
|
package/lib/test/index.js
CHANGED
|
@@ -24,15 +24,13 @@ var build = require('./build'),
|
|
|
24
24
|
webdriver = require('../../'),
|
|
25
25
|
flow = webdriver.promise.controlFlow(),
|
|
26
26
|
firefox = require('../../firefox'),
|
|
27
|
+
logging = require('../../lib/logging'),
|
|
27
28
|
safari = require('../../safari'),
|
|
28
29
|
remote = require('../../remote'),
|
|
29
30
|
testing = require('../../testing'),
|
|
30
31
|
fileserver = require('./fileserver');
|
|
31
32
|
|
|
32
33
|
|
|
33
|
-
const LEGACY_FIREFOX = 'legacy-' + webdriver.Browser.FIREFOX;
|
|
34
|
-
|
|
35
|
-
|
|
36
34
|
/**
|
|
37
35
|
* Browsers with native support.
|
|
38
36
|
* @type {!Array.<webdriver.Browser>}
|
|
@@ -41,7 +39,6 @@ var NATIVE_BROWSERS = [
|
|
|
41
39
|
webdriver.Browser.CHROME,
|
|
42
40
|
webdriver.Browser.EDGE,
|
|
43
41
|
webdriver.Browser.FIREFOX,
|
|
44
|
-
LEGACY_FIREFOX,
|
|
45
42
|
webdriver.Browser.IE,
|
|
46
43
|
webdriver.Browser.OPERA,
|
|
47
44
|
webdriver.Browser.PHANTOM_JS,
|
|
@@ -49,13 +46,18 @@ var NATIVE_BROWSERS = [
|
|
|
49
46
|
];
|
|
50
47
|
|
|
51
48
|
|
|
49
|
+
var noBuild = /^1|true$/i.test(process.env['SELENIUM_NO_BUILD']);
|
|
52
50
|
var serverJar = process.env['SELENIUM_SERVER_JAR'];
|
|
53
51
|
var remoteUrl = process.env['SELENIUM_REMOTE_URL'];
|
|
54
52
|
var useLoopback = process.env['SELENIUM_USE_LOOP_BACK'] == '1';
|
|
55
|
-
var noMarionette = /^0|false$/i.test(process.env['SELENIUM_GECKODRIVER']);
|
|
56
53
|
var startServer = !!serverJar && !remoteUrl;
|
|
57
54
|
var nativeRun = !serverJar && !remoteUrl;
|
|
58
55
|
|
|
56
|
+
if (/^1|true$/i.test(process.env['SELENIUM_VERBOSE'])) {
|
|
57
|
+
logging.installConsoleHandler();
|
|
58
|
+
logging.getLogger('webdriver.http').setLevel(logging.Level.ALL);
|
|
59
|
+
}
|
|
60
|
+
|
|
59
61
|
var browsersToTest = (function() {
|
|
60
62
|
var permitRemoteBrowsers = !!remoteUrl || !!serverJar;
|
|
61
63
|
var permitUnknownBrowsers = !nativeRun;
|
|
@@ -69,9 +71,6 @@ var browsersToTest = (function() {
|
|
|
69
71
|
if (parts[0] === 'edge') {
|
|
70
72
|
parts[0] = webdriver.Browser.EDGE;
|
|
71
73
|
}
|
|
72
|
-
if (noMarionette && parts[0] === webdriver.Browser.FIREFOX) {
|
|
73
|
-
parts[0] = LEGACY_FIREFOX;
|
|
74
|
-
}
|
|
75
74
|
return parts.join(':');
|
|
76
75
|
});
|
|
77
76
|
|
|
@@ -81,10 +80,6 @@ var browsersToTest = (function() {
|
|
|
81
80
|
parts[0] = webdriver.Browser.IE;
|
|
82
81
|
}
|
|
83
82
|
|
|
84
|
-
if (parts[0] === LEGACY_FIREFOX) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
83
|
if (NATIVE_BROWSERS.indexOf(parts[0]) == -1 && !permitRemoteBrowsers) {
|
|
89
84
|
throw Error('Browser ' + parts[0] + ' requires a WebDriver server and ' +
|
|
90
85
|
'neither the SELENIUM_REMOTE_URL nor the SELENIUM_SERVER_JAR ' +
|
|
@@ -150,10 +145,6 @@ function TestEnvironment(browserName, server) {
|
|
|
150
145
|
return server || remoteUrl;
|
|
151
146
|
};
|
|
152
147
|
|
|
153
|
-
this.isMarionette = function() {
|
|
154
|
-
return !noMarionette;
|
|
155
|
-
};
|
|
156
|
-
|
|
157
148
|
this.browsers = function(var_args) {
|
|
158
149
|
var browsersToIgnore = Array.prototype.slice.apply(arguments, [0]);
|
|
159
150
|
return browsers(browserName, browsersToIgnore);
|
|
@@ -164,15 +155,7 @@ function TestEnvironment(browserName, server) {
|
|
|
164
155
|
var realBuild = builder.build;
|
|
165
156
|
|
|
166
157
|
builder.build = function() {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
if (parts[0] === LEGACY_FIREFOX) {
|
|
170
|
-
var options = builder.getFirefoxOptions() || new firefox.Options();
|
|
171
|
-
options.useGeckoDriver(false);
|
|
172
|
-
builder.setFirefoxOptions(options);
|
|
173
|
-
|
|
174
|
-
parts[0] = webdriver.Browser.FIREFOX;
|
|
175
|
-
}
|
|
158
|
+
let parts = browserName.split(/:/, 3);
|
|
176
159
|
|
|
177
160
|
builder.forBrowser(parts[0], parts[1], parts[2]);
|
|
178
161
|
if (server) {
|
|
@@ -219,7 +202,7 @@ function suite(fn, opt_options) {
|
|
|
219
202
|
try {
|
|
220
203
|
|
|
221
204
|
before(function() {
|
|
222
|
-
if (isDevMode) {
|
|
205
|
+
if (isDevMode && !noBuild) {
|
|
223
206
|
return build.of(
|
|
224
207
|
'//javascript/atoms/fragments:is-displayed',
|
|
225
208
|
'//javascript/webdriver/atoms:getAttribute')
|
|
@@ -237,15 +220,6 @@ function suite(fn, opt_options) {
|
|
|
237
220
|
browsers.forEach(function(browser) {
|
|
238
221
|
describe('[' + browser + ']', function() {
|
|
239
222
|
|
|
240
|
-
if (isDevMode && nativeRun) {
|
|
241
|
-
if (browser === LEGACY_FIREFOX) {
|
|
242
|
-
before(function() {
|
|
243
|
-
return build.of('//javascript/firefox-driver:webdriver')
|
|
244
|
-
.onlyOnce().go();
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
223
|
var serverToUse = null;
|
|
250
224
|
|
|
251
225
|
if (!!serverJar && !remoteUrl) {
|
package/lib/until.js
CHANGED
|
@@ -72,7 +72,7 @@ const webdriver = require('./webdriver'),
|
|
|
72
72
|
exports.ableToSwitchToFrame = function ableToSwitchToFrame(frame) {
|
|
73
73
|
var condition;
|
|
74
74
|
if (typeof frame === 'number' || frame instanceof webdriver.WebElement) {
|
|
75
|
-
condition = attemptToSwitchFrames;
|
|
75
|
+
condition = driver => attemptToSwitchFrames(driver, frame);
|
|
76
76
|
} else {
|
|
77
77
|
condition = function(driver) {
|
|
78
78
|
let locator = /** @type {!(By|Function)} */(frame);
|
package/lib/webdriver.js
CHANGED
|
@@ -457,12 +457,12 @@ class IWebDriver {
|
|
|
457
457
|
* while evaluating the condition, they will be allowed to propagate. In the
|
|
458
458
|
* event a condition returns a {@link promise.Promise promise}, the polling
|
|
459
459
|
* loop will wait for it to be resolved and use the resolved value for whether
|
|
460
|
-
* the condition has been
|
|
460
|
+
* the condition has been satisfied. Note the resolution time for a promise
|
|
461
461
|
* is factored into whether a wait has timed out.
|
|
462
462
|
*
|
|
463
463
|
* Note, if the provided condition is a {@link WebElementCondition}, then
|
|
464
464
|
* the wait will return a {@link WebElementPromise} that will resolve to the
|
|
465
|
-
* element that
|
|
465
|
+
* element that satisfied the condition.
|
|
466
466
|
*
|
|
467
467
|
* _Example:_ waiting up to 10 seconds for an element to be present on the
|
|
468
468
|
* page.
|
|
@@ -750,20 +750,12 @@ class WebDriver {
|
|
|
750
750
|
* commands should execute under, including the initial session creation.
|
|
751
751
|
* Defaults to the {@link promise.controlFlow() currently active}
|
|
752
752
|
* control flow.
|
|
753
|
-
* @param {(function(new: WebDriver,
|
|
754
|
-
* !IThenable<!Session>,
|
|
755
|
-
* !command.Executor,
|
|
756
|
-
* promise.ControlFlow=))=} opt_ctor
|
|
757
|
-
* A reference to the constructor of the specific type of WebDriver client
|
|
758
|
-
* to instantiate. Will create a vanilla {@linkplain WebDriver} instance
|
|
759
|
-
* if a constructor is not provided.
|
|
760
753
|
* @param {(function(this: void): ?)=} opt_onQuit A callback to invoke when
|
|
761
754
|
* the newly created session is terminated. This should be used to clean
|
|
762
755
|
* up any resources associated with the session.
|
|
763
756
|
* @return {!WebDriver} The driver for the newly created session.
|
|
764
757
|
*/
|
|
765
|
-
static createSession(
|
|
766
|
-
executor, capabilities, opt_flow, opt_ctor, opt_onQuit) {
|
|
758
|
+
static createSession(executor, capabilities, opt_flow, opt_onQuit) {
|
|
767
759
|
let flow = opt_flow || promise.controlFlow();
|
|
768
760
|
let cmd = new command.Command(command.Name.NEW_SESSION);
|
|
769
761
|
|
|
@@ -779,11 +771,10 @@ class WebDriver {
|
|
|
779
771
|
'WebDriver.createSession()');
|
|
780
772
|
if (typeof opt_onQuit === 'function') {
|
|
781
773
|
session = session.catch(err => {
|
|
782
|
-
return Promise.resolve(opt_onQuit.call(void 0)).then(_ => {throw err});
|
|
774
|
+
return Promise.resolve(opt_onQuit.call(void 0)).then(_ => {throw err;});
|
|
783
775
|
});
|
|
784
776
|
}
|
|
785
|
-
|
|
786
|
-
return new ctor(session, executor, flow, opt_onQuit);
|
|
777
|
+
return new this(session, executor, flow, opt_onQuit);
|
|
787
778
|
}
|
|
788
779
|
|
|
789
780
|
/** @override */
|
|
@@ -850,7 +841,7 @@ class WebDriver {
|
|
|
850
841
|
new command.Command(command.Name.QUIT),
|
|
851
842
|
'WebDriver.quit()');
|
|
852
843
|
// Delete our session ID when the quit command finishes; this will allow us
|
|
853
|
-
// to throw an error when
|
|
844
|
+
// to throw an error when attempting to use a driver post-quit.
|
|
854
845
|
return /** @type {!promise.Thenable} */(promise.finally(result, () => {
|
|
855
846
|
this.session_ = this.flow_.promise((_, reject) => {
|
|
856
847
|
reject(new error.NoSuchSessionError(
|
|
@@ -1181,7 +1172,7 @@ class Navigation {
|
|
|
1181
1172
|
/**
|
|
1182
1173
|
* Provides methods for managing browser and driver state.
|
|
1183
1174
|
*
|
|
1184
|
-
* This class should never be instantiated directly.
|
|
1175
|
+
* This class should never be instantiated directly. Instead, obtain an instance
|
|
1185
1176
|
* with {@linkplain WebDriver#manage() webdriver.manage()}.
|
|
1186
1177
|
*/
|
|
1187
1178
|
class Options {
|
|
@@ -1326,6 +1317,91 @@ class Options {
|
|
|
1326
1317
|
});
|
|
1327
1318
|
}
|
|
1328
1319
|
|
|
1320
|
+
/**
|
|
1321
|
+
* Schedules a command to fetch the timeouts currently configured for the
|
|
1322
|
+
* current session.
|
|
1323
|
+
*
|
|
1324
|
+
* @return {!promise.Thenable<{script: number,
|
|
1325
|
+
* pageLoad: number,
|
|
1326
|
+
* implicit: number}>} A promise that will be
|
|
1327
|
+
* resolved with the timeouts currently configured for the current
|
|
1328
|
+
* session.
|
|
1329
|
+
* @see #setTimeouts()
|
|
1330
|
+
*/
|
|
1331
|
+
getTimeouts() {
|
|
1332
|
+
return this.driver_.schedule(
|
|
1333
|
+
new command.Command(command.Name.GET_TIMEOUT),
|
|
1334
|
+
`WebDriver.manage().getTimeouts()`)
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
/**
|
|
1338
|
+
* Schedules a command to set timeout durations associated with the current
|
|
1339
|
+
* session.
|
|
1340
|
+
*
|
|
1341
|
+
* The following timeouts are supported (all timeouts are specified in
|
|
1342
|
+
* milliseconds):
|
|
1343
|
+
*
|
|
1344
|
+
* - `implicit` specifies the maximum amount of time to wait for an element
|
|
1345
|
+
* locator to succeed when {@linkplain WebDriver#findElement locating}
|
|
1346
|
+
* {@linkplain WebDriver#findElements elements} on the page.
|
|
1347
|
+
* Defaults to 0 milliseconds.
|
|
1348
|
+
*
|
|
1349
|
+
* - `pageLoad` specifies the maximum amount of time to wait for a page to
|
|
1350
|
+
* finishing loading. Defaults to 300000 milliseconds.
|
|
1351
|
+
*
|
|
1352
|
+
* - `script` specifies the maximum amount of time to wait for an
|
|
1353
|
+
* {@linkplain WebDriver#executeScript evaluated script} to run. If set to
|
|
1354
|
+
* `null`, the script timeout will be indefinite.
|
|
1355
|
+
* Defaults to 30000 milliseconds.
|
|
1356
|
+
*
|
|
1357
|
+
* @param {{script: (number|null|undefined),
|
|
1358
|
+
* pageLoad: (number|null|undefined),
|
|
1359
|
+
* implicit: (number|null|undefined)}} conf
|
|
1360
|
+
* The desired timeout configuration.
|
|
1361
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved when the
|
|
1362
|
+
* timeouts have been set.
|
|
1363
|
+
* @throws {!TypeError} if an invalid options object is provided.
|
|
1364
|
+
* @see #getTimeouts()
|
|
1365
|
+
* @see <https://w3c.github.io/webdriver/webdriver-spec.html#dfn-set-timeouts>
|
|
1366
|
+
*/
|
|
1367
|
+
setTimeouts({script, pageLoad, implicit} = {}) {
|
|
1368
|
+
let cmd = new command.Command(command.Name.SET_TIMEOUT);
|
|
1369
|
+
|
|
1370
|
+
let valid = false;
|
|
1371
|
+
function setParam(key, value) {
|
|
1372
|
+
if (value === null || typeof value === 'number') {
|
|
1373
|
+
valid = true;
|
|
1374
|
+
cmd.setParameter(key, value);
|
|
1375
|
+
} else if (typeof value !== 'undefined') {
|
|
1376
|
+
throw TypeError(
|
|
1377
|
+
'invalid timeouts configuration:'
|
|
1378
|
+
+ ` expected "${key}" to be a number, got ${typeof value}`);
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
setParam('implicit', implicit);
|
|
1382
|
+
setParam('pageLoad', pageLoad);
|
|
1383
|
+
setParam('script', script);
|
|
1384
|
+
|
|
1385
|
+
if (valid) {
|
|
1386
|
+
return this.driver_.schedule(cmd, `WebDriver.manage().setTimeouts()`)
|
|
1387
|
+
.catch(() => {
|
|
1388
|
+
// Fallback to the legacy method.
|
|
1389
|
+
let cmds = [];
|
|
1390
|
+
if (typeof script === 'number') {
|
|
1391
|
+
cmds.push(legacyTimeout(this.driver_, 'script', script));
|
|
1392
|
+
}
|
|
1393
|
+
if (typeof implicit === 'number') {
|
|
1394
|
+
cmds.push(legacyTimeout(this.driver_, 'implicit', implicit));
|
|
1395
|
+
}
|
|
1396
|
+
if (typeof pageLoad === 'number') {
|
|
1397
|
+
cmds.push(legacyTimeout(this.driver_, 'page load', pageLoad));
|
|
1398
|
+
}
|
|
1399
|
+
return Promise.all(cmds);
|
|
1400
|
+
});
|
|
1401
|
+
}
|
|
1402
|
+
throw TypeError('no timeouts specified');
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1329
1405
|
/**
|
|
1330
1406
|
* @return {!Logs} The interface for managing driver
|
|
1331
1407
|
* logs.
|
|
@@ -1336,6 +1412,7 @@ class Options {
|
|
|
1336
1412
|
|
|
1337
1413
|
/**
|
|
1338
1414
|
* @return {!Timeouts} The interface for managing driver timeouts.
|
|
1415
|
+
* @deprecated Use {@link #setTimeouts()} instead.
|
|
1339
1416
|
*/
|
|
1340
1417
|
timeouts() {
|
|
1341
1418
|
return new Timeouts(this.driver_);
|
|
@@ -1350,6 +1427,22 @@ class Options {
|
|
|
1350
1427
|
}
|
|
1351
1428
|
|
|
1352
1429
|
|
|
1430
|
+
/**
|
|
1431
|
+
* @param {!WebDriver} driver
|
|
1432
|
+
* @param {string} type
|
|
1433
|
+
* @param {number} ms
|
|
1434
|
+
* @return {!promise.Thenable<void>}
|
|
1435
|
+
*/
|
|
1436
|
+
function legacyTimeout(driver, type, ms) {
|
|
1437
|
+
return driver.schedule(
|
|
1438
|
+
new command.Command(command.Name.SET_TIMEOUT)
|
|
1439
|
+
.setParameter('type', type)
|
|
1440
|
+
.setParameter('ms', ms),
|
|
1441
|
+
`WebDriver.manage().setTimeouts({${type}: ${ms}})`);
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
|
|
1445
|
+
|
|
1353
1446
|
/**
|
|
1354
1447
|
* A record object describing a browser cookie.
|
|
1355
1448
|
*
|
|
@@ -1427,11 +1520,14 @@ Options.Cookie.prototype.expiry;
|
|
|
1427
1520
|
/**
|
|
1428
1521
|
* An interface for managing timeout behavior for WebDriver instances.
|
|
1429
1522
|
*
|
|
1430
|
-
* This class should never be instantiated directly.
|
|
1523
|
+
* This class should never be instantiated directly. Instead, obtain an instance
|
|
1431
1524
|
* with
|
|
1432
1525
|
*
|
|
1433
1526
|
* webdriver.manage().timeouts()
|
|
1434
1527
|
*
|
|
1528
|
+
* @deprecated This has been deprecated in favor of
|
|
1529
|
+
* {@link Options#setTimeouts()}, which supports setting multiple timeouts
|
|
1530
|
+
* at once.
|
|
1435
1531
|
* @see WebDriver#manage()
|
|
1436
1532
|
* @see Options#timeouts()
|
|
1437
1533
|
*/
|
|
@@ -1465,9 +1561,11 @@ class Timeouts {
|
|
|
1465
1561
|
* @param {number} ms The amount of time to wait, in milliseconds.
|
|
1466
1562
|
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1467
1563
|
* when the implicit wait timeout has been set.
|
|
1564
|
+
* @deprecated Use {@link Options#setTimeouts()
|
|
1565
|
+
* driver.manage().setTimeouts({implicit: ms})}.
|
|
1468
1566
|
*/
|
|
1469
1567
|
implicitlyWait(ms) {
|
|
1470
|
-
return this.
|
|
1568
|
+
return this.driver_.manage().setTimeouts({implicit: ms});
|
|
1471
1569
|
}
|
|
1472
1570
|
|
|
1473
1571
|
/**
|
|
@@ -1478,9 +1576,11 @@ class Timeouts {
|
|
|
1478
1576
|
* @param {number} ms The amount of time to wait, in milliseconds.
|
|
1479
1577
|
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1480
1578
|
* when the script timeout has been set.
|
|
1579
|
+
* @deprecated Use {@link Options#setTimeouts()
|
|
1580
|
+
* driver.manage().setTimeouts({script: ms})}.
|
|
1481
1581
|
*/
|
|
1482
1582
|
setScriptTimeout(ms) {
|
|
1483
|
-
return this.
|
|
1583
|
+
return this.driver_.manage().setTimeouts({script: ms});
|
|
1484
1584
|
}
|
|
1485
1585
|
|
|
1486
1586
|
/**
|
|
@@ -1491,17 +1591,11 @@ class Timeouts {
|
|
|
1491
1591
|
* @param {number} ms The amount of time to wait, in milliseconds.
|
|
1492
1592
|
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1493
1593
|
* when the timeout has been set.
|
|
1594
|
+
* @deprecated Use {@link Options#setTimeouts()
|
|
1595
|
+
* driver.manage().setTimeouts({pageLoad: ms})}.
|
|
1494
1596
|
*/
|
|
1495
1597
|
pageLoadTimeout(ms) {
|
|
1496
|
-
return this.
|
|
1497
|
-
}
|
|
1498
|
-
|
|
1499
|
-
_scheduleCommand(ms, timeoutIdentifier, timeoutName) {
|
|
1500
|
-
return this.driver_.schedule(
|
|
1501
|
-
new command.Command(command.Name.SET_TIMEOUT).
|
|
1502
|
-
setParameter('type', timeoutIdentifier).
|
|
1503
|
-
setParameter('ms', ms),
|
|
1504
|
-
`WebDriver.manage().timeouts().${timeoutName}(${ms})`);
|
|
1598
|
+
return this.driver_.manage().setTimeouts({pageLoad: ms});
|
|
1505
1599
|
}
|
|
1506
1600
|
}
|
|
1507
1601
|
|
|
@@ -2009,7 +2103,7 @@ class WebElement {
|
|
|
2009
2103
|
* this instance.
|
|
2010
2104
|
*
|
|
2011
2105
|
* Modifier keys (SHIFT, CONTROL, ALT, META) are stateful; once a modifier is
|
|
2012
|
-
* processed in the
|
|
2106
|
+
* processed in the key sequence, that key state is toggled until one of the
|
|
2013
2107
|
* following occurs:
|
|
2014
2108
|
*
|
|
2015
2109
|
* - The modifier key is encountered again in the sequence. At this point the
|
|
@@ -2028,13 +2122,13 @@ class WebElement {
|
|
|
2028
2122
|
* Key.chord(Key.CONTROL, "a"),
|
|
2029
2123
|
* "now text is");
|
|
2030
2124
|
*
|
|
2031
|
-
* - The end of the
|
|
2125
|
+
* - The end of the key sequence is encountered. When there are no more keys
|
|
2032
2126
|
* to type, all depressed modifier keys are released (with accompanying
|
|
2033
2127
|
* keyup events).
|
|
2034
2128
|
*
|
|
2035
2129
|
* If this element is a file input ({@code <input type="file">}), the
|
|
2036
2130
|
* specified key sequence should specify the path to the file to attach to
|
|
2037
|
-
* the element. This is
|
|
2131
|
+
* the element. This is analogous to the user clicking "Browse..." and entering
|
|
2038
2132
|
* the path into the file select dialog.
|
|
2039
2133
|
*
|
|
2040
2134
|
* var form = driver.findElement(By.css('form'));
|
|
@@ -2050,7 +2144,7 @@ class WebElement {
|
|
|
2050
2144
|
*
|
|
2051
2145
|
* __Note:__ On browsers where native keyboard events are not supported
|
|
2052
2146
|
* (e.g. Firefox on OS X), key events will be synthesized. Special
|
|
2053
|
-
*
|
|
2147
|
+
* punctuation keys will be synthesized according to a standard QWERTY en-us
|
|
2054
2148
|
* keyboard layout.
|
|
2055
2149
|
*
|
|
2056
2150
|
* @param {...(number|string|!IThenable<(number|string)>)} var_args The
|
|
@@ -2083,6 +2177,7 @@ class WebElement {
|
|
|
2083
2177
|
if (!this.driver_.fileDetector_) {
|
|
2084
2178
|
return this.schedule_(
|
|
2085
2179
|
new command.Command(command.Name.SEND_KEYS_TO_ELEMENT).
|
|
2180
|
+
setParameter('text', keys.then(keys => keys.join(''))).
|
|
2086
2181
|
setParameter('value', keys),
|
|
2087
2182
|
'WebElement.sendKeys()');
|
|
2088
2183
|
}
|
|
@@ -2098,6 +2193,7 @@ class WebElement {
|
|
|
2098
2193
|
}).then(function(keys) {
|
|
2099
2194
|
return element.schedule_(
|
|
2100
2195
|
new command.Command(command.Name.SEND_KEYS_TO_ELEMENT).
|
|
2196
|
+
setParameter('text', keys).
|
|
2101
2197
|
setParameter('value', keys.split('')),
|
|
2102
2198
|
'WebElement.sendKeys()');
|
|
2103
2199
|
});
|
|
@@ -2214,7 +2310,7 @@ class WebElement {
|
|
|
2214
2310
|
|
|
2215
2311
|
/**
|
|
2216
2312
|
* Schedules a command to query whether the DOM element represented by this
|
|
2217
|
-
* instance is enabled, as
|
|
2313
|
+
* instance is enabled, as dictated by the {@code disabled} attribute.
|
|
2218
2314
|
* @return {!promise.Thenable<boolean>} A promise that will be
|
|
2219
2315
|
* resolved with whether this element is currently enabled.
|
|
2220
2316
|
*/
|
|
@@ -2327,7 +2423,7 @@ class WebElementPromise extends WebElement {
|
|
|
2327
2423
|
if (promise.CancellableThenable.isImplementation(el)) {
|
|
2328
2424
|
/** @type {!promise.CancellableThenable} */(el).cancel(opt_reason);
|
|
2329
2425
|
}
|
|
2330
|
-
}
|
|
2426
|
+
};
|
|
2331
2427
|
|
|
2332
2428
|
/** @override */
|
|
2333
2429
|
this.then = el.then.bind(el);
|
package/net/portprober.js
CHANGED
package/opera.js
CHANGED
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
* var options = new opera.Options();
|
|
63
63
|
* // configure browser options ...
|
|
64
64
|
*
|
|
65
|
-
* var driver =
|
|
65
|
+
* var driver = opera.Driver.createSession(options, service);
|
|
66
66
|
*
|
|
67
67
|
* Users should only instantiate the {@link Driver} class directly when they
|
|
68
68
|
* need a custom driver service configuration (as shown above). For normal
|
|
@@ -383,7 +383,7 @@ class Driver extends webdriver.WebDriver {
|
|
|
383
383
|
}
|
|
384
384
|
|
|
385
385
|
return /** @type {!Driver} */(
|
|
386
|
-
|
|
386
|
+
super.createSession(executor, caps, opt_flow));
|
|
387
387
|
}
|
|
388
388
|
|
|
389
389
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "selenium-webdriver",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.5.0",
|
|
4
4
|
"description": "The official WebDriver JavaScript bindings from the Selenium project",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"keywords": [
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"node": ">= 6.9.0"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"
|
|
26
|
+
"jszip": "^3.1.3",
|
|
27
27
|
"rimraf": "^2.5.4",
|
|
28
28
|
"tmp": "0.0.30",
|
|
29
29
|
"xml2js": "^0.4.17"
|
package/phantomjs.js
CHANGED
|
@@ -217,8 +217,8 @@ class Driver extends webdriver.WebDriver {
|
|
|
217
217
|
});
|
|
218
218
|
|
|
219
219
|
var executor = createExecutor(service.start());
|
|
220
|
-
return /** @type {!Driver} */(
|
|
221
|
-
executor, caps, opt_flow,
|
|
220
|
+
return /** @type {!Driver} */(super.createSession(
|
|
221
|
+
executor, caps, opt_flow, () => service.kill()));
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
/**
|
package/remote/index.js
CHANGED
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
|
|
18
18
|
'use strict';
|
|
19
19
|
|
|
20
|
-
const AdmZip = require('adm-zip');
|
|
21
20
|
const fs = require('fs');
|
|
22
21
|
const path = require('path');
|
|
23
22
|
const url = require('url');
|
|
@@ -26,6 +25,7 @@ const util = require('util');
|
|
|
26
25
|
const httpUtil = require('../http/util');
|
|
27
26
|
const io = require('../io');
|
|
28
27
|
const exec = require('../io/exec');
|
|
28
|
+
const {Zip} = require('../io/zip');
|
|
29
29
|
const cmd = require('../lib/command');
|
|
30
30
|
const input = require('../lib/input');
|
|
31
31
|
const promise = require('../lib/promise');
|
|
@@ -492,7 +492,12 @@ class SeleniumServer extends DriverService {
|
|
|
492
492
|
return jvmArgs.concat('-jar', jar, '-port', port).concat(args);
|
|
493
493
|
});
|
|
494
494
|
|
|
495
|
-
|
|
495
|
+
let java = 'java';
|
|
496
|
+
if (process.env['JAVA_HOME']) {
|
|
497
|
+
java = path.join(process.env['JAVA_HOME'], 'bin/java');
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
super(java, {
|
|
496
501
|
loopback: options.loopback,
|
|
497
502
|
port: port,
|
|
498
503
|
args: args,
|
|
@@ -570,15 +575,16 @@ class FileDetector extends input.FileDetector {
|
|
|
570
575
|
return file; // Not a valid file, return original input.
|
|
571
576
|
}
|
|
572
577
|
|
|
573
|
-
|
|
574
|
-
zip.
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
578
|
+
let zip = new Zip;
|
|
579
|
+
return zip.addFile(file)
|
|
580
|
+
.then(() => zip.toBuffer())
|
|
581
|
+
.then(buf => buf.toString('base64'))
|
|
582
|
+
.then(encodedZip => {
|
|
583
|
+
let command = new cmd.Command(cmd.Name.UPLOAD_FILE)
|
|
584
|
+
.setParameter('file', encodedZip);
|
|
585
|
+
return driver.schedule(command,
|
|
586
|
+
'remote.FileDetector.handleFile(' + file + ')');
|
|
587
|
+
});
|
|
582
588
|
}, function(err) {
|
|
583
589
|
if (err.code === 'ENOENT') {
|
|
584
590
|
return file; // Not a file; return original input.
|