selenium-webdriver 4.0.0-alpha.4 → 4.0.0-alpha.8

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 (52) hide show
  1. package/.eslintrc.js +27 -0
  2. package/.prettierrc +4 -0
  3. package/CHANGES.md +22 -1
  4. package/README.md +4 -4
  5. package/chrome.js +72 -590
  6. package/chromium.js +1024 -0
  7. package/devtools/CDPConnection.js +37 -0
  8. package/devtools/generator/protocol-dts-generator.js +429 -0
  9. package/edge.js +124 -86
  10. package/firefox.js +201 -202
  11. package/http/index.js +131 -115
  12. package/http/util.js +56 -64
  13. package/ie.js +180 -104
  14. package/index.js +246 -199
  15. package/io/exec.js +34 -39
  16. package/io/index.js +141 -151
  17. package/io/zip.js +75 -65
  18. package/lib/README +5 -0
  19. package/lib/actions.js +138 -121
  20. package/lib/atoms/find-elements.js +123 -0
  21. package/lib/atoms/get-attribute.js +79 -60
  22. package/lib/atoms/is-displayed.js +72 -73
  23. package/{example/chrome_mobile_emulation.js → lib/atoms/make-atoms-module.js} +16 -23
  24. package/lib/by.js +192 -65
  25. package/lib/capabilities.js +82 -78
  26. package/lib/command.js +18 -20
  27. package/lib/error.js +134 -168
  28. package/lib/http.js +324 -230
  29. package/lib/input.js +325 -302
  30. package/lib/logging.js +127 -138
  31. package/lib/promise.js +60 -66
  32. package/lib/proxy.js +31 -41
  33. package/lib/session.js +12 -15
  34. package/lib/symbols.js +3 -4
  35. package/lib/until.js +162 -162
  36. package/lib/webdriver.js +733 -522
  37. package/net/index.js +30 -36
  38. package/net/portprober.js +31 -144
  39. package/opera.js +406 -0
  40. package/package.json +18 -11
  41. package/proxy.js +2 -2
  42. package/remote/index.js +190 -187
  43. package/safari.js +40 -49
  44. package/LICENSE +0 -202
  45. package/NOTICE +0 -2
  46. package/example/chrome_android.js +0 -42
  47. package/example/firefox_channels.js +0 -77
  48. package/example/google_search.js +0 -50
  49. package/example/google_search_test.js +0 -72
  50. package/example/headless.js +0 -55
  51. package/example/logging.js +0 -68
  52. package/testing/index.js +0 -498
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,114 +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
186
+
187
+ // Update the protocol to avoid EPROTO errors when the webdriver proxy
188
+ // uses a different protocol from the remote selenium server.
189
+ options.protocol = opt_proxy.protocol
189
190
 
190
191
  if (proxy.auth) {
191
192
  options.headers['Proxy-Authorization'] =
192
- 'Basic ' + new Buffer(proxy.auth).toString('base64');
193
+ 'Basic ' + Buffer.from(proxy.auth).toString('base64')
193
194
  }
194
195
  }
195
196
 
