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.
Files changed (50) hide show
  1. package/CHANGES.md +56 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +2 -0
  4. package/README.md +2 -0
  5. package/chrome.js +69 -79
  6. package/chromium.js +231 -164
  7. package/{lib/atoms/make-atoms-module.js → devtools/CDPConnection.js} +15 -9
  8. package/edge.js +104 -146
  9. package/example/chrome_android.js +45 -0
  10. package/example/chrome_mobile_emulation.js +46 -0
  11. package/example/firefox_channels.js +84 -0
  12. package/example/google_search.js +50 -0
  13. package/example/google_search_test.js +70 -0
  14. package/example/headless.js +63 -0
  15. package/example/logging.js +64 -0
  16. package/firefox.js +199 -200
  17. package/http/index.js +128 -116
  18. package/http/util.js +56 -64
  19. package/ie.js +180 -104
  20. package/index.js +246 -199
  21. package/io/exec.js +35 -40
  22. package/io/index.js +146 -157
  23. package/io/zip.js +75 -66
  24. package/lib/atoms/find-elements.js +123 -0
  25. package/lib/atoms/get-attribute.js +75 -59
  26. package/lib/atoms/is-displayed.js +72 -72
  27. package/lib/atoms/mutation-listener.js +55 -0
  28. package/lib/by.js +192 -65
  29. package/lib/capabilities.js +76 -86
  30. package/lib/command.js +19 -35
  31. package/lib/error.js +134 -168
  32. package/lib/http.js +308 -232
  33. package/lib/input.js +192 -453
  34. package/lib/logging.js +126 -137
  35. package/lib/promise.js +53 -71
  36. package/lib/proxy.js +31 -41
  37. package/lib/session.js +12 -15
  38. package/lib/symbols.js +3 -4
  39. package/lib/until.js +162 -160
  40. package/lib/webdriver.js +1014 -549
  41. package/net/index.js +30 -36
  42. package/net/portprober.js +30 -143
  43. package/opera.js +406 -0
  44. package/package.json +15 -7
  45. package/proxy.js +2 -2
  46. package/remote/index.js +189 -187
  47. package/safari.js +40 -49
  48. package/testing/index.js +504 -0
  49. package/lib/README +0 -5
  50. package/lib/actions.js +0 -609
package/http/index.js CHANGED
@@ -20,14 +20,13 @@
20
20
  * communicates with a remote end using HTTP + JSON.
21
21
  */
22
22
 
23
- 'use strict';
23
+ 'use strict'
24
24
 
25
- const http = require('http');
26
- const https = require('https');
27
- const url = require('url');
28
-
29
- const httpLib = require('../lib/http');
25
+ const http = require('http')
26
+ const https = require('https')
27
+ const url = require('url')
30
28
 
29
+ const httpLib = require('../lib/http')
31
30
 
32
31
  /**
33
32
  * @typedef {{protocol: (?string|undefined),
@@ -38,8 +37,7 @@ const httpLib = require('../lib/http');
38
37
  * path: (?string|undefined),
39
38
  * pathname: (?string|undefined)}}
40
39
  */
41
- var RequestOptions;
42
-
40
+ var RequestOptions // eslint-disable-line
43
41
 
44
42
  /**
45
43
  * @param {string} aUrl The request URL to parse.
@@ -47,26 +45,25 @@ var RequestOptions;
47
45
  * @throws {Error} if the URL does not include a hostname.
48
46
  */
49
47
  function getRequestOptions(aUrl) {
50
- let options = url.parse(aUrl);
48
+ //eslint-disable-next-line node/no-deprecated-api
49
+ let options = url.parse(aUrl)
51
50
  if (!options.hostname) {
52
- throw new Error('Invalid URL: ' + aUrl);
51
+ throw new Error('Invalid URL: ' + aUrl)
53
52
  }
54
53
  // Delete the search and has portions as they are not used.
55
- options.search = null;
56
- options.hash = null;
57
- options.path = options.pathname;
58
- return options;
54
+ options.search = null
55
+ options.hash = null
56
+ options.path = options.pathname
57
+ return options
59
58
  }
