selenium-webdriver 3.6.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.
Files changed (97) hide show
  1. package/CHANGES.md +181 -0
  2. package/README.md +25 -27
  3. package/chrome.js +113 -127
  4. package/edge.js +42 -117
  5. package/example/chrome_android.js +8 -8
  6. package/example/chrome_mobile_emulation.js +8 -8
  7. package/example/firefox_channels.js +22 -18
  8. package/example/google_search_test.js +39 -26
  9. package/example/logging.js +39 -6
  10. package/firefox.js +769 -0
  11. package/http/index.js +41 -4
  12. package/http/util.js +11 -6
  13. package/ie.js +56 -97
  14. package/index.js +178 -114
  15. package/jasmine.json +11 -0
  16. package/lib/actions.js +68 -63
  17. package/lib/by.js +1 -1
  18. package/lib/capabilities.js +255 -192
  19. package/lib/command.js +26 -50
  20. package/lib/error.js +85 -44
  21. package/lib/http.js +133 -110
  22. package/lib/input.js +1044 -8
  23. package/lib/promise.js +222 -3323
  24. package/lib/proxy.js +134 -39
  25. package/lib/test/bootstrap_jasmine.js +28 -0
  26. package/lib/test/data/actions/click.html +24 -0
  27. package/lib/test/data/actions/drag.html +77 -0
  28. package/lib/test/data/actions/record_click.html +21 -0
  29. package/lib/test/data/chrome/download.html +2 -0
  30. package/lib/test/data/inputs.html +42 -0
  31. package/lib/test/data/selectPage.html +12 -0
  32. package/lib/test/data/simpleTest.html +5 -0
  33. package/lib/test/data/upload_invisible.html +45 -0
  34. package/lib/test/fileserver.js +23 -19
  35. package/lib/test/index.js +30 -212
  36. package/lib/test/resources.js +0 -1
  37. package/lib/webdriver.js +675 -936
  38. package/net/index.js +21 -25
  39. package/net/portprober.js +51 -68
  40. package/package.json +5 -3
  41. package/remote/index.js +5 -19
  42. package/safari.js +41 -128
  43. package/test/actions_test.js +173 -18
  44. package/test/{session_test.js → builder_test.js} +44 -37
  45. package/test/chrome/devtools_test.js +93 -0
  46. package/test/chrome/options_test.js +48 -154
  47. package/test/chrome/service_test.js +7 -7
  48. package/test/cookie_test.js +77 -63
  49. package/test/element_finding_test.js +206 -201
  50. package/test/execute_script_test.js +115 -114
  51. package/test/fingerprint_test.js +16 -15
  52. package/test/firefox_test.js +251 -0
  53. package/test/http/http_test.js +0 -1
  54. package/test/http/util_test.js +2 -2
  55. package/test/io/zip_test.js +6 -7
  56. package/test/lib/error_test.js +34 -7
  57. package/test/lib/http_test.js +8 -128
  58. package/test/lib/input_test.js +1379 -0
  59. package/test/lib/promise_test.js +473 -908
  60. package/test/lib/webdriver_test.js +296 -868
  61. package/test/logging_test.js +37 -43
  62. package/test/page_loading_test.js +71 -81
  63. package/test/proxy_test.js +64 -72
  64. package/test/rect_test.js +14 -25
  65. package/test/remote_test.js +10 -29
  66. package/test/safari_test.js +7 -71
  67. package/test/stale_element_test.js +20 -23
  68. package/test/tag_name_test.js +10 -9
  69. package/test/upload_test.js +27 -35
  70. package/test/window_test.js +72 -85
  71. package/testing/index.js +386 -314
  72. package/.npmignore +0 -2
  73. package/example/async_await_test.js +0 -69
  74. package/example/google_search_generator.js +0 -47
  75. package/example/parallel_flows.js +0 -51
  76. package/firefox/binary.js +0 -347
  77. package/firefox/extension.js +0 -224
  78. package/firefox/index.js +0 -576
  79. package/firefox/profile.js +0 -311
  80. package/lib/events.js +0 -210
  81. package/lib/test/data/firefox/jetpack-sample.xpi +0 -0
  82. package/lib/test/data/firefox/sample.xpi +0 -0
  83. package/lib/test/promise.js +0 -79
  84. package/opera.js +0 -405
  85. package/phantomjs.js +0 -282
  86. package/test/firefox/extension_test.js +0 -120
  87. package/test/firefox/firefox_test.js +0 -244
  88. package/test/firefox/profile_test.js +0 -140
  89. package/test/lib/events_test.js +0 -177
  90. package/test/lib/promise_aplus_test.js +0 -78
  91. package/test/lib/promise_error_test.js +0 -884
  92. package/test/lib/promise_flow_test.js +0 -2288
  93. package/test/lib/promise_generator_test.js +0 -310
  94. package/test/phantomjs/execute_phantomjs_test.js +0 -59
  95. package/test/testing/assert_test.js +0 -373
  96. package/test/testing/index_test.js +0 -224
  97. package/testing/assert.js +0 -378
