selenium-webdriver 3.1.0 → 3.6.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 +112 -0
- package/NOTICE +1 -1
- package/README.md +5 -11
- package/chrome.js +122 -33
- package/edge.js +2 -2
- package/example/async_await_test.js +69 -0
- package/example/chrome_android.js +2 -3
- package/example/chrome_mobile_emulation.js +3 -4
- package/example/firefox_channels.js +3 -3
- package/example/google_search.js +3 -3
- package/example/google_search_generator.js +2 -5
- package/example/google_search_test.js +5 -6
- package/example/headless.js +55 -0
- package/example/logging.js +3 -3
- package/example/parallel_flows.js +4 -7
- package/firefox/binary.js +3 -0
- package/firefox/extension.js +118 -81
- package/firefox/index.js +117 -263
- package/firefox/profile.js +18 -137
- package/ie.js +2 -2
- package/index.js +4 -1
- package/io/index.js +59 -0
- package/io/zip.js +214 -0
- package/lib/atoms/get-attribute.js +9 -0
- package/lib/atoms/is-displayed.js +73 -78
- package/lib/by.js +8 -0
- package/lib/capabilities.js +61 -22
- package/lib/command.js +2 -0
- package/lib/error.js +32 -2
- package/lib/http.js +53 -44
- package/lib/promise.js +72 -25
- package/lib/test/data/click_tests/disabled_element.html +12 -0
- package/lib/test/data/content-editable.html +10 -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/scrolling_tests/page_with_partially_hidden_element.html +14 -0
- package/lib/test/data/single_text_input.html +12 -0
- package/lib/test/index.js +4 -36
- package/lib/webdriver.js +147 -55
- package/net/portprober.js +1 -1
- package/opera.js +1 -1
- package/package.json +2 -2
- package/phantomjs.js +2 -2
- package/remote/index.js +21 -14
- package/safari.js +2 -2
- package/test/firefox/extension_test.js +41 -17
- package/test/firefox/firefox_test.js +37 -19
- 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 +21 -1
- package/test/lib/http_test.js +11 -3
- package/test/lib/webdriver_test.js +107 -3
- package/test/page_loading_test.js +0 -6
- package/test/remote_test.js +3 -3
- package/test/session_test.js +68 -23
- package/testing/index.js +2 -3
- package/lib/atoms/getAttribute.js +0 -12
- package/lib/firefox/amd64/libnoblur64.so +0 -0
- package/lib/firefox/i386/libnoblur.so +0 -0
- package/lib/firefox/webdriver.json +0 -69
- package/lib/firefox/webdriver.xpi +0 -0
|
@@ -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>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Page with partially hidden element</title>
|
|
5
|
+
</head>
|
|
6
|
+
<body>
|
|
7
|
+
<div style="width:200px; height: 200px; overflow: auto;">
|
|
8
|
+
<div style="height: 175px; width: 240px;">Placeholder</div>
|
|
9
|
+
<div>
|
|
10
|
+
<button type="button" style="height: 40px; box-sizing: border-box" id="btn" onclick="window.location='target_page.html'">Click me!</button>
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
</body>
|
|
14
|
+
</html>
|
package/lib/test/index.js
CHANGED
|
@@ -31,9 +31,6 @@ var build = require('./build'),
|
|
|
31
31
|
fileserver = require('./fileserver');
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
const LEGACY_FIREFOX = 'legacy-' + webdriver.Browser.FIREFOX;
|
|
35
|
-
|
|
36
|
-
|
|
37
34
|
/**
|
|
38
35
|
* Browsers with native support.
|
|
39
36
|
* @type {!Array.<webdriver.Browser>}
|
|
@@ -42,7 +39,6 @@ var NATIVE_BROWSERS = [
|
|
|
42
39
|
webdriver.Browser.CHROME,
|
|
43
40
|
webdriver.Browser.EDGE,
|
|
44
41
|
webdriver.Browser.FIREFOX,
|
|
45
|
-
LEGACY_FIREFOX,
|
|
46
42
|
webdriver.Browser.IE,
|
|
47
43
|
webdriver.Browser.OPERA,
|
|
48
44
|
webdriver.Browser.PHANTOM_JS,
|
|
@@ -50,10 +46,10 @@ var NATIVE_BROWSERS = [
|
|
|
50
46
|
];
|
|
51
47
|
|
|
52
48
|
|
|
49
|
+
var noBuild = /^1|true$/i.test(process.env['SELENIUM_NO_BUILD']);
|
|
53
50
|
var serverJar = process.env['SELENIUM_SERVER_JAR'];
|
|
54
51
|
var remoteUrl = process.env['SELENIUM_REMOTE_URL'];
|
|
55
52
|
var useLoopback = process.env['SELENIUM_USE_LOOP_BACK'] == '1';
|
|
56
|
-
var noMarionette = /^0|false$/i.test(process.env['SELENIUM_GECKODRIVER']);
|
|
57
53
|
var startServer = !!serverJar && !remoteUrl;
|
|
58
54
|
var nativeRun = !serverJar && !remoteUrl;
|
|
59
55
|
|
|
@@ -75,9 +71,6 @@ var browsersToTest = (function() {
|
|
|
75
71
|
if (parts[0] === 'edge') {
|
|
76
72
|
parts[0] = webdriver.Browser.EDGE;
|
|
77
73
|
}
|
|
78
|
-
if (noMarionette && parts[0] === webdriver.Browser.FIREFOX) {
|
|
79
|
-
parts[0] = LEGACY_FIREFOX;
|
|
80
|
-
}
|
|
81
74
|
return parts.join(':');
|
|
82
75
|
});
|
|
83
76
|
|
|
@@ -87,10 +80,6 @@ var browsersToTest = (function() {
|
|
|
87
80
|
parts[0] = webdriver.Browser.IE;
|
|
88
81
|
}
|
|
89
82
|
|
|
90
|
-
if (parts[0] === LEGACY_FIREFOX) {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
83
|
if (NATIVE_BROWSERS.indexOf(parts[0]) == -1 && !permitRemoteBrowsers) {
|
|
95
84
|
throw Error('Browser ' + parts[0] + ' requires a WebDriver server and ' +
|
|
96
85
|
'neither the SELENIUM_REMOTE_URL nor the SELENIUM_SERVER_JAR ' +
|
|
@@ -156,10 +145,6 @@ function TestEnvironment(browserName, server) {
|
|
|
156
145
|
return server || remoteUrl;
|
|
157
146
|
};
|
|
158
147
|
|
|
159
|
-
this.isMarionette = function() {
|
|
160
|
-
return !noMarionette;
|
|
161
|
-
};
|
|
162
|
-
|
|
163
148
|
this.browsers = function(var_args) {
|
|
164
149
|
var browsersToIgnore = Array.prototype.slice.apply(arguments, [0]);
|
|
165
150
|
return browsers(browserName, browsersToIgnore);
|
|
@@ -170,15 +155,7 @@ function TestEnvironment(browserName, server) {
|
|
|
170
155
|
var realBuild = builder.build;
|
|
171
156
|
|
|
172
157
|
builder.build = function() {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
if (parts[0] === LEGACY_FIREFOX) {
|
|
176
|
-
var options = builder.getFirefoxOptions() || new firefox.Options();
|
|
177
|
-
options.useGeckoDriver(false);
|
|
178
|
-
builder.setFirefoxOptions(options);
|
|
179
|
-
|
|
180
|
-
parts[0] = webdriver.Browser.FIREFOX;
|
|
181
|
-
}
|
|
158
|
+
let parts = browserName.split(/:/, 3);
|
|
182
159
|
|
|
183
160
|
builder.forBrowser(parts[0], parts[1], parts[2]);
|
|
184
161
|
if (server) {
|
|
@@ -225,10 +202,10 @@ function suite(fn, opt_options) {
|
|
|
225
202
|
try {
|
|
226
203
|
|
|
227
204
|
before(function() {
|
|
228
|
-
if (isDevMode) {
|
|
205
|
+
if (isDevMode && !noBuild) {
|
|
229
206
|
return build.of(
|
|
230
207
|
'//javascript/atoms/fragments:is-displayed',
|
|
231
|
-
'//javascript/webdriver/atoms:
|
|
208
|
+
'//javascript/webdriver/atoms:get-attribute')
|
|
232
209
|
.onlyOnce().go();
|
|
233
210
|
}
|
|
234
211
|
});
|
|
@@ -243,15 +220,6 @@ function suite(fn, opt_options) {
|
|
|
243
220
|
browsers.forEach(function(browser) {
|
|
244
221
|
describe('[' + browser + ']', function() {
|
|
245
222
|
|
|
246
|
-
if (isDevMode && nativeRun) {
|
|
247
|
-
if (browser === LEGACY_FIREFOX) {
|
|
248
|
-
before(function() {
|
|
249
|
-
return build.of('//javascript/firefox-driver:webdriver')
|
|
250
|
-
.onlyOnce().go();
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
223
|
var serverToUse = null;
|
|
256
224
|
|
|
257
225
|
if (!!serverJar && !remoteUrl) {
|
package/lib/webdriver.js
CHANGED
|
@@ -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
|
|
|
@@ -782,8 +774,7 @@ class WebDriver {
|
|
|
782
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 */
|
|
@@ -1054,13 +1045,15 @@ class WebDriver {
|
|
|
1054
1045
|
let cmd = new command.Command(command.Name.FIND_ELEMENTS).
|
|
1055
1046
|
setParameter('using', locator.using).
|
|
1056
1047
|
setParameter('value', locator.value);
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1048
|
+
return this.schedule(cmd, 'WebDriver.findElements(' + locator + ')')
|
|
1049
|
+
.then(
|
|
1050
|
+
(res) => Array.isArray(res) ? res : [],
|
|
1051
|
+
(e) => {
|
|
1052
|
+
if (e instanceof error.NoSuchElementError) {
|
|
1053
|
+
return [];
|
|
1054
|
+
}
|
|
1055
|
+
throw e;
|
|
1056
|
+
});
|
|
1064
1057
|
}
|
|
1065
1058
|
}
|
|
1066
1059
|
|
|
@@ -1200,14 +1193,14 @@ class Options {
|
|
|
1200
1193
|
* __Sample Usage:__
|
|
1201
1194
|
*
|
|
1202
1195
|
* // Set a basic cookie.
|
|
1203
|
-
* driver.
|
|
1196
|
+
* driver.manage().addCookie({name: 'foo', value: 'bar'});
|
|
1204
1197
|
*
|
|
1205
1198
|
* // Set a cookie that expires in 10 minutes.
|
|
1206
1199
|
* let expiry = new Date(Date.now() + (10 * 60 * 1000));
|
|
1207
|
-
* driver.
|
|
1200
|
+
* driver.manage().addCookie({name: 'foo', value: 'bar', expiry});
|
|
1208
1201
|
*
|
|
1209
1202
|
* // The cookie expiration may also be specified in seconds since epoch.
|
|
1210
|
-
* driver.
|
|
1203
|
+
* driver.manage().addCookie({
|
|
1211
1204
|
* name: 'foo',
|
|
1212
1205
|
* value: 'bar',
|
|
1213
1206
|
* expiry: Math.floor(Date.now() / 1000)
|
|
@@ -1220,36 +1213,29 @@ class Options {
|
|
|
1220
1213
|
* invalid.
|
|
1221
1214
|
* @throws {TypeError} if `spec` is not a cookie object.
|
|
1222
1215
|
*/
|
|
1223
|
-
addCookie(
|
|
1224
|
-
if (!spec || typeof spec !== 'object') {
|
|
1225
|
-
throw TypeError('addCookie called with non-cookie parameter');
|
|
1226
|
-
}
|
|
1227
|
-
|
|
1216
|
+
addCookie({name, value, path, domain, secure, httpOnly, expiry}) {
|
|
1228
1217
|
// We do not allow '=' or ';' in the name.
|
|
1229
|
-
let name = spec.name;
|
|
1230
1218
|
if (/[;=]/.test(name)) {
|
|
1231
1219
|
throw new error.InvalidArgumentError(
|
|
1232
1220
|
'Invalid cookie name "' + name + '"');
|
|
1233
1221
|
}
|
|
1234
1222
|
|
|
1235
1223
|
// We do not allow ';' in value.
|
|
1236
|
-
let value = spec.value;
|
|
1237
1224
|
if (/;/.test(value)) {
|
|
1238
1225
|
throw new error.InvalidArgumentError(
|
|
1239
1226
|
'Invalid cookie value "' + value + '"');
|
|
1240
1227
|
}
|
|
1241
1228
|
|
|
1242
1229
|
let cookieString = name + '=' + value +
|
|
1243
|
-
(
|
|
1244
|
-
(
|
|
1245
|
-
(
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
let date = /** @type {!Date} */(spec.expiry);
|
|
1230
|
+
(domain ? ';domain=' + domain : '') +
|
|
1231
|
+
(path ? ';path=' + path : '') +
|
|
1232
|
+
(secure ? ';secure' : '');
|
|
1233
|
+
|
|
1234
|
+
if (typeof expiry === 'number') {
|
|
1235
|
+
expiry = Math.floor(expiry);
|
|
1236
|
+
cookieString += ';expires=' + new Date(expiry * 1000).toUTCString();
|
|
1237
|
+
} else if (expiry instanceof Date) {
|
|
1238
|
+
let date = /** @type {!Date} */(expiry);
|
|
1253
1239
|
expiry = Math.floor(date.getTime() / 1000);
|
|
1254
1240
|
cookieString += ';expires=' + date.toUTCString();
|
|
1255
1241
|
}
|
|
@@ -1259,9 +1245,10 @@ class Options {
|
|
|
1259
1245
|
setParameter('cookie', {
|
|
1260
1246
|
'name': name,
|
|
1261
1247
|
'value': value,
|
|
1262
|
-
'path':
|
|
1263
|
-
'domain':
|
|
1264
|
-
'secure': !!
|
|
1248
|
+
'path': path,
|
|
1249
|
+
'domain': domain,
|
|
1250
|
+
'secure': !!secure,
|
|
1251
|
+
'httpOnly': !!httpOnly,
|
|
1265
1252
|
'expiry': expiry
|
|
1266
1253
|
}),
|
|
1267
1254
|
'WebDriver.manage().addCookie(' + cookieString + ')');
|
|
@@ -1326,6 +1313,91 @@ class Options {
|
|
|
1326
1313
|
});
|
|
1327
1314
|
}
|
|
1328
1315
|
|
|
1316
|
+
/**
|
|
1317
|
+
* Schedules a command to fetch the timeouts currently configured for the
|
|
1318
|
+
* current session.
|
|
1319
|
+
*
|
|
1320
|
+
* @return {!promise.Thenable<{script: number,
|
|
1321
|
+
* pageLoad: number,
|
|
1322
|
+
* implicit: number}>} A promise that will be
|
|
1323
|
+
* resolved with the timeouts currently configured for the current
|
|
1324
|
+
* session.
|
|
1325
|
+
* @see #setTimeouts()
|
|
1326
|
+
*/
|
|
1327
|
+
getTimeouts() {
|
|
1328
|
+
return this.driver_.schedule(
|
|
1329
|
+
new command.Command(command.Name.GET_TIMEOUT),
|
|
1330
|
+
`WebDriver.manage().getTimeouts()`)
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
/**
|
|
1334
|
+
* Schedules a command to set timeout durations associated with the current
|
|
1335
|
+
* session.
|
|
1336
|
+
*
|
|
1337
|
+
* The following timeouts are supported (all timeouts are specified in
|
|
1338
|
+
* milliseconds):
|
|
1339
|
+
*
|
|
1340
|
+
* - `implicit` specifies the maximum amount of time to wait for an element
|
|
1341
|
+
* locator to succeed when {@linkplain WebDriver#findElement locating}
|
|
1342
|
+
* {@linkplain WebDriver#findElements elements} on the page.
|
|
1343
|
+
* Defaults to 0 milliseconds.
|
|
1344
|
+
*
|
|
1345
|
+
* - `pageLoad` specifies the maximum amount of time to wait for a page to
|
|
1346
|
+
* finishing loading. Defaults to 300000 milliseconds.
|
|
1347
|
+
*
|
|
1348
|
+
* - `script` specifies the maximum amount of time to wait for an
|
|
1349
|
+
* {@linkplain WebDriver#executeScript evaluated script} to run. If set to
|
|
1350
|
+
* `null`, the script timeout will be indefinite.
|
|
1351
|
+
* Defaults to 30000 milliseconds.
|
|
1352
|
+
*
|
|
1353
|
+
* @param {{script: (number|null|undefined),
|
|
1354
|
+
* pageLoad: (number|null|undefined),
|
|
1355
|
+
* implicit: (number|null|undefined)}} conf
|
|
1356
|
+
* The desired timeout configuration.
|
|
1357
|
+
* @return {!promise.Thenable<void>} A promise that will be resolved when the
|
|
1358
|
+
* timeouts have been set.
|
|
1359
|
+
* @throws {!TypeError} if an invalid options object is provided.
|
|
1360
|
+
* @see #getTimeouts()
|
|
1361
|
+
* @see <https://w3c.github.io/webdriver/webdriver-spec.html#dfn-set-timeouts>
|
|
1362
|
+
*/
|
|
1363
|
+
setTimeouts({script, pageLoad, implicit} = {}) {
|
|
1364
|
+
let cmd = new command.Command(command.Name.SET_TIMEOUT);
|
|
1365
|
+
|
|
1366
|
+
let valid = false;
|
|
1367
|
+
function setParam(key, value) {
|
|
1368
|
+
if (value === null || typeof value === 'number') {
|
|
1369
|
+
valid = true;
|
|
1370
|
+
cmd.setParameter(key, value);
|
|
1371
|
+
} else if (typeof value !== 'undefined') {
|
|
1372
|
+
throw TypeError(
|
|
1373
|
+
'invalid timeouts configuration:'
|
|
1374
|
+
+ ` expected "${key}" to be a number, got ${typeof value}`);
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
setParam('implicit', implicit);
|
|
1378
|
+
setParam('pageLoad', pageLoad);
|
|
1379
|
+
setParam('script', script);
|
|
1380
|
+
|
|
1381
|
+
if (valid) {
|
|
1382
|
+
return this.driver_.schedule(cmd, `WebDriver.manage().setTimeouts()`)
|
|
1383
|
+
.catch(() => {
|
|
1384
|
+
// Fallback to the legacy method.
|
|
1385
|
+
let cmds = [];
|
|
1386
|
+
if (typeof script === 'number') {
|
|
1387
|
+
cmds.push(legacyTimeout(this.driver_, 'script', script));
|
|
1388
|
+
}
|
|
1389
|
+
if (typeof implicit === 'number') {
|
|
1390
|
+
cmds.push(legacyTimeout(this.driver_, 'implicit', implicit));
|
|
1391
|
+
}
|
|
1392
|
+
if (typeof pageLoad === 'number') {
|
|
1393
|
+
cmds.push(legacyTimeout(this.driver_, 'page load', pageLoad));
|
|
1394
|
+
}
|
|
1395
|
+
return Promise.all(cmds);
|
|
1396
|
+
});
|
|
1397
|
+
}
|
|
1398
|
+
throw TypeError('no timeouts specified');
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1329
1401
|
/**
|
|
1330
1402
|
* @return {!Logs} The interface for managing driver
|
|
1331
1403
|
* logs.
|
|
@@ -1336,6 +1408,7 @@ class Options {
|
|
|
1336
1408
|
|
|
1337
1409
|
/**
|
|
1338
1410
|
* @return {!Timeouts} The interface for managing driver timeouts.
|
|
1411
|
+
* @deprecated Use {@link #setTimeouts()} instead.
|
|
1339
1412
|
*/
|
|
1340
1413
|
timeouts() {
|
|
1341
1414
|
return new Timeouts(this.driver_);
|
|
@@ -1350,6 +1423,22 @@ class Options {
|
|
|
1350
1423
|
}
|
|
1351
1424
|
|
|
1352
1425
|
|
|
1426
|
+
/**
|
|
1427
|
+
* @param {!WebDriver} driver
|
|
1428
|
+
* @param {string} type
|
|
1429
|
+
* @param {number} ms
|
|
1430
|
+
* @return {!promise.Thenable<void>}
|
|
1431
|
+
*/
|
|
1432
|
+
function legacyTimeout(driver, type, ms) {
|
|
1433
|
+
return driver.schedule(
|
|
1434
|
+
new command.Command(command.Name.SET_TIMEOUT)
|
|
1435
|
+
.setParameter('type', type)
|
|
1436
|
+
.setParameter('ms', ms),
|
|
1437
|
+
`WebDriver.manage().setTimeouts({${type}: ${ms}})`);
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
|
|
1441
|
+
|
|
1353
1442
|
/**
|
|
1354
1443
|
* A record object describing a browser cookie.
|
|
1355
1444
|
*
|
|
@@ -1413,8 +1502,7 @@ Options.Cookie.prototype.httpOnly;
|
|
|
1413
1502
|
* When the cookie expires.
|
|
1414
1503
|
*
|
|
1415
1504
|
* When {@linkplain Options#addCookie() adding a cookie}, this may be specified
|
|
1416
|
-
* in _seconds_ since Unix epoch (January 1, 1970).
|
|
1417
|
-
* 20 years in the future if omitted.
|
|
1505
|
+
* as a {@link Date} object, or in _seconds_ since Unix epoch (January 1, 1970).
|
|
1418
1506
|
*
|
|
1419
1507
|
* The expiry is always returned in seconds since epoch when
|
|
1420
1508
|
* {@linkplain Options#getCookies() retrieving cookies} from the browser.
|
|
@@ -1432,6 +1520,9 @@ Options.Cookie.prototype.expiry;
|
|
|
1432
1520
|
*
|
|
1433
1521
|
* webdriver.manage().timeouts()
|
|
1434
1522
|
*
|
|
1523
|
+
* @deprecated This has been deprecated in favor of
|
|
1524
|
+
* {@link Options#setTimeouts()}, which supports setting multiple timeouts
|
|
1525
|
+
* at once.
|
|
1435
1526
|
* @see WebDriver#manage()
|
|
1436
1527
|
* @see Options#timeouts()
|
|
1437
1528
|
*/
|
|
@@ -1465,9 +1556,11 @@ class Timeouts {
|
|
|
1465
1556
|
* @param {number} ms The amount of time to wait, in milliseconds.
|
|
1466
1557
|
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1467
1558
|
* when the implicit wait timeout has been set.
|
|
1559
|
+
* @deprecated Use {@link Options#setTimeouts()
|
|
1560
|
+
* driver.manage().setTimeouts({implicit: ms})}.
|
|
1468
1561
|
*/
|
|
1469
1562
|
implicitlyWait(ms) {
|
|
1470
|
-
return this.
|
|
1563
|
+
return this.driver_.manage().setTimeouts({implicit: ms});
|
|
1471
1564
|
}
|
|
1472
1565
|
|
|
1473
1566
|
/**
|
|
@@ -1478,9 +1571,11 @@ class Timeouts {
|
|
|
1478
1571
|
* @param {number} ms The amount of time to wait, in milliseconds.
|
|
1479
1572
|
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1480
1573
|
* when the script timeout has been set.
|
|
1574
|
+
* @deprecated Use {@link Options#setTimeouts()
|
|
1575
|
+
* driver.manage().setTimeouts({script: ms})}.
|
|
1481
1576
|
*/
|
|
1482
1577
|
setScriptTimeout(ms) {
|
|
1483
|
-
return this.
|
|
1578
|
+
return this.driver_.manage().setTimeouts({script: ms});
|
|
1484
1579
|
}
|
|
1485
1580
|
|
|
1486
1581
|
/**
|
|
@@ -1491,17 +1586,11 @@ class Timeouts {
|
|
|
1491
1586
|
* @param {number} ms The amount of time to wait, in milliseconds.
|
|
1492
1587
|
* @return {!promise.Thenable<void>} A promise that will be resolved
|
|
1493
1588
|
* when the timeout has been set.
|
|
1589
|
+
* @deprecated Use {@link Options#setTimeouts()
|
|
1590
|
+
* driver.manage().setTimeouts({pageLoad: ms})}.
|
|
1494
1591
|
*/
|
|
1495
1592
|
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})`);
|
|
1593
|
+
return this.driver_.manage().setTimeouts({pageLoad: ms});
|
|
1505
1594
|
}
|
|
1506
1595
|
}
|
|
1507
1596
|
|
|
@@ -1989,7 +2078,8 @@ class WebElement {
|
|
|
1989
2078
|
command.Name.FIND_CHILD_ELEMENTS).
|
|
1990
2079
|
setParameter('using', locator.using).
|
|
1991
2080
|
setParameter('value', locator.value);
|
|
1992
|
-
return this.schedule_(cmd, 'WebElement.findElements(' + locator + ')')
|
|
2081
|
+
return this.schedule_(cmd, 'WebElement.findElements(' + locator + ')')
|
|
2082
|
+
.then(result => Array.isArray(result) ? result : []);
|
|
1993
2083
|
}
|
|
1994
2084
|
}
|
|
1995
2085
|
|
|
@@ -2083,6 +2173,7 @@ class WebElement {
|
|
|
2083
2173
|
if (!this.driver_.fileDetector_) {
|
|
2084
2174
|
return this.schedule_(
|
|
2085
2175
|
new command.Command(command.Name.SEND_KEYS_TO_ELEMENT).
|
|
2176
|
+
setParameter('text', keys.then(keys => keys.join(''))).
|
|
2086
2177
|
setParameter('value', keys),
|
|
2087
2178
|
'WebElement.sendKeys()');
|
|
2088
2179
|
}
|
|
@@ -2098,6 +2189,7 @@ class WebElement {
|
|
|
2098
2189
|
}).then(function(keys) {
|
|
2099
2190
|
return element.schedule_(
|
|
2100
2191
|
new command.Command(command.Name.SEND_KEYS_TO_ELEMENT).
|
|
2192
|
+
setParameter('text', keys).
|
|
2101
2193
|
setParameter('value', keys.split('')),
|
|
2102
2194
|
'WebElement.sendKeys()');
|
|
2103
2195
|
});
|
package/net/portprober.js
CHANGED
package/opera.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "selenium-webdriver",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.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');
|
|
@@ -278,9 +278,10 @@ class DriverService {
|
|
|
278
278
|
if (!this.address_ || !this.command_) {
|
|
279
279
|
return Promise.resolve(); // Not currently running.
|
|
280
280
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
281
|
+
let cmd = this.command_;
|
|
282
|
+
this.address_ = null;
|
|
283
|
+
this.command_ = null;
|
|
284
|
+
return cmd.then(c => c.kill('SIGTERM'));
|
|
284
285
|
}
|
|
285
286
|
|
|
286
287
|
/**
|
|
@@ -492,7 +493,12 @@ class SeleniumServer extends DriverService {
|
|
|
492
493
|
return jvmArgs.concat('-jar', jar, '-port', port).concat(args);
|
|
493
494
|
});
|
|
494
495
|
|
|
495
|
-
|
|
496
|
+
let java = 'java';
|
|
497
|
+
if (process.env['JAVA_HOME']) {
|
|
498
|
+
java = path.join(process.env['JAVA_HOME'], 'bin/java');
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
super(java, {
|
|
496
502
|
loopback: options.loopback,
|
|
497
503
|
port: port,
|
|
498
504
|
args: args,
|
|
@@ -570,15 +576,16 @@ class FileDetector extends input.FileDetector {
|
|
|
570
576
|
return file; // Not a valid file, return original input.
|
|
571
577
|
}
|
|
572
578
|
|
|
573
|
-
|
|
574
|
-
zip.
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
579
|
+
let zip = new Zip;
|
|
580
|
+
return zip.addFile(file)
|
|
581
|
+
.then(() => zip.toBuffer())
|
|
582
|
+
.then(buf => buf.toString('base64'))
|
|
583
|
+
.then(encodedZip => {
|
|
584
|
+
let command = new cmd.Command(cmd.Name.UPLOAD_FILE)
|
|
585
|
+
.setParameter('file', encodedZip);
|
|
586
|
+
return driver.schedule(command,
|
|
587
|
+
'remote.FileDetector.handleFile(' + file + ')');
|
|
588
|
+
});
|
|
582
589
|
}, function(err) {
|
|
583
590
|
if (err.code === 'ENOENT') {
|
|
584
591
|
return file; // Not a file; return original input.
|
package/safari.js
CHANGED
|
@@ -250,8 +250,8 @@ class Driver extends webdriver.WebDriver {
|
|
|
250
250
|
let executor = new http.Executor(
|
|
251
251
|
service.start().then(url => new http.HttpClient(url)));
|
|
252
252
|
|
|
253
|
-
return /** @type {!Driver} */(
|
|
254
|
-
executor, caps, opt_flow,
|
|
253
|
+
return /** @type {!Driver} */(super.createSession(
|
|
254
|
+
executor, caps, opt_flow, () => service.kill()));
|
|
255
255
|
}
|
|
256
256
|
}
|
|
257
257
|
|