196
- let requestFn = options.protocol === 'https:' ? https.request : http.request;
197
+ let requestFn = options.protocol === 'https:' ? https.request : http.request
197
198
  var request = requestFn(options, function onResponse(response) {
198
199
  if (response.statusCode == 302 || response.statusCode == 303) {
199
200
  try {
200
- var location = url.parse(response.headers['location']);
201
+ // eslint-disable-next-line node/no-deprecated-api
202
+ var location = url.parse(response.headers['location'])
201
203
  } catch (ex) {
202
- onError(Error(
204
+ onError(
205
+ Error(
203
206
  'Failed to parse "Location" header for server redirect: ' +
204
- ex.message + '\nResponse was: \n' +
205
- new httpLib.Response(response.statusCode, response.headers, '')));
206
- return;
207
+ ex.message +
208
+ '\nResponse was: \n' +
209
+ new httpLib.Response(response.statusCode, response.headers, '')
210
+ )
211
+ )
212
+ return
207
213
  }
208
214
 
209
215
  if (!location.hostname) {
210
- location.hostname = hostname;
211
- location.port = port;
216
+ location.hostname = hostname
217
+ location.port = port
218
+ location.auth = options.auth
212
219
  }
213
220
 
214
- request.abort();
215
- sendRequest({
216
- method: 'GET',
217
- protocol: location.protocol || options.protocol,
218
- hostname: location.hostname,
219
- port: location.port,
220
- path: location.path,
221
- pathname: location.pathname,
222
- search: location.search,
223
- hash: location.hash,
224
- headers: {
225
- 'Accept': 'application/json; charset=utf-8',
226
- 'User-Agent': USER_AGENT,
227
- }
228
- }, onOk, onError, undefined, opt_proxy);
229
- 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
230
244
  }
231
245
 
232
- var body = [];
233
- response.on('data', body.push.bind(body));
234
- response.on('end', function() {
246
+ var body = []
247
+ response.on('data', body.push.bind(body))
248
+ response.on('end', function () {
235
249
  var resp = new httpLib.Response(
236
- /** @type {number} */(response.statusCode),
237
- /** @type {!Object<string>} */(response.headers),
238
- Buffer.concat(body).toString('utf8').replace(/\0/g, ''));
239
- onOk(resp);
240
- });
241
- });
242
-
243
- 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) {
244
259
  if (typeof opt_retries === 'undefined') {
245
- opt_retries = 0;
260
+ opt_retries = 0
246
261
  }
247
262
 
248
263
  if (shouldRetryRequest(opt_retries, e)) {
249
- opt_retries += 1;
250
- setTimeout(function() {
251
- sendRequest(options, onOk, onError, opt_data, opt_proxy, opt_retries);
252
- }, 15);
264
+ opt_retries += 1
265
+ setTimeout(function () {
266
+ sendRequest(options, onOk, onError, opt_data, opt_proxy, opt_retries)
267
+ }, 15)
253
268
  } else {
254
- var message = e.message;
269
+ var message = e.message
255
270
  if (e.code) {
256
- message = e.code + ' ' + message;
271
+ message = e.code + ' ' + message
257
272
  }
258
- onError(new Error(message));
273
+ onError(new Error(message))
259
274
  }
260
- });
275
+ })
261
276
 
262
277
  if (opt_data) {
263
- request.write(opt_data);
278
+ request.write(opt_data)
264
279
  }
265
280
 
266
- request.end();
281
+ request.end()
267
282
  }
268
283
 
269
-
270
- const MAX_RETRIES = 3;
284
+ const MAX_RETRIES = 3
271
285
 
272
286
  /**
273
287
  * A retry is sometimes needed on Windows where we may quickly run out of
@@ -279,7 +293,7 @@ const MAX_RETRIES = 3;
279
293
  * @return {boolean}
280
294
  */
281
295
  function shouldRetryRequest(retries, err) {
282
- return retries < MAX_RETRIES && isRetryableNetworkError(err);
296
+ return retries < MAX_RETRIES && isRetryableNetworkError(err)
283
297
  }
284
298
 
285
299
  /**
@@ -288,21 +302,23 @@ function shouldRetryRequest(retries, err) {
288
302
  */
289
303
  function isRetryableNetworkError(err) {
290
304
  if (err && err.code) {
291
- return err.code === 'ECONNABORTED' ||
292
- err.code === 'ECONNRESET' ||
293
- err.code === 'ECONNREFUSED' ||
294
- err.code === 'EADDRINUSE' ||
295
- 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
+ )
296
313
  }
297
314
 
298
- return false;
315
+ return false
299
316
  }
300
317
 
301
-
302
318
  // PUBLIC API
303
319
 
304
- exports.Agent = http.Agent;
305
- exports.Executor = httpLib.Executor;
306
- exports.HttpClient = HttpClient;
307
- exports.Request = httpLib.Request;
308
- 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
+ var client = new HttpClient(url)
39
+ var executor = new Executor(client)
40
+ var 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
+ }