selenium-webdriver 3.3.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 (117) hide show
  1. package/CHANGES.md +273 -0
  2. package/NOTICE +1 -1
  3. package/README.md +28 -36
  4. package/chrome.js +221 -146
  5. package/edge.js +43 -118
  6. package/example/chrome_android.js +8 -9
  7. package/example/chrome_mobile_emulation.js +9 -10
  8. package/example/firefox_channels.js +23 -19
  9. package/example/google_search.js +3 -3
  10. package/example/google_search_test.js +39 -27
  11. package/example/headless.js +55 -0
  12. package/example/logging.js +40 -7
  13. package/firefox.js +769 -0
  14. package/http/index.js +41 -4
  15. package/http/util.js +11 -6
  16. package/ie.js +57 -98
  17. package/index.js +182 -115
  18. package/io/index.js +59 -0
  19. package/io/zip.js +214 -0
  20. package/jasmine.json +11 -0
  21. package/lib/actions.js +68 -63
  22. package/lib/atoms/get-attribute.js +9 -0
  23. package/lib/atoms/is-displayed.js +73 -78
  24. package/lib/by.js +9 -1
  25. package/lib/capabilities.js +303 -201
  26. package/lib/command.js +28 -50
  27. package/lib/error.js +113 -42
  28. package/lib/http.js +167 -135
  29. package/lib/input.js +1044 -8
  30. package/lib/promise.js +222 -3331
  31. package/lib/proxy.js +134 -39
  32. package/lib/test/bootstrap_jasmine.js +28 -0
  33. package/lib/test/data/actions/click.html +24 -0
  34. package/lib/test/data/actions/drag.html +77 -0
  35. package/lib/test/data/actions/record_click.html +21 -0
  36. package/lib/test/data/chrome/download.html +2 -0
  37. package/lib/test/data/click_tests/disabled_element.html +12 -0
  38. package/lib/test/data/content-editable.html +10 -0
  39. package/lib/test/data/firefox/webextension.xpi +0 -0
  40. package/lib/test/data/inputs.html +42 -0
  41. package/lib/test/data/key_logger.html +34 -0
  42. package/lib/test/data/nestedElements.html +10 -1
  43. package/lib/test/data/scrolling_tests/page_with_partially_hidden_element.html +14 -0
  44. package/lib/test/data/selectPage.html +12 -0
  45. package/lib/test/data/simpleTest.html +5 -0
  46. package/lib/test/data/single_text_input.html +12 -0
  47. package/lib/test/data/upload_invisible.html +45 -0
  48. package/lib/test/fileserver.js +23 -19
  49. package/lib/test/index.js +30 -244
  50. package/lib/test/resources.js +0 -1
  51. package/lib/webdriver.js +770 -939
  52. package/net/index.js +21 -25
  53. package/net/portprober.js +51 -68
  54. package/package.json +6 -4
  55. package/remote/index.js +18 -30
  56. package/safari.js +42 -129
  57. package/test/actions_test.js +173 -18
  58. package/test/builder_test.js +106 -0
  59. package/test/chrome/devtools_test.js +93 -0
  60. package/test/chrome/options_test.js +48 -154
  61. package/test/chrome/service_test.js +7 -7
  62. package/test/cookie_test.js +77 -63
  63. package/test/element_finding_test.js +206 -201
  64. package/test/execute_script_test.js +115 -114
  65. package/test/fingerprint_test.js +16 -15
  66. package/test/firefox_test.js +251 -0
  67. package/test/http/http_test.js +18 -1
  68. package/test/http/util_test.js +2 -2
  69. package/test/{io_test.js → io/io_test.js} +40 -1
  70. package/test/io/zip_test.js +127 -0
  71. package/test/lib/by_test.js +21 -0
  72. package/test/lib/error_test.js +55 -8
  73. package/test/lib/http_test.js +18 -130
  74. package/test/lib/input_test.js +1379 -0
  75. package/test/lib/promise_test.js +473 -908
  76. package/test/lib/webdriver_test.js +357 -825
  77. package/test/logging_test.js +37 -43
  78. package/test/page_loading_test.js +70 -86
  79. package/test/proxy_test.js +64 -72
  80. package/test/rect_test.js +14 -25
  81. package/test/remote_test.js +13 -32
  82. package/test/safari_test.js +7 -71
  83. package/test/stale_element_test.js +20 -23
  84. package/test/tag_name_test.js +10 -9
  85. package/test/upload_test.js +27 -35
  86. package/test/window_test.js +72 -85
  87. package/testing/index.js +386 -315
  88. package/.npmignore +0 -2
  89. package/example/async_await_test.js +0 -68
  90. package/example/google_search_generator.js +0 -50
  91. package/example/parallel_flows.js +0 -54
  92. package/firefox/binary.js +0 -344
  93. package/firefox/extension.js +0 -187
  94. package/firefox/index.js +0 -722
  95. package/firefox/profile.js +0 -430
  96. package/lib/atoms/getAttribute.js +0 -12
  97. package/lib/events.js +0 -210
  98. package/lib/firefox/webdriver.json +0 -70
  99. package/lib/firefox/webdriver.xpi +0 -0
  100. package/lib/test/data/firefox/jetpack-sample.xpi +0 -0
  101. package/lib/test/data/firefox/sample.xpi +0 -0
  102. package/lib/test/promise.js +0 -79
  103. package/opera.js +0 -405
  104. package/phantomjs.js +0 -282
  105. package/test/firefox/extension_test.js +0 -96
  106. package/test/firefox/firefox_test.js +0 -226
  107. package/test/firefox/profile_test.js +0 -185
  108. package/test/lib/events_test.js +0 -177
  109. package/test/lib/promise_aplus_test.js +0 -78
  110. package/test/lib/promise_error_test.js +0 -884
  111. package/test/lib/promise_flow_test.js +0 -2288
  112. package/test/lib/promise_generator_test.js +0 -310
  113. package/test/phantomjs/execute_phantomjs_test.js +0 -59
  114. package/test/session_test.js +0 -54
  115. package/test/testing/assert_test.js +0 -373
  116. package/test/testing/index_test.js +0 -224
  117. package/testing/assert.js +0 -378
