selenium-webdriver 4.0.0-alpha.7 → 4.0.0-beta.3
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 +56 -0
- package/LICENSE +202 -0
- package/NOTICE +2 -0
- package/README.md +2 -0
- package/chrome.js +69 -79
- package/chromium.js +231 -164
- package/{lib/atoms/make-atoms-module.js → devtools/CDPConnection.js} +15 -9
- package/edge.js +104 -146
- package/example/chrome_android.js +45 -0
- package/example/chrome_mobile_emulation.js +46 -0
- 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 +199 -200
- package/http/index.js +128 -116
- package/http/util.js +56 -64
- package/ie.js +180 -104
- package/index.js +246 -199
- package/io/exec.js +35 -40
- package/io/index.js +146 -157
- package/io/zip.js +75 -66
- package/lib/atoms/find-elements.js +123 -0
- package/lib/atoms/get-attribute.js +75 -59
- package/lib/atoms/is-displayed.js +72 -72
- package/lib/atoms/mutation-listener.js +55 -0
- package/lib/by.js +192 -65
- package/lib/capabilities.js +76 -86
- package/lib/command.js +19 -35
- package/lib/error.js +134 -168
- package/lib/http.js +308 -232
- package/lib/input.js +192 -453
- package/lib/logging.js +126 -137
- package/lib/promise.js +53 -71
- package/lib/proxy.js +31 -41
- package/lib/session.js +12 -15
- package/lib/symbols.js +3 -4
- package/lib/until.js +162 -160
- package/lib/webdriver.js +1014 -549
- package/net/index.js +30 -36
- package/net/portprober.js +30 -143
- package/opera.js +406 -0
- package/package.json +15 -7
- package/proxy.js +2 -2
- package/remote/index.js +189 -187
- package/safari.js +40 -49
- package/testing/index.js +504 -0
- package/lib/README +0 -5
- package/lib/actions.js +0 -609
package/remote/index.js
CHANGED
|
@@ -15,35 +15,30 @@
|
|
|
15
15
|
// specific language governing permissions and limitations
|
|
16
16
|
// under the License.
|
|
17
17
|
|
|
18
|
-
'use strict'
|
|
18
|
+
'use strict'
|
|
19
19
|
|
|
20
|
-
const fs = require('fs')
|
|
21
|
-
const path = require('path')
|
|
22
|
-
const url = require('url')
|
|
23
|
-
const util = require('util');
|
|
24
|
-
|
|
25
|
-
const httpUtil = require('../http/util');
|
|
26
|
-
const io = require('../io');
|
|
27
|
-
const exec = require('../io/exec');
|
|
28
|
-
const {Zip} = require('../io/zip');
|
|
29
|
-
const cmd = require('../lib/command');
|
|
30
|
-
const input = require('../lib/input');
|
|
31
|
-
const webdriver = require('../lib/webdriver');
|
|
32
|
-
const net = require('../net');
|
|
33
|
-
const portprober = require('../net/portprober');
|
|
20
|
+
const fs = require('fs')
|
|
21
|
+
const path = require('path')
|
|
22
|
+
const url = require('url')
|
|
34
23
|
|
|
24
|
+
const httpUtil = require('../http/util')
|
|
25
|
+
const io = require('../io')
|
|
26
|
+
const exec = require('../io/exec')
|
|
27
|
+
const { Zip } = require('../io/zip')
|
|
28
|
+
const cmd = require('../lib/command')
|
|
29
|
+
const input = require('../lib/input')
|
|
30
|
+
const net = require('../net')
|
|
31
|
+
const portprober = require('../net/portprober')
|
|
35
32
|
|
|
36
33
|
/**
|
|
37
34
|
* @typedef {(string|!Array<string|number|!stream.Stream|null|undefined>)}
|
|
38
35
|
*/
|
|
39
|
-
var StdIoOptions
|
|
40
|
-
|
|
36
|
+
var StdIoOptions // eslint-disable-line
|
|
41
37
|
|
|
42
38
|
/**
|
|
43
39
|
* @typedef {(string|!IThenable<string>)}
|
|
44
40
|
*/
|
|
45
|
-
var CommandLineFlag
|
|
46
|
-
|
|
41
|
+
var CommandLineFlag // eslint-disable-line
|
|
47
42
|
|
|
48
43
|
/**
|
|
49
44
|
* A record object that defines the configuration options for a DriverService
|
|
@@ -58,7 +53,7 @@ function ServiceOptions() {}
|
|
|
58
53
|
*
|
|
59
54
|
* @type {(boolean|undefined)}
|
|
60
55
|
*/
|
|
61
|
-
ServiceOptions.prototype.loopback
|
|
56
|
+
ServiceOptions.prototype.loopback
|
|
62
57
|
|
|
63
58
|
/**
|
|
64
59
|
* The host name to access the server on. If this option is specified, the
|
|
@@ -66,7 +61,7 @@ ServiceOptions.prototype.loopback;
|
|
|
66
61
|
*
|
|
67
62
|
* @type {(string|undefined)}
|
|
68
63
|
*/
|
|
69
|
-
ServiceOptions.prototype.hostname
|
|
64
|
+
ServiceOptions.prototype.hostname
|
|
70
65
|
|
|
71
66
|
/**
|
|
72
67
|
* The port to start the server on (must be > 0). If the port is provided as a
|
|
@@ -74,7 +69,7 @@ ServiceOptions.prototype.hostname;
|
|
|
74
69
|
*
|
|
75
70
|
* @type {(number|!IThenable<number>)}
|
|
76
71
|
*/
|
|
77
|
-
ServiceOptions.prototype.port
|
|
72
|
+
ServiceOptions.prototype.port
|
|
78
73
|
|
|
79
74
|
/**
|
|
80
75
|
* The arguments to pass to the service. If a promise is provided, the service
|
|
@@ -82,7 +77,7 @@ ServiceOptions.prototype.port;
|
|
|
82
77
|
*
|
|
83
78
|
* @type {!(Array<CommandLineFlag>|IThenable<!Array<CommandLineFlag>>)}
|
|
84
79
|
*/
|
|
85
|
-
ServiceOptions.prototype.args
|
|
80
|
+
ServiceOptions.prototype.args
|
|
86
81
|
|
|
87
82
|
/**
|
|
88
83
|
* The base path on the server for the WebDriver wire protocol (e.g. '/wd/hub').
|
|
@@ -90,7 +85,7 @@ ServiceOptions.prototype.args;
|
|
|
90
85
|
*
|
|
91
86
|
* @type {(string|undefined|null)}
|
|
92
87
|
*/
|
|
93
|
-
ServiceOptions.prototype.path
|
|
88
|
+
ServiceOptions.prototype.path
|
|
94
89
|
|
|
95
90
|
/**
|
|
96
91
|
* The environment variables that should be visible to the server process.
|
|
@@ -98,7 +93,7 @@ ServiceOptions.prototype.path;
|
|
|
98
93
|
*
|
|
99
94
|
* @type {(Object<string, string>|undefined)}
|
|
100
95
|
*/
|
|
101
|
-
ServiceOptions.prototype.env
|
|
96
|
+
ServiceOptions.prototype.env
|
|
102
97
|
|
|
103
98
|
/**
|
|
104
99
|
* IO configuration for the spawned server process. For more information, refer
|
|
@@ -107,8 +102,7 @@ ServiceOptions.prototype.env;
|
|
|
107
102
|
* @type {(StdIoOptions|undefined)}
|
|
108
103
|
* @see https://nodejs.org/dist/latest-v4.x/docs/api/child_process.html#child_process_options_stdio
|
|
109
104
|
*/
|
|
110
|
-
ServiceOptions.prototype.stdio
|
|
111
|
-
|
|
105
|
+
ServiceOptions.prototype.stdio
|
|
112
106
|
|
|
113
107
|
/**
|
|
114
108
|
* Manages the life and death of a native executable WebDriver server.
|
|
@@ -125,40 +119,40 @@ class DriverService {
|
|
|
125
119
|
*/
|
|
126
120
|
constructor(executable, options) {
|
|
127
121
|
/** @private {string} */
|
|
128
|
-
this.executable_ = executable
|
|
122
|
+
this.executable_ = executable
|
|
129
123
|
|
|
130
124
|
/** @private {boolean} */
|
|
131
|
-
this.loopbackOnly_ = !!options.loopback
|
|
125
|
+
this.loopbackOnly_ = !!options.loopback
|
|
132
126
|
|
|
133
127
|
/** @private {(string|undefined)} */
|
|
134
|
-
this.hostname_ = options.hostname
|
|
128
|
+
this.hostname_ = options.hostname
|
|
135
129
|
|
|
136
130
|
/** @private {(number|!IThenable<number>)} */
|
|
137
|
-
this.port_ = options.port
|
|
131
|
+
this.port_ = options.port
|
|
138
132
|
|
|
139
133
|
/**
|
|
140
134
|
* @private {!(Array<CommandLineFlag>|
|
|
141
135
|
* IThenable<!Array<CommandLineFlag>>)}
|
|
142
136
|
*/
|
|
143
|
-
this.args_ = options.args
|
|
137
|
+
this.args_ = options.args
|
|
144
138
|
|
|
145
139
|
/** @private {string} */
|
|
146
|
-
this.path_ = options.path || '/'
|
|
140
|
+
this.path_ = options.path || '/'
|
|
147
141
|
|
|
148
142
|
/** @private {!Object<string, string>} */
|
|
149
|
-
this.env_ = options.env || process.env
|
|
143
|
+
this.env_ = options.env || process.env
|
|
150
144
|
|
|
151
145
|
/**
|
|
152
146
|
* @private {(string|!Array<string|number|!stream.Stream|null|undefined>)}
|
|
153
147
|
*/
|
|
154
|
-
this.stdio_ = options.stdio || 'ignore'
|
|
148
|
+
this.stdio_ = options.stdio || 'ignore'
|
|
155
149
|
|
|
156
150
|
/**
|
|
157
151
|
* A promise for the managed subprocess, or null if the server has not been
|
|
158
152
|
* started yet. This promise will never be rejected.
|
|
159
153
|
* @private {Promise<!exec.Command>}
|
|
160
154
|
*/
|
|
161
|
-
this.command_ = null
|
|
155
|
+
this.command_ = null
|
|
162
156
|
|
|
163
157
|
/**
|
|
164
158
|
* Promise that resolves to the server's address or null if the server has
|
|
@@ -166,7 +160,7 @@ class DriverService {
|
|
|
166
160
|
* before it starts accepting WebDriver requests.
|
|
167
161
|
* @private {Promise<string>}
|
|
168
162
|
*/
|
|
169
|
-
this.address_ = null
|
|
163
|
+
this.address_ = null
|
|
170
164
|
}
|
|
171
165
|
|
|
172
166
|
/**
|
|
@@ -175,9 +169,9 @@ class DriverService {
|
|
|
175
169
|
*/
|
|
176
170
|
address() {
|
|
177
171
|
if (this.address_) {
|
|
178
|
-
return this.address_
|
|
172
|
+
return this.address_
|
|
179
173
|
}
|
|
180
|
-
throw Error('Server has not been started.')
|
|
174
|
+
throw Error('Server has not been started.')
|
|
181
175
|
}
|
|
182
176
|
|
|
183
177
|
/**
|
|
@@ -186,7 +180,7 @@ class DriverService {
|
|
|
186
180
|
* @return {boolean} Whether the underlying service process is running.
|
|
187
181
|
*/
|
|
188
182
|
isRunning() {
|
|
189
|
-
return !!this.address_
|
|
183
|
+
return !!this.address_
|
|
190
184
|
}
|
|
191
185
|
|
|
192
186
|
/**
|
|
@@ -199,71 +193,78 @@ class DriverService {
|
|
|
199
193
|
*/
|
|
200
194
|
start(opt_timeoutMs) {
|
|
201
195
|
if (this.address_) {
|
|
202
|
-
return this.address_
|
|
196
|
+
return this.address_
|
|
203
197
|
}
|
|
204
198
|
|
|
205
|
-
var timeout = opt_timeoutMs || DriverService.DEFAULT_START_TIMEOUT_MS
|
|
206
|
-
var self = this
|
|
199
|
+
var timeout = opt_timeoutMs || DriverService.DEFAULT_START_TIMEOUT_MS
|
|
200
|
+
var self = this
|
|
207
201
|
|
|
208
|
-
let resolveCommand
|
|
209
|
-
this.command_ = new Promise(resolve => resolveCommand = resolve)
|
|
202
|
+
let resolveCommand
|
|
203
|
+
this.command_ = new Promise((resolve) => (resolveCommand = resolve))
|
|
210
204
|
|
|
211
205
|
this.address_ = new Promise((resolveAddress, rejectAddress) => {
|
|
212
|
-
resolveAddress(
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
return resolveCommandLineFlags(this.args_).then(args => {
|
|
218
|
-
var command = exec(self.executable_, {
|
|
219
|
-
args: args,
|
|
220
|
-
env: self.env_,
|
|
221
|
-
stdio: self.stdio_
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
resolveCommand(command);
|
|
225
|
-
|
|
226
|
-
var earlyTermination = command.result().then(function(result) {
|
|
227
|
-
var error = result.code == null ?
|
|
228
|
-
Error('Server was killed with ' + result.signal) :
|
|
229
|
-
Error('Server terminated early with status ' + result.code);
|
|
230
|
-
rejectAddress(error);
|
|
231
|
-
self.address_ = null;
|
|
232
|
-
self.command_ = null;
|
|
233
|
-
throw error;
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
var hostname = self.hostname_;
|
|
237
|
-
if (!hostname) {
|
|
238
|
-
hostname = !self.loopbackOnly_ && net.getAddress()
|
|
239
|
-
|| net.getLoopbackAddress();
|
|
206
|
+
resolveAddress(
|
|
207
|
+
Promise.resolve(this.port_).then((port) => {
|
|
208
|
+
if (port <= 0) {
|
|
209
|
+
throw Error('Port must be > 0: ' + port)
|
|
240
210
|
}
|
|
241
211
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
212
|
+
return resolveCommandLineFlags(this.args_).then((args) => {
|
|
213
|
+
const command = exec(self.executable_, {
|
|
214
|
+
args: args,
|
|
215
|
+
env: self.env_,
|
|
216
|
+
stdio: self.stdio_,
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
resolveCommand(command)
|
|
220
|
+
|
|
221
|
+
const earlyTermination = command.result().then(function (result) {
|
|
222
|
+
const error =
|
|
223
|
+
result.code == null
|
|
224
|
+
? Error('Server was killed with ' + result.signal)
|
|
225
|
+
: Error('Server terminated early with status ' + result.code)
|
|
226
|
+
rejectAddress(error)
|
|
227
|
+
self.address_ = null
|
|
228
|
+
self.command_ = null
|
|
229
|
+
throw error
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
let hostname = self.hostname_
|
|
233
|
+
if (!hostname) {
|
|
234
|
+
hostname =
|
|
235
|
+
(!self.loopbackOnly_ && net.getAddress()) ||
|
|
236
|
+
net.getLoopbackAddress()
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
var serverUrl = url.format({
|
|
240
|
+
protocol: 'http',
|
|
241
|
+
hostname: hostname,
|
|
242
|
+
port: port + '',
|
|
243
|
+
pathname: self.path_,
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
return new Promise((fulfill, reject) => {
|
|
247
|
+
let cancelToken = earlyTermination.catch((e) =>
|
|
248
|
+
reject(Error(e.message))
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
httpUtil.waitForServer(serverUrl, timeout, cancelToken).then(
|
|
252
|
+
(_) => fulfill(serverUrl),
|
|
253
|
+
(err) => {
|
|
255
254
|
if (err instanceof httpUtil.CancellationError) {
|
|
256
|
-
fulfill(serverUrl)
|
|
255
|
+
fulfill(serverUrl)
|
|
257
256
|
} else {
|
|
258
|
-
reject(err)
|
|
257
|
+
reject(err)
|
|
259
258
|
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
259
|
+
}
|
|
260
|
+
)
|
|
261
|
+
})
|
|
262
|
+
})
|
|
263
|
+
})
|
|
264
|
+
)
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
return this.address_
|
|
267
268
|
}
|
|
268
269
|
|
|
269
270
|
/**
|
|
@@ -275,34 +276,32 @@ class DriverService {
|
|
|
275
276
|
*/
|
|
276
277
|
kill() {
|
|
277
278
|
if (!this.address_ || !this.command_) {
|
|
278
|
-
return Promise.resolve()
|
|
279
|
+
return Promise.resolve() // Not currently running.
|
|
279
280
|
}
|
|
280
|
-
let cmd = this.command_
|
|
281
|
-
this.address_ = null
|
|
282
|
-
this.command_ = null
|
|
283
|
-
return cmd.then(c => c.kill('SIGTERM'))
|
|
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
|
|
|
287
|
-
|
|
288
288
|
/**
|
|
289
289
|
* @param {!(Array<CommandLineFlag>|IThenable<!Array<CommandLineFlag>>)} args
|
|
290
290
|
* @return {!Promise<!Array<string>>}
|
|
291
291
|
*/
|
|
292
292
|
function resolveCommandLineFlags(args) {
|
|
293
293
|
// Resolve the outer array, then the individual flags.
|
|
294
|
-
return Promise.resolve(args)
|
|
295
|
-
|
|
294
|
+
return Promise.resolve(args).then(
|
|
295
|
+
/** !Array<CommandLineFlag> */ (args) => Promise.all(args)
|
|
296
|
+
)
|
|
296
297
|
}
|
|
297
298
|
|
|
298
|
-
|
|
299
299
|
/**
|
|
300
300
|
* The default amount of time, in milliseconds, to wait for the server to
|
|
301
301
|
* start.
|
|
302
302
|
* @const {number}
|
|
303
303
|
*/
|
|
304
|
-
DriverService.DEFAULT_START_TIMEOUT_MS = 30 * 1000
|
|
305
|
-
|
|
304
|
+
DriverService.DEFAULT_START_TIMEOUT_MS = 30 * 1000
|
|
306
305
|
|
|
307
306
|
/**
|
|
308
307
|
* Creates {@link DriverService} objects that manage a WebDriver server in a
|
|
@@ -316,19 +315,19 @@ DriverService.Builder = class {
|
|
|
316
315
|
*/
|
|
317
316
|
constructor(exe) {
|
|
318
317
|
if (!fs.existsSync(exe)) {
|
|
319
|
-
throw Error(`The specified executable path does not exist: ${exe}`)
|
|
318
|
+
throw Error(`The specified executable path does not exist: ${exe}`)
|
|
320
319
|
}
|
|
321
320
|
|
|
322
321
|
/** @private @const {string} */
|
|
323
|
-
this.exe_ = exe
|
|
322
|
+
this.exe_ = exe
|
|
324
323
|
|
|
325
324
|
/** @private {!ServiceOptions} */
|
|
326
325
|
this.options_ = {
|
|
327
326
|
args: [],
|
|
328
327
|
port: 0,
|
|
329
328
|
env: null,
|
|
330
|
-
stdio: 'ignore'
|
|
331
|
-
}
|
|
329
|
+
stdio: 'ignore',
|
|
330
|
+
}
|
|
332
331
|
}
|
|
333
332
|
|
|
334
333
|
/**
|
|
@@ -339,10 +338,9 @@ DriverService.Builder = class {
|
|
|
339
338
|
* @this {THIS}
|
|
340
339
|
* @template THIS
|
|
341
340
|
*/
|
|
342
|
-
addArguments(
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
return this;
|
|
341
|
+
addArguments(...arguments_) {
|
|
342
|
+
this.options_.args = this.options_.args.concat(arguments_)
|
|
343
|
+
return this
|
|
346
344
|
}
|
|
347
345
|
|
|
348
346
|
/**
|
|
@@ -353,8 +351,8 @@ DriverService.Builder = class {
|
|
|
353
351
|
* @return {!DriverService.Builder} A self reference.
|
|
354
352
|
*/
|
|
355
353
|
setHostname(hostname) {
|
|
356
|
-
this.options_.hostname = hostname
|
|
357
|
-
return this
|
|
354
|
+
this.options_.hostname = hostname
|
|
355
|
+
return this
|
|
358
356
|
}
|
|
359
357
|
|
|
360
358
|
/**
|
|
@@ -365,8 +363,8 @@ DriverService.Builder = class {
|
|
|
365
363
|
* @return {!DriverService.Builder} A self reference.
|
|
366
364
|
*/
|
|
367
365
|
setLoopback(loopback) {
|
|
368
|
-
this.options_.loopback = loopback
|
|
369
|
-
return this
|
|
366
|
+
this.options_.loopback = loopback
|
|
367
|
+
return this
|
|
370
368
|
}
|
|
371
369
|
|
|
372
370
|
/**
|
|
@@ -378,8 +376,8 @@ DriverService.Builder = class {
|
|
|
378
376
|
* @return {!DriverService.Builder} A self reference.
|
|
379
377
|
*/
|
|
380
378
|
setPath(basePath) {
|
|
381
|
-
this.options_.path = basePath
|
|
382
|
-
return this
|
|
379
|
+
this.options_.path = basePath
|
|
380
|
+
return this
|
|
383
381
|
}
|
|
384
382
|
|
|
385
383
|
/**
|
|
@@ -391,10 +389,10 @@ DriverService.Builder = class {
|
|
|
391
389
|
*/
|
|
392
390
|
setPort(port) {
|
|
393
391
|
if (port < 0) {
|
|
394
|
-
throw Error(`port must be >= 0: ${port}`)
|
|
392
|
+
throw Error(`port must be >= 0: ${port}`)
|
|
395
393
|
}
|
|
396
|
-
this.options_.port = port
|
|
397
|
-
return this
|
|
394
|
+
this.options_.port = port
|
|
395
|
+
return this
|
|
398
396
|
}
|
|
399
397
|
|
|
400
398
|
/**
|
|
@@ -409,12 +407,12 @@ DriverService.Builder = class {
|
|
|
409
407
|
*/
|
|
410
408
|
setEnvironment(env) {
|
|
411
409
|
if (env instanceof Map) {
|
|
412
|
-
let tmp = {}
|
|
413
|
-
env.forEach((value, key) => tmp[key] = value)
|
|
414
|
-
env = tmp
|
|
410
|
+
let tmp = {}
|
|
411
|
+
env.forEach((value, key) => (tmp[key] = value))
|
|
412
|
+
env = tmp
|
|
415
413
|
}
|
|
416
|
-
this.options_.env = env
|
|
417
|
-
return this
|
|
414
|
+
this.options_.env = env
|
|
415
|
+
return this
|
|
418
416
|
}
|
|
419
417
|
|
|
420
418
|
/**
|
|
@@ -426,8 +424,8 @@ DriverService.Builder = class {
|
|
|
426
424
|
* @see https://nodejs.org/dist/latest-v4.x/docs/api/child_process.html#child_process_options_stdio
|
|
427
425
|
*/
|
|
428
426
|
setStdio(config) {
|
|
429
|
-
this.options_.stdio = config
|
|
430
|
-
return this
|
|
427
|
+
this.options_.stdio = config
|
|
428
|
+
return this
|
|
431
429
|
}
|
|
432
430
|
|
|
433
431
|
/**
|
|
@@ -436,18 +434,17 @@ DriverService.Builder = class {
|
|
|
436
434
|
* @return {!DriverService} A new driver service.
|
|
437
435
|
*/
|
|
438
436
|
build() {
|
|
439
|
-
let port = this.options_.port || portprober.findFreePort()
|
|
440
|
-
let args = Promise.resolve(port).then(port => {
|
|
441
|
-
return this.options_.args.concat('--port=' + port)
|
|
442
|
-
})
|
|
437
|
+
let port = this.options_.port || portprober.findFreePort()
|
|
438
|
+
let args = Promise.resolve(port).then((port) => {
|
|
439
|
+
return this.options_.args.concat('--port=' + port)
|
|
440
|
+
})
|
|
443
441
|
|
|
444
442
|
let options =
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
return new DriverService(this.exe_, options)
|
|
443
|
+
/** @type {!ServiceOptions} */
|
|
444
|
+
(Object.assign({}, this.options_, { args, port }))
|
|
445
|
+
return new DriverService(this.exe_, options)
|
|
448
446
|
}
|
|
449
|
-
}
|
|
450
|
-
|
|
447
|
+
}
|
|
451
448
|
|
|
452
449
|
/**
|
|
453
450
|
* Manages the life and death of the
|
|
@@ -464,27 +461,30 @@ class SeleniumServer extends DriverService {
|
|
|
464
461
|
*/
|
|
465
462
|
constructor(jar, opt_options) {
|
|
466
463
|
if (!jar) {
|
|
467
|
-
throw Error('Path to the Selenium jar not specified')
|
|
464
|
+
throw Error('Path to the Selenium jar not specified')
|
|
468
465
|
}
|
|
469
466
|
|
|
470
|
-
var options = opt_options || {}
|
|
467
|
+
var options = opt_options || {}
|
|
471
468
|
|
|
472
469
|
if (options.port < 0) {
|
|
473
|
-
throw Error('Port must be >= 0: ' + options.port)
|
|
470
|
+
throw Error('Port must be >= 0: ' + options.port)
|
|
474
471
|
}
|
|
475
472
|
|
|
476
|
-
let port = options.port || portprober.findFreePort()
|
|
477
|
-
let args = Promise.all([
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
473
|
+
let port = options.port || portprober.findFreePort()
|
|
474
|
+
let args = Promise.all([
|
|
475
|
+
port,
|
|
476
|
+
options.jvmArgs || [],
|
|
477
|
+
options.args || [],
|
|
478
|
+
]).then((resolved) => {
|
|
479
|
+
let port = resolved[0]
|
|
480
|
+
let jvmArgs = resolved[1]
|
|
481
|
+
let args = resolved[2]
|
|
482
|
+
return jvmArgs.concat('-jar', jar, '-port', port).concat(args)
|
|
483
|
+
})
|
|
484
|
+
|
|
485
|
+
let java = 'java'
|
|
486
486
|
if (process.env['JAVA_HOME']) {
|
|
487
|
-
java = path.join(process.env['JAVA_HOME'], 'bin/java')
|
|
487
|
+
java = path.join(process.env['JAVA_HOME'], 'bin/java')
|
|
488
488
|
}
|
|
489
489
|
|
|
490
490
|
super(java, {
|
|
@@ -493,12 +493,11 @@ class SeleniumServer extends DriverService {
|
|
|
493
493
|
args: args,
|
|
494
494
|
path: '/wd/hub',
|
|
495
495
|
env: options.env,
|
|
496
|
-
stdio: options.stdio
|
|
497
|
-
})
|
|
496
|
+
stdio: options.stdio,
|
|
497
|
+
})
|
|
498
498
|
}
|
|
499
499
|
}
|
|
500
500
|
|
|
501
|
-
|
|
502
501
|
/**
|
|
503
502
|
* A record object describing configuration options for a {@link SeleniumServer}
|
|
504
503
|
* instance.
|
|
@@ -513,7 +512,7 @@ SeleniumServer.Options = class {
|
|
|
513
512
|
*
|
|
514
513
|
* @type {(boolean|undefined)}
|
|
515
514
|
*/
|
|
516
|
-
this.loopback
|
|
515
|
+
this.loopback
|
|
517
516
|
|
|
518
517
|
/**
|
|
519
518
|
* The port to start the server on (must be > 0). If the port is provided as
|
|
@@ -522,7 +521,7 @@ SeleniumServer.Options = class {
|
|
|
522
521
|
*
|
|
523
522
|
* @type {(number|!IThenable<number>)}
|
|
524
523
|
*/
|
|
525
|
-
this.port
|
|
524
|
+
this.port
|
|
526
525
|
|
|
527
526
|
/**
|
|
528
527
|
* The arguments to pass to the service. If a promise is provided,
|
|
@@ -530,7 +529,7 @@ SeleniumServer.Options = class {
|
|
|
530
529
|
*
|
|
531
530
|
* @type {!(Array<string>|IThenable<!Array<string>>)}
|
|
532
531
|
*/
|
|
533
|
-
this.args
|
|
532
|
+
this.args
|
|
534
533
|
|
|
535
534
|
/**
|
|
536
535
|
* The arguments to pass to the JVM. If a promise is provided,
|
|
@@ -538,7 +537,7 @@ SeleniumServer.Options = class {
|
|
|
538
537
|
*
|
|
539
538
|
* @type {(!Array<string>|!IThenable<!Array<string>>|undefined)}
|
|
540
539
|
*/
|
|
541
|
-
this.jvmArgs
|
|
540
|
+
this.jvmArgs
|
|
542
541
|
|
|
543
542
|
/**
|
|
544
543
|
* The environment variables that should be visible to the server
|
|
@@ -546,7 +545,7 @@ SeleniumServer.Options = class {
|
|
|
546
545
|
*
|
|
547
546
|
* @type {(!Object<string, string>|undefined)}
|
|
548
547
|
*/
|
|
549
|
-
this.env
|
|
548
|
+
this.env
|
|
550
549
|
|
|
551
550
|
/**
|
|
552
551
|
* IO configuration for the spawned server process. If unspecified, IO will
|
|
@@ -556,11 +555,9 @@ SeleniumServer.Options = class {
|
|
|
556
555
|
* undefined)}
|
|
557
556
|
* @see <https://nodejs.org/dist/latest-v8.x/docs/api/child_process.html#child_process_options_stdio>
|
|
558
557
|
*/
|
|
559
|
-
this.stdio
|
|
558
|
+
this.stdio
|
|
560
559
|
}
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
|
|
560
|
+
}
|
|
564
561
|
|
|
565
562
|
/**
|
|
566
563
|
* A {@link webdriver.FileDetector} that may be used when running
|
|
@@ -590,33 +587,38 @@ class FileDetector extends input.FileDetector {
|
|
|
590
587
|
* @override
|
|
591
588
|
*/
|
|
592
589
|
handleFile(driver, file) {
|
|
593
|
-
return io.stat(file).then(
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
590
|
+
return io.stat(file).then(
|
|
591
|
+
function (stats) {
|
|
592
|
+
if (stats.isDirectory()) {
|
|
593
|
+
return file // Not a valid file, return original input.
|
|
594
|
+
}
|
|
597
595
|
|
|
598
|
-
|
|
599
|
-
|
|
596
|
+
let zip = new Zip()
|
|
597
|
+
return zip
|
|
598
|
+
.addFile(file)
|
|
600
599
|
.then(() => zip.toBuffer())
|
|
601
|
-
.then(buf => buf.toString('base64'))
|
|
602
|
-
.then(encodedZip => {
|
|
603
|
-
let command = new cmd.Command(cmd.Name.UPLOAD_FILE)
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
600
|
+
.then((buf) => buf.toString('base64'))
|
|
601
|
+
.then((encodedZip) => {
|
|
602
|
+
let command = new cmd.Command(cmd.Name.UPLOAD_FILE).setParameter(
|
|
603
|
+
'file',
|
|
604
|
+
encodedZip
|
|
605
|
+
)
|
|
606
|
+
return driver.execute(command)
|
|
607
|
+
})
|
|
608
|
+
},
|
|
609
|
+
function (err) {
|
|
610
|
+
if (err.code === 'ENOENT') {
|
|
611
|
+
return file // Not a file; return original input.
|
|
612
|
+
}
|
|
613
|
+
throw err
|
|
610
614
|
}
|
|
611
|
-
|
|
612
|
-
});
|
|
615
|
+
)
|
|
613
616
|
}
|
|
614
617
|
}
|
|
615
618
|
|
|
616
|
-
|
|
617
619
|
// PUBLIC API
|
|
618
620
|
|
|
619
|
-
exports.DriverService = DriverService
|
|
620
|
-
exports.FileDetector = FileDetector
|
|
621
|
-
exports.SeleniumServer = SeleniumServer
|
|
622
|
-
exports.ServiceOptions = ServiceOptions
|
|
621
|
+
exports.DriverService = DriverService
|
|
622
|
+
exports.FileDetector = FileDetector
|
|
623
|
+
exports.SeleniumServer = SeleniumServer
|
|
624
|
+
exports.ServiceOptions = ServiceOptions // Exported for API docs.
|