selenium-webdriver 3.3.0 → 4.0.0-alpha.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 +273 -0
- package/NOTICE +1 -1
- package/README.md +28 -36
- package/chrome.js +221 -146
- package/edge.js +43 -118
- package/example/chrome_android.js +8 -9
- package/example/chrome_mobile_emulation.js +9 -10
- package/example/firefox_channels.js +23 -19
- package/example/google_search.js +3 -3
- package/example/google_search_test.js +39 -27
- package/example/headless.js +55 -0
- package/example/logging.js +40 -7
- package/firefox.js +769 -0
- package/http/index.js +41 -4
- package/http/util.js +11 -6
- package/ie.js +57 -98
- package/index.js +182 -115
- package/io/index.js +59 -0
- package/io/zip.js +214 -0
- package/jasmine.json +11 -0
- package/lib/actions.js +68 -63
- package/lib/atoms/get-attribute.js +9 -0
- package/lib/atoms/is-displayed.js +73 -78
- package/lib/by.js +9 -1
- package/lib/capabilities.js +303 -201
- package/lib/command.js +28 -50
- package/lib/error.js +113 -42
- package/lib/http.js +167 -135
- package/lib/input.js +1044 -8
- package/lib/promise.js +222 -3331
- package/lib/proxy.js +134 -39
- package/lib/test/bootstrap_jasmine.js +28 -0
- package/lib/test/data/actions/click.html +24 -0
- package/lib/test/data/actions/drag.html +77 -0
- package/lib/test/data/actions/record_click.html +21 -0
- package/lib/test/data/chrome/download.html +2 -0
- 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/inputs.html +42 -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/selectPage.html +12 -0
- package/lib/test/data/simpleTest.html +5 -0
- package/lib/test/data/single_text_input.html +12 -0
- package/lib/test/data/upload_invisible.html +45 -0
- package/lib/test/fileserver.js +23 -19
- package/lib/test/index.js +30 -244
- package/lib/test/resources.js +0 -1
- package/lib/webdriver.js +770 -939
- package/net/index.js +21 -25
- package/net/portprober.js +51 -68
- package/package.json +6 -4
- package/remote/index.js +18 -30
- package/safari.js +42 -129
- package/test/actions_test.js +173 -18
- package/test/builder_test.js +106 -0
- package/test/chrome/devtools_test.js +93 -0
- package/test/chrome/options_test.js +48 -154
- package/test/chrome/service_test.js +7 -7
- package/test/cookie_test.js +77 -63
- package/test/element_finding_test.js +206 -201
- package/test/execute_script_test.js +115 -114
- package/test/fingerprint_test.js +16 -15
- package/test/firefox_test.js +251 -0
- package/test/http/http_test.js +18 -1
- package/test/http/util_test.js +2 -2
- package/test/{io_test.js → io/io_test.js} +40 -1
- package/test/io/zip_test.js +127 -0
- package/test/lib/by_test.js +21 -0
- package/test/lib/error_test.js +55 -8
- package/test/lib/http_test.js +18 -130
- package/test/lib/input_test.js +1379 -0
- package/test/lib/promise_test.js +473 -908
- package/test/lib/webdriver_test.js +357 -825
- package/test/logging_test.js +37 -43
- package/test/page_loading_test.js +70 -86
- package/test/proxy_test.js +64 -72
- package/test/rect_test.js +14 -25
- package/test/remote_test.js +13 -32
- package/test/safari_test.js +7 -71
- package/test/stale_element_test.js +20 -23
- package/test/tag_name_test.js +10 -9
- package/test/upload_test.js +27 -35
- package/test/window_test.js +72 -85
- package/testing/index.js +386 -315
- package/.npmignore +0 -2
- package/example/async_await_test.js +0 -68
- package/example/google_search_generator.js +0 -50
- package/example/parallel_flows.js +0 -54
- package/firefox/binary.js +0 -344
- package/firefox/extension.js +0 -187
- package/firefox/index.js +0 -722
- package/firefox/profile.js +0 -430
- package/lib/atoms/getAttribute.js +0 -12
- package/lib/events.js +0 -210
- package/lib/firefox/webdriver.json +0 -70
- package/lib/firefox/webdriver.xpi +0 -0
- package/lib/test/data/firefox/jetpack-sample.xpi +0 -0
- package/lib/test/data/firefox/sample.xpi +0 -0
- package/lib/test/promise.js +0 -79
- package/opera.js +0 -405
- package/phantomjs.js +0 -282
- package/test/firefox/extension_test.js +0 -96
- package/test/firefox/firefox_test.js +0 -226
- package/test/firefox/profile_test.js +0 -185
- package/test/lib/events_test.js +0 -177
- package/test/lib/promise_aplus_test.js +0 -78
- package/test/lib/promise_error_test.js +0 -884
- package/test/lib/promise_flow_test.js +0 -2288
- package/test/lib/promise_generator_test.js +0 -310
- package/test/phantomjs/execute_phantomjs_test.js +0 -59
- package/test/session_test.js +0 -54
- package/test/testing/assert_test.js +0 -373
- package/test/testing/index_test.js +0 -224
- package/testing/assert.js +0 -378
package/net/index.js
CHANGED
|
@@ -17,11 +17,11 @@
|
|
|
17
17
|
|
|
18
18
|
'use strict';
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
const os = require('os');
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
function getLoInterface() {
|
|
24
|
-
|
|
24
|
+
let name;
|
|
25
25
|
if (process.platform === 'darwin') {
|
|
26
26
|
name = 'lo0';
|
|
27
27
|
} else if (process.platform === 'linux') {
|
|
@@ -34,32 +34,28 @@ function getLoInterface() {
|
|
|
34
34
|
/**
|
|
35
35
|
* Queries the system network interfaces for an IP address.
|
|
36
36
|
* @param {boolean} loopback Whether to find a loopback address.
|
|
37
|
-
* @param {string
|
|
38
|
-
* @return {string} The located IP address or undefined.
|
|
37
|
+
* @param {string} family The IP family (IPv4 or IPv6). Defaults to IPv4.
|
|
38
|
+
* @return {(string|undefined)} The located IP address or undefined.
|
|
39
39
|
*/
|
|
40
|
-
function getAddress(loopback,
|
|
41
|
-
|
|
42
|
-
var addresses = [];
|
|
43
|
-
|
|
44
|
-
var interfaces;
|
|
40
|
+
function getAddress(loopback, family) {
|
|
41
|
+
let interfaces;
|
|
45
42
|
if (loopback) {
|
|
46
|
-
|
|
43
|
+
let lo = getLoInterface();
|
|
47
44
|
interfaces = lo ? [lo] : null;
|
|
48
45
|
}
|
|
49
46
|
interfaces = interfaces || os.networkInterfaces();
|
|
50
|
-
for (
|
|
47
|
+
for (let key in interfaces) {
|
|
51
48
|
if (!interfaces.hasOwnProperty(key)) {
|
|
52
49
|
continue;
|
|
53
50
|
}
|
|
54
51
|
|
|
55
|
-
interfaces[key]
|
|
56
|
-
if (ipAddress.family === family &&
|
|
57
|
-
|
|
58
|
-
addresses.push(ipAddress.address);
|
|
52
|
+
for (let ipAddress of interfaces[key]) {
|
|
53
|
+
if (ipAddress.family === family && ipAddress.internal === loopback) {
|
|
54
|
+
return ipAddress.address;
|
|
59
55
|
}
|
|
60
|
-
}
|
|
56
|
+
}
|
|
61
57
|
}
|
|
62
|
-
return
|
|
58
|
+
return undefined;
|
|
63
59
|
}
|
|
64
60
|
|
|
65
61
|
|
|
@@ -68,21 +64,21 @@ function getAddress(loopback, opt_family) {
|
|
|
68
64
|
|
|
69
65
|
/**
|
|
70
66
|
* Retrieves the external IP address for this host.
|
|
71
|
-
* @param {string=}
|
|
72
|
-
* @return {string} The IP address or undefined if not available.
|
|
67
|
+
* @param {string=} family The IP family to retrieve. Defaults to "IPv4".
|
|
68
|
+
* @return {(string|undefined)} The IP address or undefined if not available.
|
|
73
69
|
*/
|
|
74
|
-
exports.getAddress = function(
|
|
75
|
-
return getAddress(false,
|
|
70
|
+
exports.getAddress = function(family = 'IPv4') {
|
|
71
|
+
return getAddress(false, family);
|
|
76
72
|
};
|
|
77
73
|
|
|
78
74
|
|
|
79
75
|
/**
|
|
80
76
|
* Retrieves a loopback address for this machine.
|
|
81
|
-
* @param {string=}
|
|
82
|
-
* @return {string} The IP address or undefined if not available.
|
|
77
|
+
* @param {string=} family The IP family to retrieve. Defaults to "IPv4".
|
|
78
|
+
* @return {(string|undefined)} The IP address or undefined if not available.
|
|
83
79
|
*/
|
|
84
|
-
exports.getLoopbackAddress = function(
|
|
85
|
-
return getAddress(true,
|
|
80
|
+
exports.getLoopbackAddress = function(family = 'IPv4') {
|
|
81
|
+
return getAddress(true, family);
|
|
86
82
|
};
|
|
87
83
|
|
|
88
84
|
|
package/net/portprober.js
CHANGED
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
|
|
18
18
|
'use strict';
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
const fs = require('fs');
|
|
21
|
+
const net = require('net');
|
|
22
|
+
const {exec} = require('child_process');
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -34,9 +34,9 @@ const DEFAULT_IANA_RANGE = {min: 49152, max: 65535};
|
|
|
34
34
|
/**
|
|
35
35
|
* The epheremal port range for the current system. Lazily computed on first
|
|
36
36
|
* access.
|
|
37
|
-
* @type {Promise
|
|
37
|
+
* @type {Promise<{min: number, max: number}>}
|
|
38
38
|
*/
|
|
39
|
-
|
|
39
|
+
let systemRange = null;
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
/**
|
|
@@ -49,11 +49,10 @@ function findSystemPortRange() {
|
|
|
49
49
|
if (systemRange) {
|
|
50
50
|
return systemRange;
|
|
51
51
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
});
|
|
52
|
+
let range =
|
|
53
|
+
process.platform === 'win32'
|
|
54
|
+
? findWindowsPortRange() : findUnixPortRange();
|
|
55
|
+
return systemRange = range.catch(() => DEFAULT_IANA_RANGE);
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
|
|
@@ -81,7 +80,7 @@ function execute(cmd) {
|
|
|
81
80
|
* @return {!Promise<{min: number, max: number}>} A promise that will resolve
|
|
82
81
|
* with the ephemeral port range on the current system.
|
|
83
82
|
*/
|
|
84
|
-
function findUnixPortRange() {
|
|
83
|
+
async function findUnixPortRange() {
|
|
85
84
|
var cmd;
|
|
86
85
|
if (process.platform === 'sunos') {
|
|
87
86
|
cmd =
|
|
@@ -94,12 +93,17 @@ function findUnixPortRange() {
|
|
|
94
93
|
' | sed -e "s/.*:\\s*//"';
|
|
95
94
|
}
|
|
96
95
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
96
|
+
let stdout = await execute(cmd);
|
|
97
|
+
if (!stdout || !stdout.length) {
|
|
98
|
+
return DEFAULT_IANA_RANGE;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
let range = stdout.trim().split(/\s+/).map(Number);
|
|
102
|
+
if (range.some(isNaN)) {
|
|
103
|
+
return DEFAULT_IANA_RANGE;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
return {min: range[0], max: range[1]};
|
|
103
107
|
}
|
|
104
108
|
|
|
105
109
|
|
|
@@ -108,35 +112,29 @@ function findUnixPortRange() {
|
|
|
108
112
|
* @return {!Promise<{min: number, max: number}>} A promise that will resolve
|
|
109
113
|
* with the ephemeral port range on the current system.
|
|
110
114
|
*/
|
|
111
|
-
function findWindowsPortRange() {
|
|
115
|
+
async function findWindowsPortRange() {
|
|
112
116
|
// First, check if we're running on XP. If this initial command fails,
|
|
113
117
|
// we just fallback on the default IANA range.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
min: range[0],
|
|
135
|
-
max: range[0] + range[1]
|
|
136
|
-
};
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
});
|
|
118
|
+
let stdout = await execute('cmd.exe /c ver');
|
|
119
|
+
if (/Windows XP/.test(stdout)) {
|
|
120
|
+
// TODO: Try to read these values from the registry.
|
|
121
|
+
return {min: 1025, max: 5000};
|
|
122
|
+
} else {
|
|
123
|
+
stdout = await execute('netsh int ipv4 show dynamicport tcp');
|
|
124
|
+
/* > netsh int ipv4 show dynamicport tcp
|
|
125
|
+
Protocol tcp Dynamic Port Range
|
|
126
|
+
---------------------------------
|
|
127
|
+
Start Port : 49152
|
|
128
|
+
Number of Ports : 16384
|
|
129
|
+
*/
|
|
130
|
+
let range = stdout.split(/\n/)
|
|
131
|
+
.filter((line) => /.*:\s*\d+/.test(line))
|
|
132
|
+
.map((line) => Number(line.split(/:\s*/)[1]));
|
|
133
|
+
return {
|
|
134
|
+
min: range[0],
|
|
135
|
+
max: range[0] + range[1]
|
|
136
|
+
};
|
|
137
|
+
}
|
|
140
138
|
}
|
|
141
139
|
|
|
142
140
|
|
|
@@ -171,30 +169,15 @@ function isFree(port, opt_host) {
|
|
|
171
169
|
* @return {!Promise<number>} A promise that will resolve to a free port. If a
|
|
172
170
|
* port cannot be found, the promise will be rejected.
|
|
173
171
|
*/
|
|
174
|
-
function findFreePort(opt_host) {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
reject(Error('Unable to find a free port'));
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
var port = Math.floor(
|
|
187
|
-
Math.random() * (range.max - range.min) + range.min);
|
|
188
|
-
isFree(port, opt_host).then(function(isFree) {
|
|
189
|
-
if (isFree) {
|
|
190
|
-
resolve(port);
|
|
191
|
-
} else {
|
|
192
|
-
findPort();
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
});
|
|
172
|
+
async function findFreePort(opt_host) {
|
|
173
|
+
let range = await findSystemPortRange();
|
|
174
|
+
for (let i = 0; i < 100; i++) {
|
|
175
|
+
let port = Math.floor(Math.random() * (range.max - range.min) + range.min);
|
|
176
|
+
if (await isFree(port, opt_host)) {
|
|
177
|
+
return port;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
throw Error('Unable to find a free port');
|
|
198
181
|
}
|
|
199
182
|
|
|
200
183
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "selenium-webdriver",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0-alpha.1",
|
|
4
4
|
"description": "The official WebDriver JavaScript bindings from the Selenium project",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"keywords": [
|
|
@@ -20,16 +20,17 @@
|
|
|
20
20
|
"url": "https://github.com/SeleniumHQ/selenium.git"
|
|
21
21
|
},
|
|
22
22
|
"engines": {
|
|
23
|
-
"node": ">=
|
|
23
|
+
"node": ">= 8.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"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"express": "^4.14.0",
|
|
33
|
+
"jasmine": "^2.8.0",
|
|
33
34
|
"mocha": "^3.1.2",
|
|
34
35
|
"multer": "^1.2.0",
|
|
35
36
|
"promises-aplus-tests": "^2.1.2",
|
|
@@ -37,6 +38,7 @@
|
|
|
37
38
|
"sinon": "^1.17.6"
|
|
38
39
|
},
|
|
39
40
|
"scripts": {
|
|
40
|
-
"test": "mocha -t 600000 --recursive test"
|
|
41
|
+
"test": "mocha -t 600000 --recursive test",
|
|
42
|
+
"test-jasmine": "jasmine JASMINE_CONFIG_PATH=jasmine.json"
|
|
41
43
|
}
|
|
42
44
|
}
|
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,9 +25,9 @@ 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
|
-
const promise = require('../lib/promise');
|
|
32
31
|
const webdriver = require('../lib/webdriver');
|
|
33
32
|
const net = require('../net');
|
|
34
33
|
const portprober = require('../net/portprober');
|
|
@@ -253,7 +252,7 @@ class DriverService {
|
|
|
253
252
|
|
|
254
253
|
httpUtil.waitForServer(serverUrl, timeout, cancelToken)
|
|
255
254
|
.then(_ => fulfill(serverUrl), err => {
|
|
256
|
-
if (err instanceof
|
|
255
|
+
if (err instanceof httpUtil.CancellationError) {
|
|
257
256
|
fulfill(serverUrl);
|
|
258
257
|
} else {
|
|
259
258
|
reject(err);
|
|
@@ -278,19 +277,10 @@ class DriverService {
|
|
|
278
277
|
if (!this.address_ || !this.command_) {
|
|
279
278
|
return Promise.resolve(); // Not currently running.
|
|
280
279
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* Schedules a task in the current control flow to stop the server if it is
|
|
288
|
-
* currently running.
|
|
289
|
-
* @return {!promise.Thenable} A promise that will be resolved when
|
|
290
|
-
* the server has been stopped.
|
|
291
|
-
*/
|
|
292
|
-
stop() {
|
|
293
|
-
return promise.controlFlow().execute(this.kill.bind(this));
|
|
280
|
+
let cmd = this.command_;
|
|
281
|
+
this.address_ = null;
|
|
282
|
+
this.command_ = null;
|
|
283
|
+
return cmd.then(c => c.kill('SIGTERM'));
|
|
294
284
|
}
|
|
295
285
|
}
|
|
296
286
|
|
|
@@ -528,11 +518,9 @@ class SeleniumServer extends DriverService {
|
|
|
528
518
|
*
|
|
529
519
|
* @typedef {{
|
|
530
520
|
* loopback: (boolean|undefined),
|
|
531
|
-
* port: (number|!
|
|
532
|
-
* args: !(Array<string>|
|
|
533
|
-
* jvmArgs: (!Array<string
|
|
534
|
-
* !promise.Promise<!Array<string>>|
|
|
535
|
-
* undefined),
|
|
521
|
+
* port: (number|!IThenable<number>),
|
|
522
|
+
* args: !(Array<string>|IThenable<!Array<string>>),
|
|
523
|
+
* jvmArgs: (!Array<string>|!IThenable<!Array<string>>|undefined),
|
|
536
524
|
* env: (!Object<string, string>|undefined),
|
|
537
525
|
* stdio: (string|!Array<string|number|!stream.Stream|null|undefined>|
|
|
538
526
|
* undefined)
|
|
@@ -575,15 +563,15 @@ class FileDetector extends input.FileDetector {
|
|
|
575
563
|
return file; // Not a valid file, return original input.
|
|
576
564
|
}
|
|
577
565
|
|
|
578
|
-
|
|
579
|
-
zip.
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
566
|
+
let zip = new Zip;
|
|
567
|
+
return zip.addFile(file)
|
|
568
|
+
.then(() => zip.toBuffer())
|
|
569
|
+
.then(buf => buf.toString('base64'))
|
|
570
|
+
.then(encodedZip => {
|
|
571
|
+
let command = new cmd.Command(cmd.Name.UPLOAD_FILE)
|
|
572
|
+
.setParameter('file', encodedZip);
|
|
573
|
+
return driver.execute(command);
|
|
574
|
+
});
|
|
587
575
|
}, function(err) {
|
|
588
576
|
if (err.code === 'ENOENT') {
|
|
589
577
|
return file; // Not a file; return original input.
|
package/safari.js
CHANGED
|
@@ -21,17 +21,28 @@
|
|
|
21
21
|
|
|
22
22
|
'use strict';
|
|
23
23
|
|
|
24
|
-
const http = require('./http');
|
|
25
|
-
const io = require('./io');
|
|
26
|
-
const {Capabilities, Capability} = require('./lib/capabilities');
|
|
27
24
|
const command = require('./lib/command');
|
|
28
25
|
const error = require('./lib/error');
|
|
29
|
-
const
|
|
26
|
+
const http = require('./http');
|
|
27
|
+
const io = require('./io');
|
|
28
|
+
const portprober = require('./net/portprober');
|
|
30
29
|
const promise = require('./lib/promise');
|
|
30
|
+
const remote = require('./remote');
|
|
31
31
|
const Symbols = require('./lib/symbols');
|
|
32
32
|
const webdriver = require('./lib/webdriver');
|
|
33
|
-
const
|
|
34
|
-
|
|
33
|
+
const {Browser, Capabilities, Capability} = require('./lib/capabilities');
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* _Synchronously_ attempts to locate the IE driver executable on the current
|
|
38
|
+
* system.
|
|
39
|
+
*
|
|
40
|
+
* @return {?string} the located executable, or `null`.
|
|
41
|
+
*/
|
|
42
|
+
function locateSynchronously() {
|
|
43
|
+
return process.platform === 'darwin'
|
|
44
|
+
? io.findInPath('safaridriver', true) : null;
|
|
45
|
+
}
|
|
35
46
|
|
|
36
47
|
|
|
37
48
|
/**
|
|
@@ -39,7 +50,7 @@ const remote = require('./remote');
|
|
|
39
50
|
* @throws {Error}
|
|
40
51
|
*/
|
|
41
52
|
function findSafariDriver() {
|
|
42
|
-
let exe =
|
|
53
|
+
let exe = locateSynchronously();
|
|
43
54
|
if (!exe) {
|
|
44
55
|
throw Error(
|
|
45
56
|
`The safaridriver executable could not be found on the current PATH.
|
|
@@ -73,80 +84,19 @@ const TECHNOLOGY_PREVIEW_OPTIONS_KEY = 'technologyPreview';
|
|
|
73
84
|
/**
|
|
74
85
|
* Configuration options specific to the {@link Driver SafariDriver}.
|
|
75
86
|
*/
|
|
76
|
-
class Options {
|
|
77
|
-
constructor() {
|
|
78
|
-
/** @private {Object<string, *>} */
|
|
79
|
-
this.options_ = null;
|
|
80
|
-
|
|
81
|
-
/** @private {./lib/logging.Preferences} */
|
|
82
|
-
this.logPrefs_ = null;
|
|
83
|
-
|
|
84
|
-
/** @private {?./lib/capabilities.ProxyConfig} */
|
|
85
|
-
this.proxy_ = null;
|
|
86
|
-
}
|
|
87
|
-
|
|
87
|
+
class Options extends Capabilities {
|
|
88
88
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* @param {!Capabilities} capabilities The capabilities object.
|
|
92
|
-
* @return {!Options} The SafariDriver options.
|
|
93
|
-
*/
|
|
94
|
-
static fromCapabilities(capabilities) {
|
|
95
|
-
var options = new Options();
|
|
96
|
-
var o = capabilities.get(OPTIONS_CAPABILITY_KEY);
|
|
97
|
-
|
|
98
|
-
if (o instanceof Options) {
|
|
99
|
-
options = o;
|
|
100
|
-
} else if (o) {
|
|
101
|
-
options.setCleanSession(o.cleanSession);
|
|
102
|
-
options.setTechnologyPreview(o[TECHNOLOGY_PREVIEW_OPTIONS_KEY]);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (capabilities.has(Capability.PROXY)) {
|
|
106
|
-
options.setProxy(capabilities.get(Capability.PROXY));
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (capabilities.has(Capability.LOGGING_PREFS)) {
|
|
110
|
-
options.setLoggingPrefs(capabilities.get(Capability.LOGGING_PREFS));
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return options;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Sets whether to force Safari to start with a clean session. Enabling this
|
|
118
|
-
* option will cause all global browser data to be deleted.
|
|
119
|
-
* @param {boolean} clean Whether to make sure the session has no cookies,
|
|
120
|
-
* cache entries, local storage, or databases.
|
|
121
|
-
* @return {!Options} A self reference.
|
|
89
|
+
* @param {(Capabilities|Map<string, ?>|Object)=} other Another set of
|
|
90
|
+
* capabilities to initialize this instance from.
|
|
122
91
|
*/
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
this.options_ = {};
|
|
126
|
-
}
|
|
127
|
-
this.options_['cleanSession'] = clean;
|
|
128
|
-
return this;
|
|
129
|
-
}
|
|
92
|
+
constructor(other = undefined) {
|
|
93
|
+
super(other);
|
|
130
94
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
* @param {!./lib/logging.Preferences} prefs The logging preferences.
|
|
134
|
-
* @return {!Options} A self reference.
|
|
135
|
-
*/
|
|
136
|
-
setLoggingPrefs(prefs) {
|
|
137
|
-
this.logPrefs_ = prefs;
|
|
138
|
-
return this;
|
|
139
|
-
}
|
|
95
|
+
/** @private {!Object} */
|
|
96
|
+
this.options_ = this.get(OPTIONS_CAPABILITY_KEY) || {};
|
|
140
97
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
*
|
|
144
|
-
* @param {./lib/capabilities.ProxyConfig} proxy The proxy configuration to use.
|
|
145
|
-
* @return {!Options} A self reference.
|
|
146
|
-
*/
|
|
147
|
-
setProxy(proxy) {
|
|
148
|
-
this.proxy_ = proxy;
|
|
149
|
-
return this;
|
|
98
|
+
this.set(OPTIONS_CAPABILITY_KEY, this.options_);
|
|
99
|
+
this.setBrowserName(Browser.SAFARI);
|
|
150
100
|
}
|
|
151
101
|
|
|
152
102
|
/**
|
|
@@ -157,52 +107,19 @@ class Options {
|
|
|
157
107
|
* @return {!Options} A self reference.
|
|
158
108
|
*/
|
|
159
109
|
setTechnologyPreview(useTechnologyPreview) {
|
|
160
|
-
if (!this.options_) {
|
|
161
|
-
this.options_ = {};
|
|
162
|
-
}
|
|
163
|
-
|
|
164
110
|
this.options_[TECHNOLOGY_PREVIEW_OPTIONS_KEY] = !!useTechnologyPreview;
|
|
165
111
|
return this;
|
|
166
112
|
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Converts this options instance to a {@link Capabilities} object.
|
|
170
|
-
* @param {Capabilities=} opt_capabilities The capabilities to
|
|
171
|
-
* merge these options into, if any.
|
|
172
|
-
* @return {!Capabilities} The capabilities.
|
|
173
|
-
*/
|
|
174
|
-
toCapabilities(opt_capabilities) {
|
|
175
|
-
var caps = opt_capabilities || Capabilities.safari();
|
|
176
|
-
if (this.logPrefs_) {
|
|
177
|
-
caps.set(Capability.LOGGING_PREFS, this.logPrefs_);
|
|
178
|
-
}
|
|
179
|
-
if (this.proxy_) {
|
|
180
|
-
caps.set(Capability.PROXY, this.proxy_);
|
|
181
|
-
}
|
|
182
|
-
if (this.options_) {
|
|
183
|
-
caps.set(OPTIONS_CAPABILITY_KEY, this);
|
|
184
|
-
}
|
|
185
|
-
return caps;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Converts this instance to its JSON wire protocol representation. Note this
|
|
190
|
-
* function is an implementation detail not intended for general use.
|
|
191
|
-
* @return {!Object<string, *>} The JSON wire protocol representation of this
|
|
192
|
-
* instance.
|
|
193
|
-
*/
|
|
194
|
-
[Symbols.serialize]() {
|
|
195
|
-
return this.options_ || {};
|
|
196
|
-
}
|
|
197
113
|
}
|
|
198
114
|
|
|
199
115
|
/**
|
|
200
|
-
* @param {(
|
|
116
|
+
* @param {(Capabilities|Object<string, *>)=} o The options object
|
|
201
117
|
* @return {boolean}
|
|
202
118
|
*/
|
|
203
119
|
function useTechnologyPreview(o) {
|
|
204
|
-
if (o instanceof
|
|
205
|
-
|
|
120
|
+
if (o instanceof Capabilities) {
|
|
121
|
+
let options = o.get(OPTIONS_CAPABILITY_KEY);
|
|
122
|
+
return !!(options && options[TECHNOLOGY_PREVIEW_OPTIONS_KEY]);
|
|
206
123
|
}
|
|
207
124
|
|
|
208
125
|
if (o && typeof o === 'object') {
|
|
@@ -212,7 +129,10 @@ function useTechnologyPreview(o) {
|
|
|
212
129
|
return false;
|
|
213
130
|
}
|
|
214
131
|
|
|
215
|
-
|
|
132
|
+
|
|
133
|
+
const SAFARIDRIVER_TECHNOLOGY_PREVIEW_EXE =
|
|
134
|
+
'/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver';
|
|
135
|
+
|
|
216
136
|
|
|
217
137
|
/**
|
|
218
138
|
* A WebDriver client for Safari. This class should never be instantiated
|
|
@@ -227,21 +147,13 @@ class Driver extends webdriver.WebDriver {
|
|
|
227
147
|
/**
|
|
228
148
|
* Creates a new Safari session.
|
|
229
149
|
*
|
|
230
|
-
* @param {(Options|Capabilities)=}
|
|
231
|
-
* options for the new session.
|
|
232
|
-
* @param {promise.ControlFlow=} opt_flow The control flow to create
|
|
233
|
-
* the driver under.
|
|
150
|
+
* @param {(Options|Capabilities)=} options The configuration options.
|
|
234
151
|
* @return {!Driver} A new driver instance.
|
|
235
152
|
*/
|
|
236
|
-
static createSession(
|
|
237
|
-
let caps
|
|
238
|
-
|
|
239
|
-
if (opt_config instanceof Options) {
|
|
240
|
-
caps = opt_config.toCapabilities();
|
|
241
|
-
} else {
|
|
242
|
-
caps = opt_config || Capabilities.safari();
|
|
243
|
-
}
|
|
153
|
+
static createSession(options) {
|
|
154
|
+
let caps = options || new Options();
|
|
244
155
|
|
|
156
|
+
let exe;
|
|
245
157
|
if (useTechnologyPreview(caps.get(OPTIONS_CAPABILITY_KEY))) {
|
|
246
158
|
exe = SAFARIDRIVER_TECHNOLOGY_PREVIEW_EXE;
|
|
247
159
|
}
|
|
@@ -250,8 +162,8 @@ class Driver extends webdriver.WebDriver {
|
|
|
250
162
|
let executor = new http.Executor(
|
|
251
163
|
service.start().then(url => new http.HttpClient(url)));
|
|
252
164
|
|
|
253
|
-
return /** @type {!Driver} */(
|
|
254
|
-
executor, caps,
|
|
165
|
+
return /** @type {!Driver} */(super.createSession(
|
|
166
|
+
executor, caps, () => service.kill()));
|
|
255
167
|
}
|
|
256
168
|
}
|
|
257
169
|
|
|
@@ -262,3 +174,4 @@ class Driver extends webdriver.WebDriver {
|
|
|
262
174
|
exports.Driver = Driver;
|
|
263
175
|
exports.Options = Options;
|
|
264
176
|
exports.ServiceBuilder = ServiceBuilder;
|
|
177
|
+
exports.locateSynchronously = locateSynchronously;
|