selenium-webdriver 3.5.0 → 3.6.0

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/lib/error.js CHANGED
@@ -51,11 +51,27 @@ class ElementNotSelectableError extends WebDriverError {
51
51
  }
52
52
 
53
53
 
54
+ /**
55
+ * Indicates a command could not be completed because the target element is
56
+ * not pointer or keyboard interactable. This will often occur if an element
57
+ * is present in the DOM, but not rendered (i.e. its CSS style has
58
+ * "display: none").
59
+ */
60
+ class ElementNotInteractableError extends WebDriverError {
61
+ /** @param {string=} opt_error the error message, if any. */
62
+ constructor(opt_error) {
63
+ super(opt_error);
64
+ }
65
+ }
66
+
67
+
54
68
  /**
55
69
  * An element command could not be completed because the element is not visible
56
70
  * on the page.
71
+ *
72
+ * @deprecated Use {@link ElementNotInteractable} instead.
57
73
  */
58
- class ElementNotVisibleError extends WebDriverError {
74
+ class ElementNotVisibleError extends ElementNotInteractableError {
59
75
  /** @param {string=} opt_error the error message, if any. */
60
76
  constructor(opt_error) {
61
77
  super(opt_error);
@@ -400,6 +416,7 @@ const LEGACY_ERROR_CODE_TO_TYPE = new Map([
400
416
 
401
417
  const ERROR_CODE_TO_TYPE = new Map([
402
418
  ['unknown error', WebDriverError],
419
+ ['element not interactable', ElementNotInteractableError],
403
420
  ['element not selectable', ElementNotSelectableError],
404
421
  ['element not visible', ElementNotVisibleError],
405
422
  ['invalid argument', InvalidArgumentError],
@@ -547,6 +564,7 @@ module.exports = {
547
564
  ErrorCode: ErrorCode,
548
565
 
549
566
  WebDriverError: WebDriverError,
567
+ ElementNotInteractableError: ElementNotInteractableError,
550
568
  ElementNotSelectableError: ElementNotSelectableError,
551
569
  ElementNotVisibleError: ElementNotVisibleError,
552
570
  InvalidArgumentError: InvalidArgumentError,
package/lib/http.js CHANGED
@@ -35,7 +35,7 @@ const WebElement = require('./webdriver').WebElement;
35
35
  const {getAttribute, isDisplayed} = /** @suppress {undefinedVars|uselessCode} */(function() {
36
36
  try {
37
37
  return {
38
- getAttribute: require('./atoms/getAttribute.js'),
38
+ getAttribute: require('./atoms/get-attribute.js'),
39
39
  isDisplayed: require('./atoms/is-displayed.js')
40
40
  };
41
41
  } catch (ex) {
package/lib/promise.js CHANGED
@@ -33,13 +33,12 @@
33
33
  * > style tests:
34
34
  * >
35
35
  * > ```js
36
- * > const {Builder, By, promise, until} = require('selenium-webdriver');
36
+ * > const {Builder, By, Key, promise, until} = require('selenium-webdriver');
37
37
  * >
38
38
  * > let result = promise.consume(function* doGoogleSearch() {
39
39
  * > let driver = new Builder().forBrowser('firefox').build();
40
40
  * > yield driver.get('http://www.google.com/ncr');
41
- * > yield driver.findElement(By.name('q')).sendKeys('webdriver');
42
- * > yield driver.findElement(By.name('btnG')).click();
41
+ * > yield driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN);
43
42
  * > yield driver.wait(until.titleIs('webdriver - Google Search'), 1000);
44
43
  * > yield driver.quit();
45
44
  * > });
@@ -63,8 +62,7 @@
63
62
  * control flow, allowing users to write
64
63
  *
65
64
  * driver.get('http://www.google.com/ncr');
66
- * driver.findElement({name: 'q'}).sendKeys('webdriver');
67
- * driver.findElement({name: 'btnGn'}).click();
65
+ * driver.findElement({name: 'q'}).sendKeys('webdriver', Key.RETURN);
68
66
  *
69
67
  * instead of
70
68
  *
@@ -73,13 +71,7 @@
73
71
  * return driver.findElement({name: 'q'});
74
72
  * })
75
73
  * .then(function(q) {
76
- * return q.sendKeys('webdriver');
77
- * })
78
- * .then(function() {
79
- * return driver.findElement({name: 'btnG'});
80
- * })
81
- * .then(function(btnG) {
82
- * return btnG.click();
74
+ * return q.sendKeys('webdriver', Key.RETURN);
83
75
  * });
84
76
  *
85
77
  * ## Tasks and Task Queues
@@ -0,0 +1,10 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Testing content editable</title>
5
+ </head>
6
+ <body>
7
+ <div id="editable" contenteditable="true">
8
+ Why <span>hello</span></div>
9
+ </body>
10
+ </html>
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Page with partially hidden element</title>
5
+ </head>
6
+ <body>
7
+ <div style="width:200px; height: 200px; overflow: auto;">
8
+ <div style="height: 175px; width: 240px;">Placeholder</div>
9
+ <div>
10
+ <button type="button" style="height: 40px; box-sizing: border-box" id="btn" onclick="window.location='target_page.html'">Click me!</button>
11
+ </div>
12
+ </div>
13
+ </body>
14
+ </html>
package/lib/test/index.js CHANGED
@@ -205,7 +205,7 @@ function suite(fn, opt_options) {
205
205
  if (isDevMode && !noBuild) {
206
206
  return build.of(
207
207
  '//javascript/atoms/fragments:is-displayed',
208
- '//javascript/webdriver/atoms:getAttribute')
208
+ '//javascript/webdriver/atoms:get-attribute')
209
209
  .onlyOnce().go();
210
210
  }
211
211
  });
package/lib/webdriver.js CHANGED
@@ -1045,13 +1045,15 @@ class WebDriver {
1045
1045
  let cmd = new command.Command(command.Name.FIND_ELEMENTS).
1046
1046
  setParameter('using', locator.using).
1047
1047
  setParameter('value', locator.value);
1048
- let res = this.schedule(cmd, 'WebDriver.findElements(' + locator + ')');
1049
- return res.catch(function(e) {
1050
- if (e instanceof error.NoSuchElementError) {
1051
- return [];
1052
- }
1053
- throw e;
1054
- });
1048
+ return this.schedule(cmd, 'WebDriver.findElements(' + locator + ')')
1049
+ .then(
1050
+ (res) => Array.isArray(res) ? res : [],
1051
+ (e) => {
1052
+ if (e instanceof error.NoSuchElementError) {
1053
+ return [];
1054
+ }
1055
+ throw e;
1056
+ });
1055
1057
  }
1056
1058
  }
1057
1059
 
@@ -1191,14 +1193,14 @@ class Options {
1191
1193
  * __Sample Usage:__
1192
1194
  *
1193
1195
  * // Set a basic cookie.
1194
- * driver.options().addCookie({name: 'foo', value: 'bar'});
1196
+ * driver.manage().addCookie({name: 'foo', value: 'bar'});
1195
1197
  *
1196
1198
  * // Set a cookie that expires in 10 minutes.
1197
1199
  * let expiry = new Date(Date.now() + (10 * 60 * 1000));
1198
- * driver.options().addCookie({name: 'foo', value: 'bar', expiry});
1200
+ * driver.manage().addCookie({name: 'foo', value: 'bar', expiry});
1199
1201
  *
1200
1202
  * // The cookie expiration may also be specified in seconds since epoch.
1201
- * driver.options().addCookie({
1203
+ * driver.manage().addCookie({
1202
1204
  * name: 'foo',
1203
1205
  * value: 'bar',
1204
1206
  * expiry: Math.floor(Date.now() / 1000)
@@ -1211,36 +1213,29 @@ class Options {
1211
1213
  * invalid.
1212
1214
  * @throws {TypeError} if `spec` is not a cookie object.
1213
1215
  */
1214
- addCookie(spec) {
1215
- if (!spec || typeof spec !== 'object') {
1216
- throw TypeError('addCookie called with non-cookie parameter');
1217
- }
1218
-
1216
+ addCookie({name, value, path, domain, secure, httpOnly, expiry}) {
1219
1217
  // We do not allow '=' or ';' in the name.
1220
- let name = spec.name;
1221
1218
  if (/[;=]/.test(name)) {
1222
1219
  throw new error.InvalidArgumentError(
1223
1220
  'Invalid cookie name "' + name + '"');
1224
1221
  }
1225
1222
 
1226
1223
  // We do not allow ';' in value.
1227
- let value = spec.value;
1228
1224
  if (/;/.test(value)) {
1229
1225
  throw new error.InvalidArgumentError(
1230
1226
  'Invalid cookie value "' + value + '"');
1231
1227
  }
1232
1228
 
1233
1229
  let cookieString = name + '=' + value +
1234
- (spec.domain ? ';domain=' + spec.domain : '') +
1235
- (spec.path ? ';path=' + spec.path : '') +
1236
- (spec.secure ? ';secure' : '');
1237
-
1238
- let expiry;
1239
- if (typeof spec.expiry === 'number') {
1240
- expiry = Math.floor(spec.expiry);
1241
- cookieString += ';expires=' + new Date(spec.expiry * 1000).toUTCString();
1242
- } else if (spec.expiry instanceof Date) {
1243
- let date = /** @type {!Date} */(spec.expiry);
1230
+ (domain ? ';domain=' + domain : '') +
1231
+ (path ? ';path=' + path : '') +
1232
+ (secure ? ';secure' : '');
1233
+
1234
+ if (typeof expiry === 'number') {
1235
+ expiry = Math.floor(expiry);
1236
+ cookieString += ';expires=' + new Date(expiry * 1000).toUTCString();
1237
+ } else if (expiry instanceof Date) {
1238
+ let date = /** @type {!Date} */(expiry);
1244
1239
  expiry = Math.floor(date.getTime() / 1000);
1245
1240
  cookieString += ';expires=' + date.toUTCString();
1246
1241
  }
@@ -1250,9 +1245,10 @@ class Options {
1250
1245
  setParameter('cookie', {
1251
1246
  'name': name,
1252
1247
  'value': value,
1253
- 'path': spec.path,
1254
- 'domain': spec.domain,
1255
- 'secure': !!spec.secure,
1248
+ 'path': path,
1249
+ 'domain': domain,
1250
+ 'secure': !!secure,
1251
+ 'httpOnly': !!httpOnly,
1256
1252
  'expiry': expiry
1257
1253
  }),
1258
1254
  'WebDriver.manage().addCookie(' + cookieString + ')');
@@ -1506,8 +1502,7 @@ Options.Cookie.prototype.httpOnly;
1506
1502
  * When the cookie expires.
1507
1503
  *
1508
1504
  * When {@linkplain Options#addCookie() adding a cookie}, this may be specified
1509
- * in _seconds_ since Unix epoch (January 1, 1970). The expiry will default to
1510
- * 20 years in the future if omitted.
1505
+ * as a {@link Date} object, or in _seconds_ since Unix epoch (January 1, 1970).
1511
1506
  *
1512
1507
  * The expiry is always returned in seconds since epoch when
1513
1508
  * {@linkplain Options#getCookies() retrieving cookies} from the browser.
@@ -2083,7 +2078,8 @@ class WebElement {
2083
2078
  command.Name.FIND_CHILD_ELEMENTS).
2084
2079
  setParameter('using', locator.using).
2085
2080
  setParameter('value', locator.value);
2086
- return this.schedule_(cmd, 'WebElement.findElements(' + locator + ')');
2081
+ return this.schedule_(cmd, 'WebElement.findElements(' + locator + ')')
2082
+ .then(result => Array.isArray(result) ? result : []);
2087
2083
  }
2088
2084
  }
2089
2085
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "selenium-webdriver",
3
- "version": "3.5.0",
3
+ "version": "3.6.0",
4
4
  "description": "The official WebDriver JavaScript bindings from the Selenium project",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
package/remote/index.js CHANGED
@@ -278,9 +278,10 @@ class DriverService {
278
278
  if (!this.address_ || !this.command_) {
279
279
  return Promise.resolve(); // Not currently running.
280
280
  }
281
- return this.command_.then(function(command) {
282
- command.kill('SIGTERM');
283
- });
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
  /**
@@ -52,6 +52,17 @@ test.suite(function(env) {
52
52
  }
53
53
  });
54
54
 
55
+ /**
56
+ * @param {...string} extensions the extensions to install.
57
+ * @return {!firefox.Profile} a new profile.
58
+ */
59
+ function profileWithExtensions(...extensions) {
60
+ let profile = new firefox.Profile();
61
+ profile.setPreference('xpinstall.signatures.required', false);
62
+ extensions.forEach(ext => profile.addExtension(ext));
63
+ return profile;
64
+ }
65
+
55
66
  /**
56
67
  * Runs a test that requires Firefox Developer Edition. The test will be
57
68
  * skipped if dev cannot be found on the current system.
@@ -99,9 +110,7 @@ test.suite(function(env) {
99
110
  });
100
111
 
101
112
  test.it('can start Firefox with a jetpack extension', function() {
102
- let profile = new firefox.Profile();
103
- profile.addExtension(JETPACK_EXTENSION);
104
-
113
+ let profile = profileWithExtensions(JETPACK_EXTENSION);
105
114
  let options = new firefox.Options().setProfile(profile);
106
115
 
107
116
  return runWithFirefoxDev(options, function*() {
@@ -115,9 +124,7 @@ test.suite(function(env) {
115
124
  });
116
125
 
117
126
  test.it('can start Firefox with a normal extension', function() {
118
- let profile = new firefox.Profile();
119
- profile.addExtension(NORMAL_EXTENSION);
120
-
127
+ let profile = profileWithExtensions(NORMAL_EXTENSION);
121
128
  let options = new firefox.Options().setProfile(profile);
122
129
 
123
130
  return runWithFirefoxDev(options, function*() {
@@ -131,9 +138,7 @@ test.suite(function(env) {
131
138
  });
132
139
 
133
140
  test.it('can start Firefox with a webextension extension', function() {
134
- let profile = new firefox.Profile();
135
- profile.addExtension(WEBEXTENSION_EXTENSION);
136
-
141
+ let profile = profileWithExtensions(WEBEXTENSION_EXTENSION);
137
142
  let options = new firefox.Options().setProfile(profile);
138
143
 
139
144
  return runWithFirefoxDev(options, function*() {
@@ -147,10 +152,8 @@ test.suite(function(env) {
147
152
  });
148
153
 
149
154
  test.it('can start Firefox with multiple extensions', function() {
150
- let profile = new firefox.Profile();
151
- profile.addExtension(JETPACK_EXTENSION);
152
- profile.addExtension(NORMAL_EXTENSION);
153
-
155
+ let profile =
156
+ profileWithExtensions(JETPACK_EXTENSION, NORMAL_EXTENSION);
154
157
  let options = new firefox.Options().setProfile(profile);
155
158
 
156
159
  return runWithFirefoxDev(options, function*() {
@@ -168,26 +171,6 @@ test.suite(function(env) {
168
171
  });
169
172
  });
170
173
 
171
- test.it('can be used alongside preset capabilities', function*() {
172
- let binary = yield firefox.Channel.AURORA.locate();
173
-
174
- let profile = new firefox.Profile();
175
- profile.addExtension(JETPACK_EXTENSION);
176
- profile.setPreference('general.useragent.override', 'foo;bar');
177
-
178
- driver = yield env.builder()
179
- .withCapabilities({'moz:firefoxOptions': {binary}})
180
- .setFirefoxOptions(new firefox.Options().setProfile(profile))
181
- .build();
182
-
183
- yield loadJetpackPage(driver,
184
- 'data:text/html;charset=UTF-8,<html><div>content</div></html>');
185
-
186
- let text =
187
- yield driver.findElement({id: 'jetpack-sample-banner'}).getText();
188
- assert(text).equalTo('Hello, world!');
189
- });
190
-
191
174
  function loadJetpackPage(driver, url) {
192
175
  // On linux the jetpack extension does not always run the first time
193
176
  // we load a page. If this happens, just reload the page (a simple
@@ -38,6 +38,7 @@ describe('error', function() {
38
38
  });
39
39
 
40
40
  test('unknown error', error.WebDriverError);
41
+ test('element not interactable', error.ElementNotInteractableError);
41
42
  test('element not selectable', error.ElementNotSelectableError);
42
43
  test('element not visible', error.ElementNotVisibleError);
43
44
  test('invalid argument', error.InvalidArgumentError);
package/testing/index.js CHANGED
@@ -41,7 +41,7 @@
41
41
  * The provided wrappers leverage the {@link webdriver.promise.ControlFlow}
42
42
  * to simplify writing asynchronous tests:
43
43
  *
44
- * var {Builder, By, until} = require('selenium-webdriver');
44
+ * var {Builder, By, Key, until} = require('selenium-webdriver');
45
45
  * var test = require('selenium-webdriver/testing');
46
46
  *
47
47
  * test.describe('Google Search', function() {
@@ -57,8 +57,7 @@
57
57
  *
58
58
  * test.it('should append query to title', function() {
59
59
  * driver.get('http://www.google.com/ncr');
60
- * driver.findElement(By.name('q')).sendKeys('webdriver');
61
- * driver.findElement(By.name('btnG')).click();
60
+ * driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN);
62
61
  * driver.wait(until.titleIs('webdriver - Google Search'), 1000);
63
62
  * });
64
63
  * });
@@ -1,70 +0,0 @@
1
- {
2
- "frozen": {
3
- "app.update.auto": false,
4
- "app.update.enabled": false,
5
- "browser.displayedE10SNotice": 4,
6
- "browser.download.manager.showWhenStarting": false,
7
- "browser.EULA.override": true,
8
- "browser.EULA.3.accepted": true,
9
- "browser.link.open_external": 2,
10
- "browser.link.open_newwindow": 2,
11
- "browser.offline": false,
12
- "browser.reader.detectedFirstArticle": true,
13
- "browser.safebrowsing.enabled": false,
14
- "browser.safebrowsing.malware.enabled": false,
15
- "browser.search.update": false,
16
- "browser.selfsupport.url" : "",
17
- "browser.sessionstore.resume_from_crash": false,
18
- "browser.shell.checkDefaultBrowser": false,
19
- "browser.tabs.warnOnClose": false,
20
- "browser.tabs.warnOnOpen": false,
21
- "datareporting.healthreport.service.enabled": false,
22
- "datareporting.healthreport.uploadEnabled": false,
23
- "datareporting.healthreport.service.firstRun": false,
24
- "datareporting.healthreport.logging.consoleEnabled": false,
25
- "datareporting.policy.dataSubmissionEnabled": false,
26
- "datareporting.policy.dataSubmissionPolicyAccepted": false,
27
- "devtools.errorconsole.enabled": true,
28
- "dom.disable_open_during_load": false,
29
- "extensions.autoDisableScopes": 10,
30
- "extensions.blocklist.enabled": false,
31
- "extensions.checkCompatibility.nightly": false,
32
- "extensions.logging.enabled": true,
33
- "extensions.update.enabled": false,
34
- "extensions.update.notifyUser": false,
35
- "javascript.enabled": true,
36
- "network.manage-offline-status": false,
37
- "network.http.phishy-userpass-length": 255,
38
- "offline-apps.allow_by_default": true,
39
- "prompts.tab_modal.enabled": false,
40
- "security.fileuri.origin_policy": 3,
41
- "security.fileuri.strict_origin_policy": false,
42
- "signon.rememberSignons": false,
43
- "toolkit.networkmanager.disable": true,
44
- "toolkit.telemetry.prompted": 2,
45
- "toolkit.telemetry.enabled": false,
46
- "toolkit.telemetry.rejected": true,
47
- "xpinstall.signatures.required": false,
48
- "xpinstall.whitelist.required": false
49
- },
50
- "mutable": {
51
- "browser.dom.window.dump.enabled": true,
52
- "browser.laterrun.enabled": false,
53
- "browser.newtab.url": "about:blank",
54
- "browser.newtabpage.enabled": false,
55
- "browser.startup.page": 0,
56
- "browser.startup.homepage": "about:blank",
57
- "browser.startup.homepage_override.mstone": "ignore",
58
- "browser.usedOnWindows10.introURL": "about:blank",
59
- "dom.max_chrome_script_run_time": 30,
60
- "dom.max_script_run_time": 30,
61
- "dom.report_all_js_exceptions": true,
62
- "javascript.options.showInConsole": true,
63
- "network.captive-portal-service.enabled": false,
64
- "security.csp.enable": false,
65
- "startup.homepage_welcome_url": "about:blank",
66
- "startup.homepage_welcome_url.additional": "about:blank",
67
- "webdriver_accept_untrusted_certs": true,
68
- "webdriver_assume_untrusted_issuer": true
69
- }
70
- }