package/net/index.js CHANGED
@@ -17,11 +17,11 @@
17
17
 
18
18
  'use strict';
19
19
 
20
- var os = require('os');
20
+ const os = require('os');
21
21
 
22
22
 
23
23
  function getLoInterface() {
24
- var name;
24
+ let name;
25
25
  if (process.platform === 'darwin') {
26
26
  name = 'lo0';
27
27
  } else if (process.platform === 'linux') {
@@ -34,32 +34,28 @@ function getLoInterface() {
34
34
  /**
35
35
  * Queries the system network interfaces for an IP address.
36
36
  * @param {boolean} loopback Whether to find a loopback address.
37
- * @param {string=} opt_family The IP family (IPv4 or IPv6). Defaults to IPv4.
38
- * @return {string} The located IP address or undefined.
37
+ * @param {string} family The IP family (IPv4 or IPv6). Defaults to IPv4.
38
+ * @return {(string|undefined)} The located IP address or undefined.
39
39
  */
40
- function getAddress(loopback, opt_family) {
41
- var family = opt_family || 'IPv4';
42
- var addresses = [];
43
-
44
- var interfaces;
40
+ function getAddress(loopback, family) {
41
+ let interfaces;
45
42
  if (loopback) {
46
- var lo = getLoInterface();
43
+ let lo = getLoInterface();
47
44
  interfaces = lo ? [lo] : null;
48
45
  }
49
46
  interfaces = interfaces || os.networkInterfaces();
50
- for (var key in interfaces) {
47
+ for (let key in interfaces) {
51
48
  if (!interfaces.hasOwnProperty(key)) {
52
49
  continue;
53
50
  }
54
51
 
55
- interfaces[key].forEach(function(ipAddress) {
56
- if (ipAddress.family === family &&
57
- ipAddress.internal === loopback) {
58
- addresses.push(ipAddress.address);
52
+ for (let ipAddress of interfaces[key]) {
53
+ if (ipAddress.family === family && ipAddress.internal === loopback) {
54
+ return ipAddress.address;
59
55
  }
60
- });
56
+ }
61
57
  }
62
- return addresses[0];
58
+ return undefined;
63
59
  }
64
60
 
65
61
 
@@ -68,21 +64,21 @@ function getAddress(loopback, opt_family) {
68
64
 
69
65
  /**
70
66
  * Retrieves the external IP address for this host.
71
- * @param {string=} opt_family The IP family to retrieve. Defaults to "IPv4".
72
- * @return {string} The IP address or undefined if not available.
67
+ * @param {string=} family The IP family to retrieve. Defaults to "IPv4".
68
+ * @return {(string|undefined)} The IP address or undefined if not available.
73
69
  */
74
- exports.getAddress = function(opt_family) {
75
- return getAddress(false, opt_family);
70
+ exports.getAddress = function(family = 'IPv4') {
71
+ return getAddress(false, family);
76
72
  };
77
73
 
78
74
 
79
75
  /**
80
76
  * Retrieves a loopback address for this machine.
81
- * @param {string=} opt_family The IP family to retrieve. Defaults to "IPv4".
82
- * @return {string} The IP address or undefined if not available.
77
+ * @param {string=} family The IP family to retrieve. Defaults to "IPv4".
78
+ * @return {(string|undefined)} The IP address or undefined if not available.
83
79
  */
84
- exports.getLoopbackAddress = function(opt_family) {
85
- return getAddress(true, opt_family);
80
+ exports.getLoopbackAddress = function(family = 'IPv4') {
81
+ return getAddress(true, family);
86
82
  };
87
83
 
88
84
 
package/net/portprober.js CHANGED
@@ -17,9 +17,9 @@
17
17
 
18
18
  'use strict';
19
19
 
20
- var exec = require('child_process').exec,
21
- fs = require('fs'),
22
- net = require('net');
20
+ const fs = require('fs');
21
+ const net = require('net');
22
+ const {exec} = require('child_process');
23
23
 
24
24
 
25
25
  /**
@@ -34,9 +34,9 @@ const DEFAULT_IANA_RANGE = {min: 49152, max: 65535};
34
34
  /**
35
35
  * The epheremal port range for the current system. Lazily computed on first
36
36
  * access.
37
- * @type {Promise.<{min: number, max: number}>}
37
+ * @type {Promise<{min: number, max: number}>}
38
38
  */
39
- var systemRange = null;
39
+ let systemRange = null;
40
40
 
41
41
 
42
42
  /**
@@ -49,11 +49,10 @@ function findSystemPortRange() {
49
49
  if (systemRange) {
50
50
  return systemRange;
51
51
  }
52
- var range = process.platform === 'win32' ?
53
- findWindowsPortRange() : findUnixPortRange();
54
- return systemRange = range.catch(function() {
55
- return DEFAULT_IANA_RANGE;
56
- });
52
+ let range =
53
+ process.platform === 'win32'
54
+ ? findWindowsPortRange() : findUnixPortRange();
55
+ return systemRange = range.catch(() => DEFAULT_IANA_RANGE);
57
56
  }
58
57
 
59
58
 
@@ -81,7 +80,7 @@ function execute(cmd) {
81
80
  * @return {!Promise<{min: number, max: number}>} A promise that will resolve
82
81
  * with the ephemeral port range on the current system.
83
82
  */
84
- function findUnixPortRange() {
83
+ async function findUnixPortRange() {
85
84
  var cmd;
86
85
  if (process.platform === 'sunos') {
87
86
  cmd =
@@ -94,12 +93,17 @@ function findUnixPortRange() {
94
93
  ' | sed -e "s/.*:\\s*//"';
95
94
  }
96
95
 
97
- return execute(cmd).then(function(stdout) {
98
- if (!stdout || !stdout.length) return DEFAULT_IANA_RANGE;
99
- var range = stdout.trim().split(/\s+/).map(Number);
100
- if (range.some(isNaN)) return DEFAULT_IANA_RANGE;
101
- return {min: range[0], max: range[1]};
102
- });
96
+ let stdout = await execute(cmd);
97
+ if (!stdout || !stdout.length) {
98
+ return DEFAULT_IANA_RANGE;
99
+ };
100
+
101
+ let range = stdout.trim().split(/\s+/).map(Number);
102
+ if (range.some(isNaN)) {
103
+ return DEFAULT_IANA_RANGE;
104
+ };
105
+
106
+ return {min: range[0], max: range[1]};
103
107
  }
104
108
 
105
109
 
@@ -108,35 +112,29 @@ function findUnixPortRange() {
108
112
  * @return {!Promise<{min: number, max: number}>} A promise that will resolve
109
113
  * with the ephemeral port range on the current system.
110
114
  */
111
- function findWindowsPortRange() {
115
+ async function findWindowsPortRange() {
112
116
  // First, check if we're running on XP. If this initial command fails,
113
117
  // we just fallback on the default IANA range.
114
- return execute('cmd.exe /c ver').then(function(stdout) {
115
- if (/Windows XP/.test(stdout)) {
116
- // TODO: Try to read these values from the registry.
117
- return {min: 1025, max: 5000};
118
- } else {
119
- return execute('netsh int ipv4 show dynamicport tcp').
120
- then(function(stdout) {
121
- /* > netsh int ipv4 show dynamicport tcp
122
- Protocol tcp Dynamic Port Range
123
- ---------------------------------
124
- Start Port : 49152
125
- Number of Ports : 16384
126
- */
127
- var range = stdout.split(/\n/).filter(function(line) {
128
- return /.*:\s*\d+/.test(line);
129
- }).map(function(line) {
130
- return Number(line.split(/:\s*/)[1]);
131
- });
132
-
133
- return {
134
- min: range[0],
135
- max: range[0] + range[1]
136
- };
137
- });
138
- }
139
- });
118
+ let stdout = await execute('cmd.exe /c ver');
119
+ if (/Windows XP/.test(stdout)) {
120
+ // TODO: Try to read these values from the registry.
121
+ return {min: 1025, max: 5000};
122
+ } else {
123
+ stdout = await execute('netsh int ipv4 show dynamicport tcp');
124
+ /* > netsh int ipv4 show dynamicport tcp
125
+ Protocol tcp Dynamic Port Range
126
+ ---------------------------------
127
+ Start Port : 49152
128
+ Number of Ports : 16384
129
+ */
130
+ let range = stdout.split(/\n/)
131
+ .filter((line) => /.*:\s*\d+/.test(line))
132
+ .map((line) => Number(line.split(/:\s*/)[1]));
133
+ return {
134
+ min: range[0],
135
+ max: range[0] + range[1]
136
+ };
137
+ }
140
138
  }
141
139
 
142
140
 
@@ -171,30 +169,15 @@ function isFree(port, opt_host) {
171
169
  * @return {!Promise<number>} A promise that will resolve to a free port. If a
172
170
  * port cannot be found, the promise will be rejected.
173
171
  */
174
- function findFreePort(opt_host) {
175
- return findSystemPortRange().then(function(range) {
176
- var attempts = 0;
177
- return new Promise((resolve, reject) => {
178
- findPort();
179
-
180
- function findPort() {
181
- attempts += 1;
182
- if (attempts > 10) {
183
- reject(Error('Unable to find a free port'));
184
- }
185
-
186
- var port = Math.floor(
187
- Math.random() * (range.max - range.min) + range.min);
188
- isFree(port, opt_host).then(function(isFree) {
189
- if (isFree) {
190
- resolve(port);
191
- } else {
192
- findPort();
193
- }
194
- });
195
- }
196
- });
197
- });
172
+ async function findFreePort(opt_host) {
173
+ let range = await findSystemPortRange();
174
+ for (let i = 0; i < 100; i++) {
175
+ let port = Math.floor(Math.random() * (range.max - range.min) + range.min);
176
+ if (await isFree(port, opt_host)) {
177
+ return port;
178
+ }
179
+ }
180
+ throw Error('Unable to find a free port');
198
181
  }
199
182
 
200
183
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "selenium-webdriver",
3
- "version": "3.3.0",
3
+ "version": "4.0.0-alpha.1",
4
4
  "description": "The official WebDriver JavaScript bindings from the Selenium project",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -20,16 +20,17 @@
20
20
  "url": "https://github.com/SeleniumHQ/selenium.git"
21
21
  },
22
22
  "engines": {
23
- "node": ">= 6.9.0"
23
+ "node": ">= 8.9.0"
24
24
  },
25
25
  "dependencies": {
26
- "adm-zip": "^0.4.7",
26
+ "jszip": "^3.1.3",
27
27
  "rimraf": "^2.5.4",
28
28
  "tmp": "0.0.30",
29
29
  "xml2js": "^0.4.17"
30
30
  },
31
31
  "devDependencies": {
32
32
  "express": "^4.14.0",
33
+ "jasmine": "^2.8.0",
33
34
  "mocha": "^3.1.2",
34
35
  "multer": "^1.2.0",
35
36
  "promises-aplus-tests": "^2.1.2",
@@ -37,6 +38,7 @@
37
38
  "sinon": "^1.17.6"
38
39
  },
39
40
  "scripts": {
40
- "test": "mocha -t 600000 --recursive test"
41
+ "test": "mocha -t 600000 --recursive test",
42
+ "test-jasmine": "jasmine JASMINE_CONFIG_PATH=jasmine.json"
41
43
  }
42
44
  }
package/remote/index.js CHANGED
@@ -17,7 +17,6 @@
17
17
 
18
18
  'use strict';
19
19
 
20
- const AdmZip = require('adm-zip');
21
20
  const fs = require('fs');
22
21
  const path = require('path');
23
22
  const url = require('url');
@@ -26,9 +25,9 @@ const util = require('util');
26
25
  const httpUtil = require('../http/util');
27
26
  const io = require('../io');
28
27
  const exec = require('../io/exec');
28
+ const {Zip} = require('../io/zip');
29
29
  const cmd = require('../lib/command');
30
30
  const input = require('../lib/input');
31
- const promise = require('../lib/promise');
32
31
  const webdriver = require('../lib/webdriver');
33
32
  const net = require('../net');
34
33
  const portprober = require('../net/portprober');
@@ -253,7 +252,7 @@ class DriverService {
253
252
 
254
253
  httpUtil.waitForServer(serverUrl, timeout, cancelToken)
255
254
  .then(_ => fulfill(serverUrl), err => {
256
- if (err instanceof promise.CancellationError) {
255
+ if (err instanceof httpUtil.CancellationError) {
257
256
  fulfill(serverUrl);
258
257
  } else {
259
258
  reject(err);
@@ -278,19 +277,10 @@ class DriverService {
278
277
  if (!this.address_ || !this.command_) {
279
278
  return Promise.resolve(); // Not currently running.
280
279
  }
281
- return this.command_.then(function(command) {
282
- command.kill('SIGTERM');
283
- });
284
- }
285
-
286
- /**
287
- * Schedules a task in the current control flow to stop the server if it is
288
- * currently running.
289
- * @return {!promise.Thenable} A promise that will be resolved when
290
- * the server has been stopped.
291
- */
292
- stop() {
293
- return promise.controlFlow().execute(this.kill.bind(this));
280
+ let cmd = this.command_;
281
+ this.address_ = null;
282
+ this.command_ = null;
283
+ return cmd.then(c => c.kill('SIGTERM'));
294
284
  }
295
285
  }
296
286
 
@@ -528,11 +518,9 @@ class SeleniumServer extends DriverService {
528
518
  *
529
519
  * @typedef {{
530
520
  * loopback: (boolean|undefined),
531
- * port: (number|!promise.Promise<number>),
532
- * args: !(Array<string>|promise.Promise<!Array<string>>),
533
- * jvmArgs: (!Array<string>|
534
- * !promise.Promise<!Array<string>>|
535
- * undefined),
521
+ * port: (number|!IThenable<number>),
522
+ * args: !(Array<string>|IThenable<!Array<string>>),
523
+ * jvmArgs: (!Array<string>|!IThenable<!Array<string>>|undefined),
536
524
  * env: (!Object<string, string>|undefined),
537
525
  * stdio: (string|!Array<string|number|!stream.Stream|null|undefined>|
538
526
  * undefined)
@@ -575,15 +563,15 @@ class FileDetector extends input.FileDetector {
575
563
  return file; // Not a valid file, return original input.
576
564
  }
577
565
 
578
- var zip = new AdmZip();
579
- zip.addLocalFile(file);
580
- // Stored compression, see https://en.wikipedia.org/wiki/Zip_(file_format)
581
- zip.getEntries()[0].header.method = 0;
582
-
583
- var command = new cmd.Command(cmd.Name.UPLOAD_FILE)
584
- .setParameter('file', zip.toBuffer().toString('base64'));
585
- return driver.schedule(command,
586
- 'remote.FileDetector.handleFile(' + file + ')');
566
+ let zip = new Zip;
567
+ return zip.addFile(file)
568
+ .then(() => zip.toBuffer())
569
+ .then(buf => buf.toString('base64'))
570
+ .then(encodedZip => {
571
+ let command = new cmd.Command(cmd.Name.UPLOAD_FILE)
572
+ .setParameter('file', encodedZip);
573
+ return driver.execute(command);
574
+ });
587
575
  }, function(err) {
588
576
  if (err.code === 'ENOENT') {
589
577
  return file; // Not a file; return original input.
package/safari.js CHANGED
@@ -21,17 +21,28 @@
21
21
 
22
22
  'use strict';
23
23
 
24
- const http = require('./http');
25
- const io = require('./io');
26
- const {Capabilities, Capability} = require('./lib/capabilities');
27
24
  const command = require('./lib/command');
28
25
  const error = require('./lib/error');
29
- const logging = require('./lib/logging');
26
+ const http = require('./http');
27
+ const io = require('./io');
28
+ const portprober = require('./net/portprober');
30
29
  const promise = require('./lib/promise');
30
+ const remote = require('./remote');
31
31
  const Symbols = require('./lib/symbols');
32
32
  const webdriver = require('./lib/webdriver');
33
- const portprober = require('./net/portprober');
34
- const remote = require('./remote');
33
+ const {Browser, Capabilities, Capability} = require('./lib/capabilities');
34
+
35
+
36
+ /**
37
+ * _Synchronously_ attempts to locate the IE driver executable on the current
38
+ * system.
39
+ *
40
+ * @return {?string} the located executable, or `null`.
41
+ */
42
+ function locateSynchronously() {
43
+ return process.platform === 'darwin'
44
+ ? io.findInPath('safaridriver', true) : null;
45
+ }
35
46
 
36
47
 
37
48
  /**
@@ -39,7 +50,7 @@ const remote = require('./remote');
39
50
  * @throws {Error}
40
51
  */
41
52
  function findSafariDriver() {
42
- let exe = io.findInPath('safaridriver', true);
53
+ let exe = locateSynchronously();
43
54
  if (!exe) {
44
55
  throw Error(
45
56
  `The safaridriver executable could not be found on the current PATH.
@@ -73,80 +84,19 @@ const TECHNOLOGY_PREVIEW_OPTIONS_KEY = 'technologyPreview';
73
84
  /**
74
85
  * Configuration options specific to the {@link Driver SafariDriver}.
75
86
  */
76
- class Options {
77
- constructor() {
78
- /** @private {Object<string, *>} */
79
- this.options_ = null;
80
-
81
- /** @private {./lib/logging.Preferences} */
82
- this.logPrefs_ = null;
83
-
84
- /** @private {?./lib/capabilities.ProxyConfig} */
85
- this.proxy_ = null;
86
- }
87
-
87
+ class Options extends Capabilities {
88
88
  /**
89
- * Extracts the SafariDriver specific options from the given capabilities
90
- * object.
91
- * @param {!Capabilities} capabilities The capabilities object.
92
- * @return {!Options} The SafariDriver options.
93
- */
94
- static fromCapabilities(capabilities) {
95
- var options = new Options();
96
- var o = capabilities.get(OPTIONS_CAPABILITY_KEY);
97
-
98
- if (o instanceof Options) {
99
- options = o;
100
- } else if (o) {
101
- options.setCleanSession(o.cleanSession);
102
- options.setTechnologyPreview(o[TECHNOLOGY_PREVIEW_OPTIONS_KEY]);
103
- }
104
-
105
- if (capabilities.has(Capability.PROXY)) {
106
- options.setProxy(capabilities.get(Capability.PROXY));
107
- }
108
-
109
- if (capabilities.has(Capability.LOGGING_PREFS)) {
110
- options.setLoggingPrefs(capabilities.get(Capability.LOGGING_PREFS));
111
- }
112
-
113
- return options;
114
- }
115
-
116
- /**
117
- * Sets whether to force Safari to start with a clean session. Enabling this
118
- * option will cause all global browser data to be deleted.
119
- * @param {boolean} clean Whether to make sure the session has no cookies,
120
- * cache entries, local storage, or databases.
121
- * @return {!Options} A self reference.
89
+ * @param {(Capabilities|Map<string, ?>|Object)=} other Another set of
90
+ * capabilities to initialize this instance from.
122
91
  */
123
- setCleanSession(clean) {
124
- if (!this.options_) {
125
- this.options_ = {};
126
- }
127
- this.options_['cleanSession'] = clean;
128
- return this;
129
- }
92
+ constructor(other = undefined) {
93
+ super(other);
130
94
 
131
- /**
132
- * Sets the logging preferences for the new session.
133
- * @param {!./lib/logging.Preferences} prefs The logging preferences.
134
- * @return {!Options} A self reference.
135
- */
136
- setLoggingPrefs(prefs) {
137
- this.logPrefs_ = prefs;
138
- return this;
139
- }
95
+ /** @private {!Object} */
96
+ this.options_ = this.get(OPTIONS_CAPABILITY_KEY) || {};
140
97
 
141
- /**
142
- * Sets the proxy to use.
143
- *
144
- * @param {./lib/capabilities.ProxyConfig} proxy The proxy configuration to use.
145
- * @return {!Options} A self reference.
146
- */
147
- setProxy(proxy) {
148
- this.proxy_ = proxy;
149
- return this;
98
+ this.set(OPTIONS_CAPABILITY_KEY, this.options_);
99
+ this.setBrowserName(Browser.SAFARI);
150
100
  }
151
101
 
152
102
  /**
@@ -157,52 +107,19 @@ class Options {
157
107
  * @return {!Options} A self reference.
158
108
  */
159
109
  setTechnologyPreview(useTechnologyPreview) {
160
- if (!this.options_) {
161
- this.options_ = {};
162
- }
163
-
164
110
  this.options_[TECHNOLOGY_PREVIEW_OPTIONS_KEY] = !!useTechnologyPreview;
165
111
  return this;
166
112
  }
167
-
168
- /**
169
- * Converts this options instance to a {@link Capabilities} object.
170
- * @param {Capabilities=} opt_capabilities The capabilities to
171
- * merge these options into, if any.
172
- * @return {!Capabilities} The capabilities.
173
- */
174
- toCapabilities(opt_capabilities) {
175
- var caps = opt_capabilities || Capabilities.safari();
176
- if (this.logPrefs_) {
177
- caps.set(Capability.LOGGING_PREFS, this.logPrefs_);
178
- }
179
- if (this.proxy_) {
180
- caps.set(Capability.PROXY, this.proxy_);
181
- }
182
- if (this.options_) {
183
- caps.set(OPTIONS_CAPABILITY_KEY, this);
184
- }
185
- return caps;
186
- }
187
-
188
- /**
189
- * Converts this instance to its JSON wire protocol representation. Note this
190
- * function is an implementation detail not intended for general use.
191
- * @return {!Object<string, *>} The JSON wire protocol representation of this
192
- * instance.
193
- */
194
- [Symbols.serialize]() {
195
- return this.options_ || {};
196
- }
197
113
  }
198
114
 
199
115
  /**
200
- * @param {(Options|Object<string, *>)=} o The options object
116
+ * @param {(Capabilities|Object<string, *>)=} o The options object
201
117
  * @return {boolean}
202
118
  */
203
119
  function useTechnologyPreview(o) {
204
- if (o instanceof Options) {
205
- return !!(o.options_ && o.options_[TECHNOLOGY_PREVIEW_OPTIONS_KEY]);
120
+ if (o instanceof Capabilities) {
121
+ let options = o.get(OPTIONS_CAPABILITY_KEY);
122
+ return !!(options && options[TECHNOLOGY_PREVIEW_OPTIONS_KEY]);
206
123
  }
207
124
 
208
125
  if (o && typeof o === 'object') {
@@ -212,7 +129,10 @@ function useTechnologyPreview(o) {
212
129
  return false;
213
130
  }
214
131
 
215
- const SAFARIDRIVER_TECHNOLOGY_PREVIEW_EXE = '/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver';
132
+
133
+ const SAFARIDRIVER_TECHNOLOGY_PREVIEW_EXE =
134
+ '/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver';
135
+
216
136
 
217
137
  /**
218
138
  * A WebDriver client for Safari. This class should never be instantiated
@@ -227,21 +147,13 @@ class Driver extends webdriver.WebDriver {
227
147
  /**
228
148
  * Creates a new Safari session.
229
149
  *
230
- * @param {(Options|Capabilities)=} opt_config The configuration
231
- * options for the new session.
232
- * @param {promise.ControlFlow=} opt_flow The control flow to create
233
- * the driver under.
150
+ * @param {(Options|Capabilities)=} options The configuration options.
234
151
  * @return {!Driver} A new driver instance.
235
152
  */
236
- static createSession(opt_config, opt_flow) {
237
- let caps, exe;
238
-
239
- if (opt_config instanceof Options) {
240
- caps = opt_config.toCapabilities();
241
- } else {
242
- caps = opt_config || Capabilities.safari();
243
- }
153
+ static createSession(options) {
154
+ let caps = options || new Options();
244
155
 
156
+ let exe;
245
157
  if (useTechnologyPreview(caps.get(OPTIONS_CAPABILITY_KEY))) {
246
158
  exe = SAFARIDRIVER_TECHNOLOGY_PREVIEW_EXE;
247
159
  }
@@ -250,8 +162,8 @@ class Driver extends webdriver.WebDriver {
250
162
  let executor = new http.Executor(
251
163
  service.start().then(url => new http.HttpClient(url)));
252
164
 
253
- return /** @type {!Driver} */(webdriver.WebDriver.createSession(
254
- executor, caps, opt_flow, this, () => service.kill()));
165
+ return /** @type {!Driver} */(super.createSession(
166
+ executor, caps, () => service.kill()));
255
167
  }
256
168
  }
257
169
 
@@ -262,3 +174,4 @@ class Driver extends webdriver.WebDriver {
262
174
  exports.Driver = Driver;
263
175
  exports.Options = Options;
264
176
  exports.ServiceBuilder = ServiceBuilder;
177
+ exports.locateSynchronously = locateSynchronously;