package/edge.js CHANGED
@@ -70,121 +70,44 @@
70
70
 
71
71
  'use strict';
72
72
 
73
- const fs = require('fs'),
74
- util = require('util');
75
-
76
- const http = require('./http'),
77
- io = require('./io'),
78
- capabilities = require('./lib/capabilities'),
79
- promise = require('./lib/promise'),
80
- Symbols = require('./lib/symbols'),
81
- webdriver = require('./lib/webdriver'),
82
- portprober = require('./net/portprober'),
83
- remote = require('./remote');
73
+ const fs = require('fs');
74
+ const util = require('util');
75
+
76
+ const http = require('./http');
77
+ const io = require('./io');
78
+ const portprober = require('./net/portprober');
79
+ const promise = require('./lib/promise');
80
+ const remote = require('./remote');
81
+ const Symbols = require('./lib/symbols');
82
+ const webdriver = require('./lib/webdriver');
83
+ const {Browser, Capabilities} = require('./lib/capabilities');
84
84
 
85
85
  const EDGEDRIVER_EXE = 'MicrosoftWebDriver.exe';
86
86
 
87
87
 
88
88
  /**
89
- * Option keys.
90
- * @enum {string}
89
+ * _Synchronously_ attempts to locate the edge driver executable on the current
90
+ * system.
91
+ *
92
+ * @return {?string} the located executable, or `null`.
91
93
  */
92
- const CAPABILITY_KEY = {
93
- PAGE_LOAD_STRATEGY: 'pageLoadStrategy'
94
- };
94
+ function locateSynchronously() {
95
+ return process.platform === 'win32'
96
+ ? io.findInPath(EDGEDRIVER_EXE, true) : null;
97
+ }
95
98
 
96
99
 
97
100
  /**
98
101
  * Class for managing MicrosoftEdgeDriver specific options.
99
102
  */