60
59
 
61
-
62
60
  /** @const {string} */
63
- const USER_AGENT = (function() {
64
- const version = require('../package.json').version;
61
+ const USER_AGENT = (function () {
62
+ const version = require('../package.json').version
65
63
  const platform =
66
- ({'darwin': 'mac', 'win32': 'windows'}[process.platform]) || 'linux';
67
- return `selenium/${version} (js ${platform})`;
68
- })();
69
-
64
+ { darwin: 'mac', win32: 'windows' }[process.platform] || 'linux'
65
+ return `selenium/${version} (js ${platform})`
66
+ })()
70
67
 
71
68
  /**
72
69
  * A basic HTTP client used to send messages to a remote end.
@@ -83,47 +80,48 @@ class HttpClient {
83
80
  */
84
81
  constructor(serverUrl, opt_agent, opt_proxy) {
85
82
  /** @private {http.Agent} */
86
- this.agent_ = opt_agent || null;
83
+ this.agent_ = opt_agent || null
87
84
 
88
85
  /**
89
86
  * Base options for each request.
90
87
  * @private {RequestOptions}
91
88
  */
92
- this.options_ = getRequestOptions(serverUrl);
89
+ this.options_ = getRequestOptions(serverUrl)
93
90
 
94
91
  /**
95
92
  * @private {?RequestOptions}
96
93
  */
97
- this.proxyOptions_ = opt_proxy ? getRequestOptions(opt_proxy) : null;
94
+ this.proxyOptions_ = opt_proxy ? getRequestOptions(opt_proxy) : null
98
95
  }
99
96
 
100
97
  /** @override */
101
98
  send(httpRequest) {
102
- let data;
99
+ let data
103
100
 
104
- let headers = {};
101
+ let headers = {}
105
102
 
106
103
  if (httpRequest.headers) {
107
- httpRequest.headers.forEach(function(value, name) {
108
- headers[name] = value;
109
- });
104
+ httpRequest.headers.forEach(function (value, name) {
105
+ headers[name] = value
106
+ })
110
107
  }
111
108
 
112
- headers['User-Agent'] = USER_AGENT;
113
- headers['Content-Length'] = 0;
109
+ headers['User-Agent'] = USER_AGENT
110
+ headers['Content-Length'] = 0
114
111
  if (httpRequest.method == 'POST' || httpRequest.method == 'PUT') {
115
- data = JSON.stringify(httpRequest.data);
116
- headers['Content-Length'] = Buffer.byteLength(data, 'utf8');
117
- headers['Content-Type'] = 'application/json;charset=UTF-8';
112
+ data = JSON.stringify(httpRequest.data)
113
+ headers['Content-Length'] = Buffer.byteLength(data, 'utf8')
114
+ headers['Content-Type'] = 'application/json;charset=UTF-8'
118
115
  }
119
116
 
120
- let path = this.options_.path;
117
+ let path = this.options_.path
121
118
  if (path.endsWith('/') && httpRequest.path.startsWith('/')) {
122
- path += httpRequest.path.substring(1);
119
+ path += httpRequest.path.substring(1)
123
120
  } else {
124
- path += httpRequest.path;
121
+ path += httpRequest.path
125
122
  }
126
- let parsedPath = url.parse(path);
123
+ //eslint-disable-next-line node/no-deprecated-api
124
+ let parsedPath = url.parse(path)
127
125
 
128
126
  let options = {
129
127
  agent: this.agent_ || null,
@@ -140,15 +138,14 @@ class HttpClient {
140
138
  hash: parsedPath.hash,
141
139
 
142
140
  headers,
143
- };
141
+ }
144
142
 
145
143
  return new Promise((fulfill, reject) => {
146
- sendRequest(options, fulfill, reject, data, this.proxyOptions_);
147
- });
144
+ sendRequest(options, fulfill, reject, data, this.proxyOptions_)
145
+ })
148
146
  }
149
147
  }
150
148
 
