selenium-webdriver 4.0.0-alpha.3 → 4.0.0-alpha.7

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 (79) hide show
  1. package/CHANGES.md +9 -2
  2. package/README.md +2 -4
  3. package/chrome.js +19 -527
  4. package/chromium.js +762 -0
  5. package/edge.js +97 -58
  6. package/firefox.js +23 -5
  7. package/http/index.js +4 -0
  8. package/io/index.js +1 -1
  9. package/lib/actions.js +1 -1
  10. package/lib/atoms/get-attribute.js +1 -2
  11. package/lib/atoms/is-displayed.js +5 -6
  12. package/lib/atoms/make-atoms-module.js +17 -0
  13. package/lib/capabilities.js +17 -4
  14. package/lib/command.js +1 -0
  15. package/lib/http.js +8 -3
  16. package/lib/input.js +6 -6
  17. package/lib/logging.js +1 -1
  18. package/lib/webdriver.js +33 -3
  19. package/net/portprober.js +1 -1
  20. package/package.json +8 -9
  21. package/BUILD.bazel +0 -88
  22. package/example/chrome_android.js +0 -42
  23. package/example/chrome_mobile_emulation.js +0 -42
  24. package/example/firefox_channels.js +0 -77
  25. package/example/google_search.js +0 -50
  26. package/example/google_search_test.js +0 -72
  27. package/example/headless.js +0 -55
  28. package/example/logging.js +0 -68
  29. package/jasmine.json +0 -11
  30. package/lib/atoms/BUILD.bazel +0 -28
  31. package/lib/test/bootstrap_jasmine.js +0 -28
  32. package/lib/test/build.js +0 -156
  33. package/lib/test/data/actions/click.html +0 -24
  34. package/lib/test/data/actions/drag.html +0 -77
  35. package/lib/test/data/actions/record_click.html +0 -21
  36. package/lib/test/data/chrome/download.html +0 -2
  37. package/lib/test/data/firefox/webextension.xpi +0 -0
  38. package/lib/test/fileserver.js +0 -337
  39. package/lib/test/httpserver.js +0 -120
  40. package/lib/test/index.js +0 -87
  41. package/lib/test/resources.js +0 -40
  42. package/test/actions_test.js +0 -206
  43. package/test/builder_test.js +0 -106
  44. package/test/chrome/devtools_test.js +0 -93
  45. package/test/chrome/options_test.js +0 -121
  46. package/test/chrome/service_test.js +0 -45
  47. package/test/cookie_test.js +0 -210
  48. package/test/element_finding_test.js +0 -431
  49. package/test/execute_script_test.js +0 -355
  50. package/test/fingerprint_test.js +0 -63
  51. package/test/firefox_test.js +0 -233
  52. package/test/frame_test.js +0 -45
  53. package/test/http/http_test.js +0 -229
  54. package/test/http/util_test.js +0 -178
  55. package/test/io/io_test.js +0 -364
  56. package/test/io/zip_test.js +0 -126
  57. package/test/lib/by_test.js +0 -160
  58. package/test/lib/capabilities_test.js +0 -129
  59. package/test/lib/error_test.js +0 -333
  60. package/test/lib/http_test.js +0 -576
  61. package/test/lib/input_test.js +0 -1379
  62. package/test/lib/logging_test.js +0 -272
  63. package/test/lib/promise_test.js +0 -674
  64. package/test/lib/testutil.js +0 -90
  65. package/test/lib/until_test.js +0 -478
  66. package/test/lib/webdriver_test.js +0 -1692
  67. package/test/logging_test.js +0 -160
  68. package/test/net/index_test.js +0 -60
  69. package/test/net/portprober_test.js +0 -128
  70. package/test/page_loading_test.js +0 -156
  71. package/test/proxy_test.js +0 -167
  72. package/test/rect_test.js +0 -51
  73. package/test/remote_test.js +0 -98
  74. package/test/safari_test.js +0 -44
  75. package/test/stale_element_test.js +0 -60
  76. package/test/upload_test.js +0 -78
  77. package/test/window_test.js +0 -168
  78. package/testing/index.js +0 -498
  79. package/tools/init_jasmine.js +0 -7