100
- class Options {
101
- constructor() {
102
- /** @private {!Object} */
103
- this.options_ = {};
104
-
105
- /** @private {?capabilities.ProxyConfig} */
106
- this.proxy_ = null;
107
- }
108
-
109
- /**
110
- * Extracts the MicrosoftEdgeDriver specific options from the given
111
- * capabilities object.
112
- * @param {!capabilities.Capabilities} caps The capabilities object.
113
- * @return {!Options} The MicrosoftEdgeDriver options.
114
- */
115
- static fromCapabilities(caps) {
116
- var options = new Options();
117
- var map = options.options_;
118
-
119
- Object.keys(CAPABILITY_KEY).forEach(function(key) {
120
- key = CAPABILITY_KEY[key];
121
- if (caps.has(key)) {
122
- map[key] = caps.get(key);
123
- }
124
- });
125
-
126
- if (caps.has(capabilities.Capability.PROXY)) {
127
- options.setProxy(caps.get(capabilities.Capability.PROXY));
128
- }
129
-
130
- return options;
131
- }
132
-
133
- /**
134
- * Sets the proxy settings for the new session.
135
- * @param {capabilities.ProxyConfig} proxy The proxy configuration to use.
136
- * @return {!Options} A self reference.
137
- */
138
- setProxy(proxy) {
139
- this.proxy_ = proxy;
140
- return this;
141
- }
142
-
103
+ class Options extends Capabilities {
143
104
  /**
144
- * Sets the page load strategy for Edge.
145
- * Supported values are "normal", "eager", and "none";
146
- *
147
- * @param {string} pageLoadStrategy The page load strategy to use.
148
- * @return {!Options} A self reference.
105
+ * @param {(Capabilities|Map<string, ?>|Object)=} other Another set of
106
+ * capabilities to initialize this instance from.
149
107
  */
150
- setPageLoadStrategy(pageLoadStrategy) {
151
- this.options_[CAPABILITY_KEY.PAGE_LOAD_STRATEGY] =
152
- pageLoadStrategy.toLowerCase();
153
- return this;
154
- }
155
-
156
- /**
157
- * Converts this options instance to a {@link capabilities.Capabilities}
158
- * object.
159
- * @param {capabilities.Capabilities=} opt_capabilities The capabilities to
160
- * merge these options into, if any.
161
- * @return {!capabilities.Capabilities} The capabilities.
162
- */
163
- toCapabilities(opt_capabilities) {
164
- var caps = opt_capabilities || capabilities.Capabilities.edge();
165
- if (this.proxy_) {
166
- caps.set(capabilities.Capability.PROXY, this.proxy_);
167
- }
168
- Object.keys(this.options_).forEach(function(key) {
169
- caps.set(key, this.options_[key]);
170
- }, this);
171
- return caps;
172
- }
173
-
174
- /**
175
- * Converts this instance to its JSON wire protocol representation. Note this
176
- * function is an implementation not intended for general use.
177
- * @return {{pageLoadStrategy: (string|undefined)}}
178
- * The JSON wire protocol representation of this instance.
179
- */
180
- [Symbols.serialize]() {
181
- var json = {};
182
- for (var key in this.options_) {
183
- if (this.options_[key] != null) {
184
- json[key] = this.options_[key];
185
- }
186
- }
187
- return json;
108
+ constructor(other = undefined) {
109
+ super(other);
110
+ this.setBrowserName(Browser.EDGE);
188
111
  }
189
112
  }
190
113
 
@@ -202,7 +125,7 @@ class ServiceBuilder extends remote.DriverService.Builder {
202
125
  * MicrosoftEdgeDriver cannot be found on the PATH.
203
126
  */
204
127
  constructor(opt_exe) {
205
- let exe = opt_exe || io.findInPath(EDGEDRIVER_EXE, true);
128
+ let exe = opt_exe || locateSynchronously();
206
129
  if (!exe) {
207
130
  throw Error(
208
131
  'The ' + EDGEDRIVER_EXE + ' could not be found on the current PATH. ' +
@@ -218,6 +141,14 @@ class ServiceBuilder extends remote.DriverService.Builder {
218
141
  // (or can we?), force the DriverService to use "localhost".
219
142
  this.setHostname('localhost');
220
143
  }
144
+
145
+ /**
146
+ * Enables verbose logging.
147
+ * @return {!ServiceBuilder} A self reference.
148
+ */
149
+ enableVerboseLogging() {
150
+ return this.addArguments('--verbose');
151
+ }
221
152
  }
222
153
 
223
154
 
@@ -261,25 +192,18 @@ class Driver extends webdriver.WebDriver {
261
192
  /**
262
193
  * Creates a new browser session for Microsoft's Edge browser.
263
194
  *
264
- * @param {(capabilities.Capabilities|Options)=} opt_config The configuration
265
- * options.
266
- * @param {remote.DriverService=} opt_service The session to use; will use
195
+ * @param {(Capabilities|Options)=} options The configuration options.
196
+ * @param {remote.DriverService=} service The session to use; will use
267
197
  * the {@linkplain #getDefaultService default service} by default.
268
- * @param {promise.ControlFlow=} opt_flow The control flow to use, or
269
- * {@code null} to use the currently active flow.
270
198
  * @return {!Driver} A new driver instance.
271
199
  */
272
- static createSession(opt_config, opt_service, opt_flow) {
273
- var service = opt_service || getDefaultService();
274
- var client = service.start().then(url => new http.HttpClient(url));
275
- var executor = new http.Executor(client);
276
-
277
- var caps =
278
- opt_config instanceof Options ? opt_config.toCapabilities() :
279
- (opt_config || capabilities.Capabilities.edge());
200
+ static createSession(options, service = getDefaultService()) {
201
+ let client = service.start().then(url => new http.HttpClient(url));
202
+ let executor = new http.Executor(client);
280
203
 
204
+ options = options || new Options();
281
205
  return /** @type {!Driver} */(super.createSession(
282
- executor, caps, opt_flow, () => service.kill()));
206
+ executor, options, () => service.kill()));
283
207
  }
284
208
 
285
209
  /**
@@ -299,3 +223,4 @@ exports.Options = Options;
299
223
  exports.ServiceBuilder = ServiceBuilder;
300
224
  exports.getDefaultService = getDefaultService;
301
225
  exports.setDefaultService = setDefaultService;
226
+ exports.locateSynchronously = locateSynchronously;
@@ -23,20 +23,20 @@
23
23
 
24
24
  'use strict';
25
25
 
26
- const {Builder, By, Key, promise, until} = require('..');
26
+ const {Builder, By, Key, until} = require('..');
27
27
  const {Options} = require('../chrome');
28
28
 
29
- promise.consume(function* () {
29
+ (async function() {
30
30
  let driver;
31
31
  try {
32
- driver = yield new Builder()
32
+ driver = await new Builder()
33
33
  .forBrowser('chrome')
34
34
  .setChromeOptions(new Options().androidChrome())
35
35
  .build();
36
- yield driver.get('http://www.google.com/ncr');
37
- yield driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN);
38
- yield driver.wait(until.titleIs('webdriver - Google Search'), 1000);
36
+ await driver.get('http://www.google.com/ncr');
37
+ await driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN);
38
+ await driver.wait(until.titleIs('webdriver - Google Search'), 1000);
39
39
  } finally {
40
- yield driver && driver.quit();
40
+ await driver && driver.quit();
41
41
  }
42
- }).then(_ => console.log('SUCCESS'), err => console.error('ERROR: ' + err));
42
+ })().then(_ => console.log('SUCCESS'), err => console.error('ERROR: ' + err));
@@ -22,21 +22,21 @@
22
22
 
23
23
  'use strict';
24
24
 
25
- const {Builder, By, Key, promise, until} = require('..');
25
+ const {Builder, By, Key, until} = require('..');
26
26
  const {Options} = require('../chrome');
27
27
 
28
- promise.consume(function* () {
28
+ (async function() {
29
29
  let driver;
30
30
  try {
31
- driver = yield new Builder()
31
+ driver = await new Builder()
32
32
  .forBrowser('chrome')
33
33
  .setChromeOptions(
34
34
  new Options().setMobileEmulation({deviceName: 'Nexus 5X'}))
35
35
  .build();
36
- yield driver.get('http://www.google.com/ncr');
37
- yield driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN);
38
- yield driver.wait(until.titleIs('webdriver - Google Search'), 1000);
36
+ await driver.get('http://www.google.com/ncr');
37
+ await driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN);
38
+ await driver.wait(until.titleIs('webdriver - Google Search'), 1000);
39
39
  } finally {
40
- yield driver && driver.quit();
40
+ await driver && driver.quit();
41
41
  }
42
- }).then(_ => console.log('SUCCESS'), err => console.error('ERROR: ' + err));
42
+ })().then(_ => console.log('SUCCESS'), err => console.error('ERROR: ' + err));
@@ -32,23 +32,32 @@ const {Channel, Options} = require('../firefox');
32
32
 
33
33
  let i = 0;
34
34
  function resposition(driver) {
35
- return driver.manage().window().setSize(600, 400)
36
- .then(_ => driver.manage().window().setPosition(300 * (i++), 0));
35
+ return driver.manage().window().setRect({
36
+ width: 600,
37
+ height: 400,
38
+ x: 300 * (i++),
39
+ y: 0
40
+ });
37
41
  }
38
42
 
39
- function doSearch(driver) {
40
- // Start on the base about page.
41
- return driver.get('about:')
43
+ async function doSearch(driver) {
44
+ try {
45
+ // Start on the base about page.
46
+ await driver.get('about:')
42
47
  // Reposition so users can see the three windows.
43
- .then(_ => resposition(driver))
48
+ await resposition(driver);
44
49
  // Pause so users can see the magic.
45
- .then(_ => promise.delayed(750))
50
+ await promise.delayed(750);
46
51
  // Now do the rest.
47
- .then(_ => driver.get('http://www.google.com/ncr'))
48
- .then(_ =>
49
- driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN))
50
- .then(_ => driver.wait(until.titleIs('webdriver - Google Search'), 1000))
51
- .then(_ => driver.quit());
52
+ await driver.get('http://www.google.com/ncr');
53
+ await driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN);
54
+ await driver.wait(until.titleIs('webdriver - Google Search'), 1000);
55
+ console.log('Success!');
56
+ } catch (ex) {
57
+ console.log('An error occured! ' + ex);
58
+ } finally {
59
+ await driver.quit();
60
+ }
52
61
  }
53
62
 
54
63
  function createDriver(channel) {
@@ -56,17 +65,12 @@ function createDriver(channel) {
56
65
  return new Builder().forBrowser('firefox').setFirefoxOptions(options).build();
57
66
  }
58
67
 
59
- // NOTE: disabling the promise manager so searches all run concurrently.
60
- // For more on the promise manager and its pending deprecation, see
61
- // https://github.com/SeleniumHQ/selenium/issues/2969
62
- promise.USE_PROMISE_MANAGER = false;
63
-
64
68
  Promise.all([
65
69
  doSearch(createDriver(Channel.RELEASE)),
66
70
  doSearch(createDriver(Channel.AURORA)), // Developer Edition.
67
71
  doSearch(createDriver(Channel.NIGHTLY)),
68
72
  ]).then(_ => {
69
- console.log('Success!');
73
+ console.log('All done!');
70
74
  }, err => {
71
75
  console.error('An error occured! ' + err);
72
76
  setTimeout(() => {throw err}, 0);
@@ -18,43 +18,56 @@
18
18
  /**
19
19
  * @fileoverview An example test that may be run using Mocha.
20
20
  *
21
+ * This example uses the `selenium-webdriver/testing.suite` function, which will
22
+ * automatically run tests against every available WebDriver browser on the
23
+ * current system. Alternatively, you may use the `SELENIUM_BROWSER`
24
+ * environment variable to narrow the scope at runtime.
25
+ *
21
26
  * Usage:
22
27
  *
28
+ * # Automatically determine which browsers to run against.
23
29
  * mocha -t 10000 selenium-webdriver/example/google_search_test.js
24
30
  *
25
- * You can change which browser is started with the SELENIUM_BROWSER environment
26
- * variable:
27
- *
31
+ * # Configure tests to only run against Google Chrome.
28
32
  * SELENIUM_BROWSER=chrome \
29
33
  * mocha -t 10000 selenium-webdriver/example/google_search_test.js
30
34
  */
31
35
 
32
- const {Builder, By, Key, until} = require('..');
33
- const test = require('../testing');
36
+ const assert = require('assert');
34
37
 
35
- test.describe('Google Search', function() {
36
- let driver;
38
+ const {Browser, By, Key, until} = require('..');
39
+ const {ignore, suite} = require('../testing');
37
40
 
38
- test.before(function *() {
39
- driver = yield new Builder().forBrowser('firefox').build();
40
- });
41
+ suite(function(env) {
42
+ describe('Google Search', function() {
43
+ let driver;
41
44
 
42
- // You can write tests either using traditional promises.
43
- it('works with promises', function() {
44
- return driver.get('http://www.google.com/ncr')
45
- .then(_ =>
46
- driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN))
47
- .then(_ => driver.wait(until.titleIs('webdriver - Google Search'), 1000));
48
- });
45
+ before(async function() {
46
+ // env.builder() returns a Builder instance preconfigured for the
47
+ // envrionment's target browser (you may still define browser specific
48
+ // options if necessary (i.e. firefox.Options or chrome.Options)).
49
+ driver = await env.builder().build();
50
+ });
49
51
 
50
- // Or you can define the test as a generator function. The test will wait for
51
- // any yielded promises to resolve before invoking the next step in the
52
- // generator.
53
- test.it('works with generators', function*() {
54
- yield driver.get('http://www.google.com/ncr');
55
- yield driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN);
56
- yield driver.wait(until.titleIs('webdriver - Google Search'), 1000);
57
- });
52
+ it('demo', async function() {
53
+ await driver.get('https://www.google.com/ncr');
54
+ await driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN);
55
+ await driver.wait(until.titleIs('webdriver - Google Search'), 1000);
56
+ });
57
+
58
+ // The ignore function returns wrappers around describe & it that will
59
+ // suppress tests if the provided predicate returns true. You may provide
60
+ // any synchronous predicate. The env.browsers(...) function generates a
61
+ // predicate that will suppress tests if the env targets one of the
62
+ // specified browsers.
63
+ //
64
+ // This example is always configured to skip Chrome.
65
+ ignore(env.browsers(Browser.CHROME)).it('demo 2', async function() {
66
+ await driver.get('http://www.google.com/ncr');
67
+ let url = await driver.getCurrentUrl();
68
+ assert.equal(url, 'https://www.google.com/');
69
+ });
58
70
 
59
- test.after(() => driver.quit());
71
+ after(() => driver && driver.quit());
72
+ });
60
73
  });
@@ -21,15 +21,48 @@
21
21
 
22
22
  'use strict';
23
23
 
24
+ const chrome = require('../chrome');
25
+ const firefox = require('../firefox');
26
+ const edge = require('../edge');
24
27
  const {Builder, By, Key, logging, until} = require('..');
25
28
 
26
29
  logging.installConsoleHandler();
27
30
  logging.getLogger('webdriver.http').setLevel(logging.Level.ALL);
28
31
 
29
- var driver = new Builder().forBrowser('firefox').build();
32
+ (async function() {
33
+ let driver;
34
+ try {
35
+ driver = await new Builder()
36
+ // Default to using Firefox. This can be overridden at runtime by
37
+ // setting the SELENIUM_BROWSER environment variable:
38
+ //
39
+ // SELENIUM_BROWSER=chrome node selenium-webdriver/example/logging.js
40
+ .forBrowser('firefox')
41
+ // Configure the service for each browser to enable verbose logging and
42
+ // to inherit the stdio settings from the current process. The builder
43
+ // will only start the service if needed for the selected browser.
44
+ .setChromeService(
45
+ new chrome.ServiceBuilder()
46
+ .enableVerboseLogging()
47
+ .setStdio('inherit'))
48
+ .setEdgeService(
49
+ process.platform === 'win32'
50
+ ? new edge.ServiceBuilder()
51
+ .enableVerboseLogging()
52
+ .setStdio('inherit')
53
+ : null)
54
+ .setFirefoxService(
55
+ new firefox.ServiceBuilder()
56
+ .enableVerboseLogging()
57
+ .setStdio('inherit'))
58
+ .build();
30
59
 
31
- driver.get('http://www.google.com/ncr')
32
- .then(_ =>
33
- driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN))
34
- .then(_ => driver.wait(until.titleIs('webdriver - Google Search'), 1000))
35
- .then(_ => driver.quit());
60
+ await driver.get('http://www.google.com/ncr');
61
+ await driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN);
62
+ await driver.wait(until.titleIs('webdriver - Google Search'), 1000);
63
+ } finally {
64
+ if (driver) {
65
+ await driver.quit();
66
+ }
67
+ }
68
+ })();