151
-
152
149
  /**
153
150
  * Sends a single HTTP request.
154
151
  * @param {!Object} options The request options.
@@ -160,118 +157,131 @@ class HttpClient {
160
157
  * @param {number=} opt_retries The current number of retries.
161
158
  */
162
159
  function sendRequest(options, onOk, onError, opt_data, opt_proxy, opt_retries) {
163
- var hostname = options.hostname;
164
- var port = options.port;
160
+ var hostname = options.hostname
161
+ var port = options.port
165
162
 
166
163
  if (opt_proxy) {
167
- let proxy = /** @type {RequestOptions} */(opt_proxy);
164
+ let proxy = /** @type {RequestOptions} */ (opt_proxy)
168
165
 
169
166
  // RFC 2616, section 5.1.2:
170
167
  // The absoluteURI form is REQUIRED when the request is being made to a
171
168
  // proxy.
172
- let absoluteUri = url.format(options);
169
+ let absoluteUri = url.format(options)
173
170
 
174
171
  // RFC 2616, section 14.23:
175
172
  // An HTTP/1.1 proxy MUST ensure that any request message it forwards does
176
173
  // contain an appropriate Host header field that identifies the service
177
174
  // being requested by the proxy.
178
- let targetHost = options.hostname;
175
+ let targetHost = options.hostname
179
176
  if (options.port) {
180
- targetHost += ':' + options.port;
177
+ targetHost += ':' + options.port
181
178
  }
182
179
 
183
180
  // Update the request options with our proxy info.
184
- options.headers['Host'] = targetHost;
185
- options.path = absoluteUri;
186
- options.host = proxy.host;
187
- options.hostname = proxy.hostname;
188
- options.port = proxy.port;
181
+ options.headers['Host'] = targetHost
182
+ options.path = absoluteUri
183
+ options.host = proxy.host
184
+ options.hostname = proxy.hostname
185
+ options.port = proxy.port
189
186
 
190
187
  // Update the protocol to avoid EPROTO errors when the webdriver proxy
191
188
  // uses a different protocol from the remote selenium server.
192
- options.protocol = opt_proxy.protocol;
189
+ options.protocol = opt_proxy.protocol
193
190
 
194
191
  if (proxy.auth) {
195
192
  options.headers['Proxy-Authorization'] =
196
- 'Basic ' + new Buffer(proxy.auth).toString('base64');
193
+ 'Basic ' + Buffer.from(proxy.auth).toString('base64')
197
194
  }
198
195
  }
199
196
 
200
- let requestFn = options.protocol === 'https:' ? https.request : http.request;
197
+ let requestFn = options.protocol === 'https:' ? https.request : http.request
201
198
  var request = requestFn(options, function onResponse(response) {
202
199
  if (response.statusCode == 302 || response.statusCode == 303) {
203
200
  try {
204
- var location = url.parse(response.headers['location']);
201
+ // eslint-disable-next-line node/no-deprecated-api
202
+ var location = url.parse(response.headers['location'])
205
203
  } catch (ex) {
206
- onError(Error(
204
+ onError(
205
+ Error(
207
206
  'Failed to parse "Location" header for server redirect: ' +
208
- ex.message + '\nResponse was: \n' +
209
- new httpLib.Response(response.statusCode, response.headers, '')));
210
- return;
207
+ ex.message +
208
+ '\nResponse was: \n' +
209
+ new httpLib.Response(response.statusCode, response.headers, '')
210
+ )
211
+ )
212
+ return
211
213
  }
212
214
 
213
215
  if (!location.hostname) {
214
- location.hostname = hostname;
215
- location.port = port;
216
+ location.hostname = hostname
217
+ location.port = port
218
+ location.auth = options.auth
216
219
  }
217
220
 
218
- request.abort();
219
- sendRequest({
220
- method: 'GET',
221
- protocol: location.protocol || options.protocol,
222
- hostname: location.hostname,
223
- port: location.port,
224
- path: location.path,
225
- pathname: location.pathname,
226
- search: location.search,
227
- hash: location.hash,
228
- headers: {
229
- 'Accept': 'application/json; charset=utf-8',
230
- 'User-Agent': USER_AGENT,
231
- }
232
- }, onOk, onError, undefined, opt_proxy);
233
- return;
221
+ request.abort()
222
+ sendRequest(
223
+ {
224
+ method: 'GET',
225
+ protocol: location.protocol || options.protocol,
226
+ hostname: location.hostname,
227
+ port: location.port,
228
+ path: location.path,
229
+ auth: location.auth,
230
+ pathname: location.pathname,
231
+ search: location.search,
232
+ hash: location.hash,
233
+ headers: {
234
+ Accept: 'application/json; charset=utf-8',
235
+ 'User-Agent': USER_AGENT,
236
+ },
237
+ },
238
+ onOk,
239
+ onError,
240
+ undefined,
241
+ opt_proxy
242
+ )
243
+ return
234
244
  }
235
245
 
236
- var body = [];
237
- response.on('data', body.push.bind(body));
238
- response.on('end', function() {
246
+ var body = []
247
+ response.on('data', body.push.bind(body))
248
+ response.on('end', function () {
239
249
  var resp = new httpLib.Response(
240
- /** @type {number} */(response.statusCode),
241
- /** @type {!Object<string>} */(response.headers),
242
- Buffer.concat(body).toString('utf8').replace(/\0/g, ''));
243
- onOk(resp);
244
- });
245
- });
246
-
247
- request.on('error', function(e) {
250
+ /** @type {number} */ (response.statusCode),
251
+ /** @type {!Object<string>} */ (response.headers),
252
+ Buffer.concat(body).toString('utf8').replace(/\0/g, '')
253
+ )
254
+ onOk(resp)
255
+ })
256
+ })
257
+
258
+ request.on('error', function (e) {
248
259
  if (typeof opt_retries === 'undefined') {
249
- opt_retries = 0;
260
+ opt_retries = 0
250
261
  }
251
262
 
252
263
  if (shouldRetryRequest(opt_retries, e)) {
253
- opt_retries += 1;
254
- setTimeout(function() {
255
- sendRequest(options, onOk, onError, opt_data, opt_proxy, opt_retries);
256
- }, 15);
264
+ opt_retries += 1
265
+ setTimeout(function () {
266
+ sendRequest(options, onOk, onError, opt_data, opt_proxy, opt_retries)
267
+ }, 15)
257
268
  } else {
258
- var message = e.message;
269
+ var message = e.message
259
270
  if (e.code) {
260
- message = e.code + ' ' + message;
271
+ message = e.code + ' ' + message
261
272
  }
262
- onError(new Error(message));
273
+ onError(new Error(message))
263
274
  }
264
- });
275
+ })
265
276
 