package/chromium.js ADDED
@@ -0,0 +1,762 @@
1
+ // Licensed to the Software Freedom Conservancy (SFC) under one
2
+ // or more contributor license agreements. See the NOTICE file
3
+ // distributed with this work for additional information
4
+ // regarding copyright ownership. The SFC licenses this file
5
+ // to you under the Apache License, Version 2.0 (the
6
+ // "License"); you may not use this file except in compliance
7
+ // with the License. You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing,
12
+ // software distributed under the License is distributed on an
13
+ // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ // KIND, either express or implied. See the License for the
15
+ // specific language governing permissions and limitations
16
+ // under the License.
17
+
18
+ /**
19
+ * @fileoverview Defines an abstract {@linkplain Driver WebDriver} client for
20
+ * Chromium-based web browsers. These classes should not be instantiated
21
+ * directly.
22
+ *
23
+ * There are three primary classes exported by this module:
24
+ *
25
+ * 1. {@linkplain ServiceBuilder}: configures the
26
+ * {@link selenium-webdriver/remote.DriverService remote.DriverService}
27
+ * that manages a WebDriver server child process.
28
+ *
29
+ * 2. {@linkplain Options}: defines configuration options for each new Chromium
30
+ * session, such as which {@linkplain Options#setProxy proxy} to use,
31
+ * what {@linkplain Options#addExtensions extensions} to install, or
32
+ * what {@linkplain Options#addArguments command-line switches} to use when
33
+ * starting the browser.
34
+ *
35
+ * 3. {@linkplain Driver}: the WebDriver client; each new instance will control
36
+ * a unique browser session with a clean user profile (unless otherwise
37
+ * configured through the {@link Options} class).
38
+ *
39
+ * __Headless Chromium__ <a id="headless"></a>
40
+ *
41
+ * To start the browser in headless mode, simply call
42
+ * {@linkplain Options#headless Options.headless()}.
43
+ *
44
+ * let chrome = require('selenium-webdriver/chrome');
45
+ * let {Builder} = require('selenium-webdriver');
46
+ *
47
+ * let driver = new Builder()
48
+ * .forBrowser('chrome')
49
+ * .setChromeOptions(new chrome.Options().headless())
50
+ * .build();
51
+ *
52
+ * __Customizing the Chromium WebDriver Server__ <a id="custom-server"></a>
53
+ *
54
+ * Subclasses of {@link Driver} are expected to provide a static
55
+ * getDefaultService method. By default, this method will be called every time
56
+ * a {@link Driver} instance is created to obtain the default driver service
57
+ * for that specific browser (e.g. Chrome or Chromium Edge). Subclasses are
58
+ * responsible for managing the lifetime of the default service.
59
+ *
60
+ * You may also create a {@link Driver} with its own driver service. This is
61
+ * useful if you need to capture the server's log output for a specific session:
62
+ *
63
+ * let chrome = require('selenium-webdriver/chrome');
64
+ *
65
+ * let service = new chrome.ServiceBuilder()
66
+ * .loggingTo('/my/log/file.txt')
67
+ * .enableVerboseLogging()
68
+ * .build();
69
+ *
70
+ * let options = new chrome.Options();
71
+ * // configure browser options ...
72
+ *
73
+ * let driver = chrome.Driver.createSession(options, service);
74
+ */
75
+
76
+ 'use strict';
77
+
78
+ const http = require('./http');
79
+ const io = require('./io');
80
+ const {Capabilities, Capability} = require('./lib/capabilities');
81
+ const command = require('./lib/command');
82
+ const error = require('./lib/error');
83
+ const promise = require('./lib/promise');
84
+ const Symbols = require('./lib/symbols');
85
+ const webdriver = require('./lib/webdriver');
86
+ const remote = require('./remote');
87
+
88
+
89
+ /**
90
+ * Custom command names supported by Chromium WebDriver.
91
+ * @enum {string}
92
+ */
93
+ const Command = {
94
+ LAUNCH_APP: 'launchApp',
95
+ GET_NETWORK_CONDITIONS: 'getNetworkConditions',
96
+ SET_NETWORK_CONDITIONS: 'setNetworkConditions',
97
+ SEND_DEVTOOLS_COMMAND: 'sendDevToolsCommand',
98
+ GET_CAST_SINKS: 'getCastSinks',
99
+ SET_CAST_SINK_TO_USE: 'setCastSinkToUse',
100
+ START_CAST_TAB_MIRRORING: 'setCastTabMirroring',
101
+ GET_CAST_ISSUE_MESSAGE: 'getCastIssueMessage',
102
+ STOP_CASTING: 'stopCasting',
103
+ };
104
+
105
+
106
+ /**
107
+ * Creates a command executor with support for Chromium's custom commands.
108
+ * @param {!Promise<string>} url The server's URL.
109
+ * @return {!command.Executor} The new command executor.
110
+ */
111
+ function createExecutor(url, vendorPrefix) {
112
+ let agent = new http.Agent({ keepAlive: true });
113
+ let client = url.then(url => new http.HttpClient(url, agent));
114
+ let executor = new http.Executor(client);
115
+ configureExecutor(executor, vendorPrefix);
116
+ return executor;
117
+ }
118
+
119
+
120
+ /**
121
+ * Configures the given executor with Chromium-specific commands.
122
+ * @param {!http.Executor} executor the executor to configure.
123
+ */
124
+ function configureExecutor(executor, vendorPrefix) {
125
+ executor.defineCommand(
126
+ Command.LAUNCH_APP,
127
+ 'POST',
128
+ '/session/:sessionId/chromium/launch_app');
129
+ executor.defineCommand(
130
+ Command.GET_NETWORK_CONDITIONS,
131
+ 'GET',
132
+ '/session/:sessionId/chromium/network_conditions');
133
+ executor.defineCommand(
134
+ Command.SET_NETWORK_CONDITIONS,
135
+ 'POST',
136
+ '/session/:sessionId/chromium/network_conditions');
137
+ executor.defineCommand(
138
+ Command.SEND_DEVTOOLS_COMMAND,
139
+ 'POST',
140
+ '/session/:sessionId/chromium/send_command');
141
+ executor.defineCommand(
142
+ Command.GET_CAST_SINKS,
143
+ 'GET',
144
+ `/session/:sessionId/${vendorPrefix}/cast/get_sinks`);
145
+ executor.defineCommand(
146
+ Command.SET_CAST_SINK_TO_USE,
147
+ 'POST',
148
+ `/session/:sessionId/${vendorPrefix}/cast/set_sink_to_use`);
149
+ executor.defineCommand(
150
+ Command.START_CAST_TAB_MIRRORING,
151
+ 'POST',
152
+ `/session/:sessionId/${vendorPrefix}/cast/start_tab_mirroring`);
153
+ executor.defineCommand(
154
+ Command.GET_CAST_ISSUE_MESSAGE,
155
+ 'GET',
156
+ `/session/:sessionId/${vendorPrefix}/cast/get_issue_message`);
157
+ executor.defineCommand(
158
+ Command.STOP_CASTING,
159
+ 'POST',
160
+ `/session/:sessionId/${vendorPrefix}/cast/stop_casting`);
161
+ }
162
+
163
+
164
+ /**
165
+ * Creates {@link selenium-webdriver/remote.DriverService} instances that manage
166
+ * a WebDriver server in a child process.
167
+ */
168
+ class ServiceBuilder extends remote.DriverService.Builder {
169
+ /**
170
+ * @param {string=} exe Path to the server executable to use. Subclasses
171
+ * should ensure a valid path to the appropriate exe is provided.
172
+ */
173
+ constructor(exe) {
174
+ super(exe);
175
+ this.setLoopback(true); // Required
176
+ }
177
+
178
+ /**
179
+ * Sets which port adb is listening to. _The driver will connect to adb
180
+ * if an {@linkplain Options#androidPackage Android session} is requested, but
181
+ * adb **must** be started beforehand._
182
+ *
183
+ * @param {number} port Which port adb is running on.
184
+ * @return {!ServiceBuilder} A self reference.
185
+ */
186
+ setAdbPort(port) {
187
+ return this.addArguments('--adb-port=' + port);
188
+ }
189
+
190
+ /**
191
+ * Sets the path of the log file the driver should log to. If a log file is
192
+ * not specified, the driver will log to stderr.
193
+ * @param {string} path Path of the log file to use.
194
+ * @return {!ServiceBuilder} A self reference.
195
+ */
196
+ loggingTo(path) {
197
+ return this.addArguments('--log-path=' + path);
198
+ }
199
+
200
+ /**
201
+ * Enables verbose logging.
202
+ * @return {!ServiceBuilder} A self reference.
203
+ */
204
+ enableVerboseLogging() {
205
+ return this.addArguments('--verbose');
206
+ }
207
+
208
+ /**
209
+ * Sets the number of threads the driver should use to manage HTTP requests.
210
+ * By default, the driver will use 4 threads.
211
+ * @param {number} n The number of threads to use.
212
+ * @return {!ServiceBuilder} A self reference.
213
+ */
214
+ setNumHttpThreads(n) {
215
+ return this.addArguments('--http-threads=' + n);
216
+ }
217
+
218
+ /**
219
+ * @override
220
+ */
221
+ setPath(path) {
222
+ super.setPath(path);
223
+ return this.addArguments('--url-base=' + path);
224
+ }
225
+ }
226
+
227
+
228
+ /**
229
+ * Class for managing WebDriver options specific to a Chromium-based browser.
230
+ */
231
+ class Options extends Capabilities {
232
+ /**
233
+ * @param {(Capabilities|Map<string, ?>|Object)=} other Another set of
234
+ * capabilities to initialize this instance from.
235
+ */
236
+ constructor(other = undefined) {
237
+ super(other);
238
+
239
+ /** @private {!Object} */
240
+ this.options_ = this.get(this.CAPABILITY_KEY) || {};
241
+
242
+ this.setBrowserName(this.BROWSER_NAME_VALUE);
243
+ this.set(this.CAPABILITY_KEY, this.options_);
244
+ }
245
+
246
+ /**
247
+ * Add additional command line arguments to use when launching the browser.
248
+ * Each argument may be specified with or without the "--" prefix
249
+ * (e.g. "--foo" and "foo"). Arguments with an associated value should be
250
+ * delimited by an "=": "foo=bar".
251
+ *
252
+ * @param {...(string|!Array<string>)} args The arguments to add.
253
+ * @return {!Options} A self reference.
254
+ */
255
+ addArguments(...args) {
256
+ let newArgs = (this.options_.args || []).concat(...args);
257
+ if (newArgs.length) {
258
+ this.options_.args = newArgs;
259
+ }
260
+ return this;
261
+ }
262
+
263
+ /**
264
+ * Configures the driver to start the browser in headless mode.
265
+ *
266
+ * > __NOTE:__ Resizing the browser window in headless mode is only supported
267
+ * > in Chromium 60+. Users are encouraged to set an initial window size with
268
+ * > the {@link #windowSize windowSize({width, height})} option.
269
+ *
270
+ * > __NOTE__: For security, Chromium disables downloads by default when
271
+ * > in headless mode (to prevent sites from silently downloading files to
272
+ * > your machine). After creating a session, you may call
273
+ * > {@link ./chrome.Driver#setDownloadPath setDownloadPath} to re-enable
274
+ * > downloads, saving files in the specified directory.
275
+ *
276
+ * @return {!Options} A self reference.
277
+ */
278
+ headless() {
279
+ return this.addArguments('headless');
280
+ }
281
+
282
+ /**
283
+ * Sets the initial window size.
284
+ *
285
+ * @param {{width: number, height: number}} size The desired window size.
286
+ * @return {!Options} A self reference.
287
+ * @throws {TypeError} if width or height is unspecified, not a number, or
288
+ * less than or equal to 0.
289
+ */
290
+ windowSize({width, height}) {
291
+ function checkArg(arg) {
292
+ if (typeof arg !== 'number' || arg <= 0) {
293
+ throw TypeError('Arguments must be {width, height} with numbers > 0');
294
+ }
295
+ }
296
+ checkArg(width);
297
+ checkArg(height);
298
+ return this.addArguments(`window-size=${width},${height}`);
299
+ }
300
+
301
+ /**
302
+ * List of Chrome command line switches to exclude that ChromeDriver by default
303
+ * passes when starting Chrome. Do not prefix switches with "--".
304
+ *
305
+ * @param {...(string|!Array<string>)} args The switches to exclude.
306
+ * @return {!Options} A self reference.
307
+ */
308
+ excludeSwitches(...args) {
309
+ let switches = (this.options_.excludeSwitches || []).concat(...args);
310
+ if (switches.length) {
311
+ this.options_.excludeSwitches = switches;
312
+ }
313
+ return this;
314
+ }
315
+
316
+ /**
317
+ * Add additional extensions to install when launching the browser. Each extension
318
+ * should be specified as the path to the packed CRX file, or a Buffer for an
319
+ * extension.
320
+ * @param {...(string|!Buffer|!Array<(string|!Buffer)>)} args The
321
+ * extensions to add.
322
+ * @return {!Options} A self reference.
323
+ */
324
+ addExtensions(...args) {
325
+ let current = this.options_.extensions || [];
326
+ this.options_.extensions = current.concat(...args);
327
+ return this;
328
+ }
329
+
330
+ /**
331
+ * Sets the path to the browser binary to use. On Mac OS X, this path should
332
+ * reference the actual Chromium executable, not just the application binary
333
+ * (e.g. "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome").
334
+ *
335
+ * The binary path can be absolute or relative to the WebDriver server
336
+ * executable, but it must exist on the machine that will launch the browser.
337
+ *
338
+ * @param {string} path The path to the browser binary to use.
339
+ * @return {!Options} A self reference.
340
+ */
341
+ setBinaryPath(path) {
342
+ this.options_.binary = path;
343
+ return this;
344
+ }
345
+
346
+ /**
347
+ * Sets whether to leave the started browser process running if the controlling
348
+ * driver service is killed before {@link webdriver.WebDriver#quit()} is
349
+ * called.
350
+ * @param {boolean} detach Whether to leave the browser running if the
351
+ * driver service is killed before the session.
352
+ * @return {!Options} A self reference.
353
+ */
354
+ detachDriver(detach) {
355
+ this.options_.detach = detach;
356
+ return this;
357
+ }
358
+
359
+ /**
360
+ * Sets the user preferences for Chrome's user profile. See the "Preferences"
361
+ * file in Chrome's user data directory for examples.
362
+ * @param {!Object} prefs Dictionary of user preferences to use.
363
+ * @return {!Options} A self reference.
364
+ */
365
+ setUserPreferences(prefs) {
366
+ this.options_.prefs = prefs;
367
+ return this;
368
+ }
369
+
370
+ /**
371
+ * Sets the performance logging preferences. Options include:
372
+ *
373
+ * - `enableNetwork`: Whether or not to collect events from Network domain.
374
+ * - `enablePage`: Whether or not to collect events from Page domain.
375
+ * - `enableTimeline`: Whether or not to collect events from Timeline domain.
376
+ * Note: when tracing is enabled, Timeline domain is implicitly disabled,
377
+ * unless `enableTimeline` is explicitly set to true.
378
+ * - `tracingCategories`: A comma-separated string of Chromium tracing
379
+ * categories for which trace events should be collected. An unspecified
380
+ * or empty string disables tracing.
381
+ * - `bufferUsageReportingInterval`: The requested number of milliseconds
382
+ * between DevTools trace buffer usage events. For example, if 1000, then
383
+ * once per second, DevTools will report how full the trace buffer is. If
384
+ * a report indicates the buffer usage is 100%, a warning will be issued.
385
+ *
386
+ * @param {{enableNetwork: boolean,
387
+ * enablePage: boolean,
388
+ * enableTimeline: boolean,
389
+ * tracingCategories: string,
390
+ * bufferUsageReportingInterval: number}} prefs The performance
391
+ * logging preferences.
392
+ * @return {!Options} A self reference.
393
+ */
394
+ setPerfLoggingPrefs(prefs) {
395
+ this.options_.perfLoggingPrefs = prefs;
396
+ return this;
397
+ }
398
+
399
+ /**
400
+ * Sets preferences for the "Local State" file in Chrome's user data
401
+ * directory.
402
+ * @param {!Object} state Dictionary of local state preferences.
403
+ * @return {!Options} A self reference.
404
+ */
405
+ setLocalState(state) {
406
+ this.options_.localState = state;
407
+ return this;
408
+ }
409
+
410
+ /**
411
+ * Sets the name of the activity hosting a Chrome-based Android WebView. This
412
+ * option must be set to connect to an [Android WebView](
413
+ * https://chromedriver.chromium.org/getting-started/getting-started---android)
414
+ *
415
+ * @param {string} name The activity name.
416
+ * @return {!Options} A self reference.
417
+ */
418
+ androidActivity(name) {
419
+ this.options_.androidActivity = name;
420
+ return this;
421
+ }
422
+
423
+ /**
424
+ * Sets the device serial number to connect to via ADB. If not specified, the
425
+ * WebDriver server will select an unused device at random. An error will be
426
+ * returned if all devices already have active sessions.
427
+ *
428
+ * @param {string} serial The device serial number to connect to.
429
+ * @return {!Options} A self reference.
430
+ */
431
+ androidDeviceSerial(serial) {
432
+ this.options_.androidDeviceSerial = serial;
433
+ return this;
434
+ }
435
+
436
+ /**
437
+ * Sets the package name of the Chrome or WebView app.
438
+ *
439
+ * @param {?string} pkg The package to connect to, or `null` to disable Android
440
+ * and switch back to using desktop browser.
441
+ * @return {!Options} A self reference.
442
+ */
443
+ androidPackage(pkg) {
444
+ this.options_.androidPackage = pkg;
445
+ return this;
446
+ }
447
+
448
+ /**
449
+ * Sets the process name of the Activity hosting the WebView (as given by
450
+ * `ps`). If not specified, the process name is assumed to be the same as
451
+ * {@link #androidPackage}.
452
+ *
453
+ * @param {string} processName The main activity name.
454
+ * @return {!Options} A self reference.
455
+ */
456
+ androidProcess(processName) {
457
+ this.options_.androidProcess = processName;
458
+ return this;
459
+ }
460
+
461
+ /**
462
+ * Sets whether to connect to an already-running instead of the specified
463
+ * {@linkplain #androidProcess app} instead of launching the app with a clean
464
+ * data directory.
465
+ *
466
+ * @param {boolean} useRunning Whether to connect to a running instance.
467
+ * @return {!Options} A self reference.
468
+ */
469
+ androidUseRunningApp(useRunning) {
470
+ this.options_.androidUseRunningApp = useRunning;
471
+ return this;
472
+ }
473
+
474
+ /**
475
+ * Sets the path to the browser's log file. This path should exist on the machine
476
+ * that will launch the browser.
477
+ * @param {string} path Path to the log file to use.
478
+ * @return {!Options} A self reference.
479
+ */
480
+ setBrowserLogFile(path) {
481
+ this.options_.logPath = path;
482
+ return this;
483
+ }
484
+
485
+ /**
486
+ * Sets the directory to store browser minidumps in. This option is only
487
+ * supported when the driver is running on Linux.
488
+ * @param {string} path The directory path.
489
+ * @return {!Options} A self reference.
490
+ */
491
+ setBrowserMinidumpPath(path) {
492
+ this.options_.minidumpPath = path;
493
+ return this;
494
+ }
495
+
496
+ /**
497
+ * Configures the browser to emulate a mobile device. For more information, refer
498
+ * to the ChromeDriver project page on [mobile emulation][em]. Configuration
499
+ * options include:
500
+ *
501
+ * - `deviceName`: The name of a pre-configured [emulated device][devem]
502
+ * - `width`: screen width, in pixels
503
+ * - `height`: screen height, in pixels
504
+ * - `pixelRatio`: screen pixel ratio
505
+ *
506
+ * __Example 1: Using a Pre-configured Device__
507
+ *
508
+ * let options = new chrome.Options().setMobileEmulation(
509
+ * {deviceName: 'Google Nexus 5'});
510
+ *
511
+ * let driver = chrome.Driver.createSession(options);
512
+ *
513
+ * __Example 2: Using Custom Screen Configuration__
514
+ *
515
+ * let options = new chrome.Options().setMobileEmulation({
516
+ * width: 360,
517
+ * height: 640,
518
+ * pixelRatio: 3.0
519
+ * });
520
+ *
521
+ * let driver = chrome.Driver.createSession(options);
522
+ *
523
+ *
524
+ * [em]: https://chromedriver.chromium.org/mobile-emulation
525
+ * [devem]: https://developer.chrome.com/devtools/docs/device-mode
526
+ *
527
+ * @param {?({deviceName: string}|
528
+ * {width: number, height: number, pixelRatio: number})} config The
529
+ * mobile emulation configuration, or `null` to disable emulation.
530
+ * @return {!Options} A self reference.
531
+ */
532
+ setMobileEmulation(config) {
533
+ this.options_.mobileEmulation = config;
534
+ return this;
535
+ }
536
+
537
+ /**
538
+ * Converts this instance to its JSON wire protocol representation. Note this
539
+ * function is an implementation not intended for general use.
540
+ *
541
+ * @return {!Object} The JSON wire protocol representation of this instance.
542
+ * @suppress {checkTypes} Suppress [] access on a struct.
543
+ */
544
+ [Symbols.serialize]() {
545
+ if (this.options_.extensions && this.options_.extensions.length) {
546
+ this.options_.extensions =
547
+ this.options_.extensions.map(function(extension) {
548
+ if (Buffer.isBuffer(extension)) {
549
+ return extension.toString('base64');
550
+ }
551
+ return io.read(/** @type {string} */(extension))
552
+ .then(buffer => buffer.toString('base64'));
553
+ });
554
+ }
555
+ return super[Symbols.serialize]();
556
+ }
557
+ }
558
+
559
+
560
+ /**
561
+ * Creates a new WebDriver client for Chromium-based browsers.
562
+ */
563
+ class Driver extends webdriver.WebDriver {
564
+ /**
565
+ * Creates a new session with the WebDriver server.
566
+ *
567
+ * @param {(Capabilities|Options)=} opt_config The configuration options.
568
+ * @param {(remote.DriverService|http.Executor)=} opt_serviceExecutor Either
569
+ * a DriverService to use for the remote end, or a preconfigured executor
570
+ * for an externally managed endpoint. If neither is provided, the
571
+ * {@linkplain ##getDefaultService default service} will be used by
572
+ * default.
573
+ * @return {!Driver} A new driver instance.
574
+ */
575
+ static createSession(caps, opt_serviceExecutor) {
576
+ let executor;
577
+ let onQuit;
578
+ if (opt_serviceExecutor instanceof http.Executor) {
579
+ executor = opt_serviceExecutor;
580
+ configureExecutor(executor, this.VENDOR_COMMAND_PREFIX);
581
+ } else {
582
+ let service = opt_serviceExecutor || this.getDefaultService();
583
+ executor = createExecutor(service.start(), this.VENDOR_COMMAND_PREFIX);
584
+ onQuit = () => service.kill();
585
+ }
586
+
587
+ // W3C spec requires noProxy value to be an array of strings, but Chromium
588
+ // expects a single host as a string.
589
+ let proxy = caps.get(Capability.PROXY);
590
+ if (proxy && Array.isArray(proxy.noProxy)) {
591
+ proxy.noProxy = proxy.noProxy[0];
592
+ if (!proxy.noProxy) {
593
+ proxy.noProxy = undefined;
594
+ }
595
+ }
596
+
597
+ return /** @type {!Driver} */(super.createSession(executor, caps, onQuit));
598
+ }
599
+
600
+ /**
601
+ * This function is a no-op as file detectors are not supported by this
602
+ * implementation.
603
+ * @override
604
+ */
605
+ setFileDetector() {}
606
+
607
+ /**
608
+ * Schedules a command to launch Chrome App with given ID.
609
+ * @param {string} id ID of the App to launch.
610
+ * @return {!Promise<void>} A promise that will be resolved
611
+ * when app is launched.
612
+ */
613
+ launchApp(id) {
614
+ return this.execute(
615
+ new command.Command(Command.LAUNCH_APP).setParameter('id', id));
616
+ }
617
+
618
+ /**
619
+ * Schedules a command to get Chromium network emulation settings.
620
+ * @return {!Promise} A promise that will be resolved when network
621
+ * emulation settings are retrievied.
622
+ */
623
+ getNetworkConditions() {
624
+ return this.execute(new command.Command(Command.GET_NETWORK_CONDITIONS));
625
+ }
626
+
627
+ /**
628
+ * Schedules a command to set Chromium network emulation settings.
629
+ *
630
+ * __Sample Usage:__
631
+ *
632
+ * driver.setNetworkConditions({
633
+ * offline: false,
634
+ * latency: 5, // Additional latency (ms).
635
+ * download_throughput: 500 * 1024, // Maximal aggregated download throughput.
636
+ * upload_throughput: 500 * 1024 // Maximal aggregated upload throughput.
637
+ * });
638
+ *
639
+ * @param {Object} spec Defines the network conditions to set
640
+ * @return {!Promise<void>} A promise that will be resolved when network
641
+ * emulation settings are set.
642
+ */
643
+ setNetworkConditions(spec) {
644
+ if (!spec || typeof spec !== 'object') {
645
+ throw TypeError('setNetworkConditions called with non-network-conditions parameter');
646
+ }
647
+ return this.execute(
648
+ new command.Command(Command.SET_NETWORK_CONDITIONS)
649
+ .setParameter('network_conditions', spec));
650
+ }
651
+
652
+ /**
653
+ * Sends an arbitrary devtools command to the browser.
654
+ *
655
+ * @param {string} cmd The name of the command to send.
656
+ * @param {Object=} params The command parameters.
657
+ * @return {!Promise<void>} A promise that will be resolved when the command
658
+ * has finished.
659
+ * @see <https://chromedevtools.github.io/devtools-protocol/>
660
+ */
661
+ sendDevToolsCommand(cmd, params = {}) {
662
+ return this.execute(
663
+ new command.Command(Command.SEND_DEVTOOLS_COMMAND)
664
+ .setParameter('cmd', cmd)
665
+ .setParameter('params', params));
666
+ }
667
+
668
+ /**
669
+ * Sends a DevTools command to change the browser's download directory.
670
+ *
671
+ * @param {string} path The desired download directory.
672
+ * @return {!Promise<void>} A promise that will be resolved when the command
673
+ * has finished.
674
+ * @see #sendDevToolsCommand
675
+ */
676
+ async setDownloadPath(path) {
677
+ if (!path || typeof path !== 'string') {
678
+ throw new error.InvalidArgumentError('invalid download path');
679
+ }
680
+ const stat = await io.stat(path);
681
+ if (!stat.isDirectory()) {
682
+ throw new error.InvalidArgumentError('not a directory: ' + path);
683
+ }
684
+ return this.sendDevToolsCommand('Page.setDownloadBehavior', {
685
+ 'behavior': 'allow',
686
+ 'downloadPath': path
687
+ });
688
+ }
689
+
690
+
691
+ /**
692
+ * Returns the list of cast sinks (Cast devices) available to the Chrome media router.
693
+ *
694
+ * @return {!promise.Thenable<void>} A promise that will be resolved with an array of Strings
695
+ * containing the friendly device names of available cast sink targets.
696
+ */
697
+ getCastSinks() {
698
+ return this.schedule(
699
+ new command.Command(Command.GET_CAST_SINKS),
700
+ 'Driver.getCastSinks()');
701
+ }
702
+
703
+ /**
704
+ * Selects a cast sink (Cast device) as the recipient of media router intents (connect or play).
705
+ *
706
+ * @param {String} Friendly name of the target device.
707
+ * @return {!promise.Thenable<void>} A promise that will be resolved
708
+ * when the target device has been selected to respond further webdriver commands.
709
+ */
710
+ setCastSinkToUse(deviceName) {
711
+ return this.schedule(
712
+ new command.Command(Command.SET_CAST_SINK_TO_USE).setParameter('sinkName', deviceName),
713
+ 'Driver.setCastSinkToUse(' + deviceName + ')');
714
+ }
715
+
716
+ /**
717
+ * Initiates tab mirroring for the current browser tab on the specified device.
718
+ *
719
+ * @param {String} Friendly name of the target device.
720
+ * @return {!promise.Thenable<void>} A promise that will be resolved
721
+ * when the mirror command has been issued to the device.
722
+ */
723
+ startCastTabMirroring(deviceName) {
724
+ return this.schedule(
725
+ new command.Command(Command.START_CAST_TAB_MIRRORING).setParameter('sinkName', deviceName),
726
+ 'Driver.startCastTabMirroring(' + deviceName + ')');
727
+ }
728
+
729
+ /**
730
+ * a
731
+ *
732
+ * @param {String} Friendly name of the target device.
733
+ * @return {!promise.Thenable<void>} A promise that will be resolved
734
+ * when the mirror command has been issued to the device.
735
+ */
736
+ getCastIssueMessage() {
737
+ return this.schedule(
738
+ new command.Command(Command.GET_CAST_ISSUE_MESSAGE),
739
+ 'Driver.getCastIssueMessage()');
740
+ }
741
+
742
+ /**
743
+ * Stops casting from media router to the specified device, if connected.
744
+ *
745
+ * @param {String} Friendly name of the target device.
746
+ * @return {!promise.Thenable<void>} A promise that will be resolved
747
+ * when the stop command has been issued to the device.
748
+ */
749
+ stopCasting(deviceName) {
750
+ return this.schedule(
751
+ new command.Command(Command.STOP_CASTING).setParameter('sinkName', deviceName),
752
+ 'Driver.stopCasting(' + deviceName + ')');
753
+ }
754
+ }
755
+
756
+
757
+ // PUBLIC API
758
+
759
+
760
+ exports.Driver = Driver;
761
+ exports.Options = Options;
762
+ exports.ServiceBuilder = ServiceBuilder;