266
277
  if (opt_data) {
267
- request.write(opt_data);
278
+ request.write(opt_data)
268
279
  }
269
280
 
270
- request.end();
281
+ request.end()
271
282
  }
272
283
 
273
-
274
- const MAX_RETRIES = 3;
284
+ const MAX_RETRIES = 3
275
285
 
276
286
  /**
277
287
  * A retry is sometimes needed on Windows where we may quickly run out of
@@ -283,7 +293,7 @@ const MAX_RETRIES = 3;
283
293
  * @return {boolean}
284
294
  */
285
295
  function shouldRetryRequest(retries, err) {
286
- return retries < MAX_RETRIES && isRetryableNetworkError(err);
296
+ return retries < MAX_RETRIES && isRetryableNetworkError(err)
287
297
  }
288
298
 
289
299
  /**
@@ -292,21 +302,23 @@ function shouldRetryRequest(retries, err) {
292
302
  */
293
303
  function isRetryableNetworkError(err) {
294
304
  if (err && err.code) {
295
- return err.code === 'ECONNABORTED' ||
296
- err.code === 'ECONNRESET' ||
297
- err.code === 'ECONNREFUSED' ||
298
- err.code === 'EADDRINUSE' ||
299
- err.code === 'EPIPE';
305
+ return (
306
+ err.code === 'ECONNABORTED' ||
307
+ err.code === 'ECONNRESET' ||
308
+ err.code === 'ECONNREFUSED' ||
309
+ err.code === 'EADDRINUSE' ||
310
+ err.code === 'EPIPE' ||
311
+ err.code === 'ETIMEDOUT'
312
+ )
300
313
  }
301
314
 
302
- return false;
315
+ return false
303
316
  }
304
317
 
305
-
306
318
  // PUBLIC API
307
319
 
308
- exports.Agent = http.Agent;
309
- exports.Executor = httpLib.Executor;
310
- exports.HttpClient = HttpClient;
311
- exports.Request = httpLib.Request;
312
- exports.Response = httpLib.Response;
320
+ exports.Agent = http.Agent
321
+ exports.Executor = httpLib.Executor
322
+ exports.HttpClient = HttpClient
323
+ exports.Request = httpLib.Request
324
+ exports.Response = httpLib.Response
package/http/util.js CHANGED
@@ -19,16 +19,14 @@
19
19
  * @fileoverview Various HTTP utilities.
20
20
  */
21
21
 
22
- 'use strict';
22
+ 'use strict'
23
23
 
24
24
  const Executor = require('./index').Executor,
25
- HttpClient = require('./index').HttpClient,
26
- HttpRequest = require('./index').Request,
27
- Command = require('../lib/command').Command,
28
- CommandName = require('../lib/command').Name,
29
- error = require('../lib/error');
30
-
31
-
25
+ HttpClient = require('./index').HttpClient,
26
+ HttpRequest = require('./index').Request,
27
+ Command = require('../lib/command').Command,
28
+ CommandName = require('../lib/command').Name,
29
+ error = require('../lib/error')
32
30
 
33
31
  /**
34
32
  * Queries a WebDriver server for its current status.
@@ -37,30 +35,25 @@ const Executor = require('./index').Executor,
37
35
  * a hash of the server status.
38
36
  */
39
37
  function getStatus(url) {
40
- var client = new HttpClient(url);
41
- var executor = new Executor(client);
42
- var command = new Command(CommandName.GET_SERVER_STATUS);
43
- return executor.execute(command);
38
+ const client = new HttpClient(url)
39
+ const executor = new Executor(client)
40
+ const command = new Command(CommandName.GET_SERVER_STATUS)
41
+ return executor.execute(command)
44
42
  }
45
43
 
46
-
47
44
  class CancellationError {}
48
45
 
49
-
50
46
  // PUBLIC API
51
47
 
52
-
53
48
  /**
54
49
  * Queries a WebDriver server for its current status.
55
50
  * @param {string} url Base URL of the server to query.
56
51
  * @return {!Promise<!Object>} A promise that resolves with
57
52
  * a hash of the server status.
58
53
  */
59
- exports.getStatus = getStatus;
60
-
61
-
62
- exports.CancellationError = CancellationError;
54
+ exports.getStatus = getStatus
63
55
 
56
+ exports.CancellationError = CancellationError
64
57
 
65
58
  /**
66
59
  * Waits for a WebDriver server to be healthy and accepting requests.
@@ -72,50 +65,49 @@ exports.CancellationError = CancellationError;
72
65
  * @return {!Promise} A promise that will resolve when the server is ready, or
73
66
  * if the wait is cancelled.
74
67
  */
75
- exports.waitForServer = function(url, timeout, opt_cancelToken) {
68
+ exports.waitForServer = function (url, timeout, opt_cancelToken) {
76
69
  return new Promise((onResolve, onReject) => {
77
- let start = Date.now();
70
+ let start = Date.now()
78
71
 
79
- let done = false;
72
+ let done = false
80
73
  let resolve = (status) => {
81
- done = true;
82
- onResolve(status);
83
- };
74
+ done = true
75
+ onResolve(status)
76
+ }
84
77
  let reject = (err) => {
85
- done = true;
86
- onReject(err);
87
- };
78
+ done = true
79
+ onReject(err)
80
+ }
88
81
 
89
82
  if (opt_cancelToken) {
90
- opt_cancelToken.then(_ => reject(new CancellationError));
83
+ opt_cancelToken.then((_) => reject(new CancellationError()))
91
84
  }
92
85
 
93
- checkServerStatus();
86
+ checkServerStatus()
94
87
  function checkServerStatus() {
95
- return getStatus(url).then(status => resolve(status), onError);
88
+ return getStatus(url).then((status) => resolve(status), onError)
96
89
  }
97
90
 
98
91
  function onError(e) {
99
92
  // Some servers don't support the status command. If they are able to
100
93
  // response with an error, then can consider the server ready.
101
94
  if (e instanceof error.UnsupportedOperationError) {
102
- resolve({});
103
- return;
95
+ resolve({})
96
+ return
104
97
  }
105
98
 
106
99
  if (Date.now() - start > timeout) {
107
- reject(Error('Timed out waiting for the WebDriver server at ' + url));
100
+ reject(Error('Timed out waiting for the WebDriver server at ' + url))
108
101
  } else {
109
- setTimeout(function() {
102
+ setTimeout(function () {
110
103
  if (!done) {
111
- checkServerStatus();
104
+ checkServerStatus()
112
105
  }
113
- }, 50);
106
+ }, 50)
114
107
  }
115
108
  }
116
- });
117
- };
118
-
109
+ })
110
+ }
119
111
 
120
112
  /**
121
113
  * Polls a URL with GET requests until it returns a 2xx response or the
@@ -128,53 +120,53 @@ exports.waitForServer = function(url, timeout, opt_cancelToken) {
128
120
  * @return {!Promise} A promise that will resolve when a 2xx is received from
129
121
  * the given URL, or if the wait is cancelled.
130
122
  */
131
- exports.waitForUrl = function(url, timeout, opt_cancelToken) {
123
+ exports.waitForUrl = function (url, timeout, opt_cancelToken) {
132
124
  return new Promise((onResolve, onReject) => {
133
- let client = new HttpClient(url);
134
- let request = new HttpRequest('GET', '');
135
- let start = Date.now();
125
+ let client = new HttpClient(url)
126
+ let request = new HttpRequest('GET', '')
127
+ let start = Date.now()
136
128
 
137
- let done = false;
129
+ let done = false
138
130
  let resolve = () => {
139
- done = true;
140
- onResolve();
141
- };
131
+ done = true
132
+ onResolve()
133
+ }
142
134
  let reject = (err) => {
143
- done = true;
144
- onReject(err);
145
- };
135
+ done = true
136
+ onReject(err)
137
+ }
146
138
 
147
139
  if (opt_cancelToken) {
148
- opt_cancelToken.then(_ => reject(new CancellationError));
140
+ opt_cancelToken.then((_) => reject(new CancellationError()))
149
141
  }
150
142
 
151
- testUrl();
143
+ testUrl()
152
144
 
153
145
  function testUrl() {
154
- client.send(request).then(onResponse, onError);
146
+ client.send(request).then(onResponse, onError)
155
147
  }
156
148
 
157
149
  function onError() {
158
150
  if (Date.now() - start > timeout) {
159
- reject(Error('Timed out waiting for the URL to return 2xx: ' + url));
151
+ reject(Error('Timed out waiting for the URL to return 2xx: ' + url))
160
152
  } else {
161
- setTimeout(function() {
153
+ setTimeout(function () {
162
154
  if (!done) {
163
- testUrl();
155
+ testUrl()
164
156
  }
165
- }, 50);
157
+ }, 50)
166
158
  }
167
159
  }
168
160
 
169
161
  function onResponse(response) {
170
162
  if (done) {
171
- return;
163
+ return
172
164
  }
173
165
  if (response.status > 199 && response.status < 300) {
174
- resolve();
175
- return;
166
+ resolve()
167
+ return
176
168
  }
177
- onError();
169
+ onError()
178
170
  }
179
- });
180
- };
171
+ })
172
+ }