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

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 (50) hide show
  1. package/CHANGES.md +56 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +2 -0
  4. package/README.md +2 -0
  5. package/chrome.js +69 -79
  6. package/chromium.js +231 -164
  7. package/{lib/atoms/make-atoms-module.js → devtools/CDPConnection.js} +15 -9
  8. package/edge.js +104 -146
  9. package/example/chrome_android.js +45 -0
  10. package/example/chrome_mobile_emulation.js +46 -0
  11. package/example/firefox_channels.js +84 -0
  12. package/example/google_search.js +50 -0
  13. package/example/google_search_test.js +70 -0
  14. package/example/headless.js +63 -0
  15. package/example/logging.js +64 -0
  16. package/firefox.js +199 -200
  17. package/http/index.js +128 -116
  18. package/http/util.js +56 -64
  19. package/ie.js +180 -104
  20. package/index.js +246 -199
  21. package/io/exec.js +35 -40
  22. package/io/index.js +146 -157
  23. package/io/zip.js +75 -66
  24. package/lib/atoms/find-elements.js +123 -0
  25. package/lib/atoms/get-attribute.js +75 -59
  26. package/lib/atoms/is-displayed.js +72 -72
  27. package/lib/atoms/mutation-listener.js +55 -0
  28. package/lib/by.js +192 -65
  29. package/lib/capabilities.js +76 -86
  30. package/lib/command.js +19 -35
  31. package/lib/error.js +134 -168
  32. package/lib/http.js +308 -232
  33. package/lib/input.js +192 -453
  34. package/lib/logging.js +126 -137
  35. package/lib/promise.js +53 -71
  36. package/lib/proxy.js +31 -41
  37. package/lib/session.js +12 -15
  38. package/lib/symbols.js +3 -4
  39. package/lib/until.js +162 -160
  40. package/lib/webdriver.js +1014 -549
  41. package/net/index.js +30 -36
  42. package/net/portprober.js +30 -143
  43. package/opera.js +406 -0
  44. package/package.json +15 -7
  45. package/proxy.js +2 -2
  46. package/remote/index.js +189 -187
  47. package/safari.js +40 -49
  48. package/testing/index.js +504 -0
  49. package/lib/README +0 -5
  50. package/lib/actions.js +0 -609
package/lib/input.js CHANGED
@@ -15,19 +15,19 @@
15
15
  // specific language governing permissions and limitations
16
16
  // under the License.
17
17
 
18
- 'use strict';
18
+ 'use strict'
19
19
 
20
20
  /**
21
21
  * @fileoverview Defines types related to user input with the WebDriver API.
22
22
  */
23
23
 
24
- const promise = require('./promise');
25
- const {Command, Executor, Name} = require('./command');
24
+ const promise = require('./promise')
25
+ const { Command, Name } = require('./command')
26
26
  const {
27
27
  InvalidArgumentError,
28
28
  UnknownCommandError,
29
- UnsupportedOperationError
30
- } = require('./error');
29
+ UnsupportedOperationError,
30
+ } = require('./error')
31
31
 
32
32
  /**
33
33
  * Enumeration of the buttons used in the advanced interactions API.
@@ -36,10 +36,8 @@ const {
36
36
  const Button = {
37
37
  LEFT: 0,
38
38
  MIDDLE: 1,
39
- RIGHT: 2
40
- };
41
-
42
-
39
+ RIGHT: 2,
40
+ }
43
41
 
44
42
  /**
45
43
  * Representations of pressable keys that aren't text. These are stored in
@@ -50,69 +48,69 @@ const Button = {
50
48
  * @see <https://www.w3.org/TR/webdriver/#keyboard-actions>
51
49
  */
52
50
  const Key = {
53
- NULL: '\uE000',
54
- CANCEL: '\uE001', // ^break
55
- HELP: '\uE002',
56
- BACK_SPACE: '\uE003',
57
- TAB: '\uE004',
58
- CLEAR: '\uE005',
59
- RETURN: '\uE006',
60
- ENTER: '\uE007',
61
- SHIFT: '\uE008',
62
- CONTROL: '\uE009',
63
- ALT: '\uE00A',
64
- PAUSE: '\uE00B',
65
- ESCAPE: '\uE00C',
66
- SPACE: '\uE00D',
67
- PAGE_UP: '\uE00E',
68
- PAGE_DOWN: '\uE00F',
69
- END: '\uE010',
70
- HOME: '\uE011',
71
- ARROW_LEFT: '\uE012',
72
- LEFT: '\uE012',
73
- ARROW_UP: '\uE013',
74
- UP: '\uE013',
75
- ARROW_RIGHT: '\uE014',
76
- RIGHT: '\uE014',
77
- ARROW_DOWN: '\uE015',
78
- DOWN: '\uE015',
79
- INSERT: '\uE016',
80
- DELETE: '\uE017',
81
- SEMICOLON: '\uE018',
82
- EQUALS: '\uE019',
83
-
84
- NUMPAD0: '\uE01A', // number pad keys
85
- NUMPAD1: '\uE01B',
86
- NUMPAD2: '\uE01C',
87
- NUMPAD3: '\uE01D',
88
- NUMPAD4: '\uE01E',
89
- NUMPAD5: '\uE01F',
90
- NUMPAD6: '\uE020',
91
- NUMPAD7: '\uE021',
92
- NUMPAD8: '\uE022',
93
- NUMPAD9: '\uE023',
94
- MULTIPLY: '\uE024',
95
- ADD: '\uE025',
96
- SEPARATOR: '\uE026',
97
- SUBTRACT: '\uE027',
98
- DECIMAL: '\uE028',
99
- DIVIDE: '\uE029',
100
-
101
- F1: '\uE031', // function keys
102
- F2: '\uE032',
103
- F3: '\uE033',
104
- F4: '\uE034',
105
- F5: '\uE035',
106
- F6: '\uE036',
107
- F7: '\uE037',
108
- F8: '\uE038',
109
- F9: '\uE039',
110
- F10: '\uE03A',
111
- F11: '\uE03B',
112
- F12: '\uE03C',
113
-
114
- COMMAND: '\uE03D', // Apple command key
115
- META: '\uE03D', // alias for Windows key
51
+ NULL: '\uE000',
52
+ CANCEL: '\uE001', // ^break
53
+ HELP: '\uE002',
54
+ BACK_SPACE: '\uE003',
55
+ TAB: '\uE004',
56
+ CLEAR: '\uE005',
57
+ RETURN: '\uE006',
58
+ ENTER: '\uE007',
59
+ SHIFT: '\uE008',
60
+ CONTROL: '\uE009',
61
+ ALT: '\uE00A',
62
+ PAUSE: '\uE00B',
63
+ ESCAPE: '\uE00C',
64
+ SPACE: '\uE00D',
65
+ PAGE_UP: '\uE00E',
66
+ PAGE_DOWN: '\uE00F',
67
+ END: '\uE010',
68
+ HOME: '\uE011',
69
+ ARROW_LEFT: '\uE012',
70
+ LEFT: '\uE012',
71
+ ARROW_UP: '\uE013',
72
+ UP: '\uE013',
73
+ ARROW_RIGHT: '\uE014',
74
+ RIGHT: '\uE014',
75
+ ARROW_DOWN: '\uE015',
76
+ DOWN: '\uE015',
77
+ INSERT: '\uE016',
78
+ DELETE: '\uE017',
79
+ SEMICOLON: '\uE018',
80
+ EQUALS: '\uE019',
81
+
82
+ NUMPAD0: '\uE01A', // number pad keys
83
+ NUMPAD1: '\uE01B',
84
+ NUMPAD2: '\uE01C',
85
+ NUMPAD3: '\uE01D',
86
+ NUMPAD4: '\uE01E',
87
+ NUMPAD5: '\uE01F',
88
+ NUMPAD6: '\uE020',
89
+ NUMPAD7: '\uE021',
90
+ NUMPAD8: '\uE022',
91
+ NUMPAD9: '\uE023',
92
+ MULTIPLY: '\uE024',
93
+ ADD: '\uE025',
94
+ SEPARATOR: '\uE026',
95
+ SUBTRACT: '\uE027',
96
+ DECIMAL: '\uE028',
97
+ DIVIDE: '\uE029',
98
+
99
+ F1: '\uE031', // function keys
100
+ F2: '\uE032',
101
+ F3: '\uE033',
102
+ F4: '\uE034',
103
+ F5: '\uE035',
104
+ F6: '\uE036',
105
+ F7: '\uE037',
106
+ F8: '\uE038',
107
+ F9: '\uE039',
108
+ F10: '\uE03A',
109
+ F11: '\uE03B',
110
+ F12: '\uE03C',
111
+
112
+ COMMAND: '\uE03D', // Apple command key
113
+ META: '\uE03D', // alias for Windows key
116
114
 
117
115
  /**
118
116
  * Japanese modifier key for switching between full- and half-width
@@ -120,8 +118,7 @@ const Key = {
120
118
  * @see <https://en.wikipedia.org/wiki/Language_input_keys>
121
119
  */
122
120
  ZENKAKU_HANKAKU: '\uE040',
123
- };
124
-
121
+ }
125
122
 
126
123
  /**
127
124
  * Simulate pressing many keys at once in a "chord". Takes a sequence of
@@ -135,10 +132,9 @@ const Key = {
135
132
  * @param {...string} keys The key sequence to concatenate.
136
133
  * @return {string} The null-terminated key sequence.
137
134
  */
138
- Key.chord = function(...keys) {
139
- return keys.join('') + Key.NULL;
140
- };
141
-
135
+ Key.chord = function (...keys) {
136
+ return keys.join('') + Key.NULL
137
+ }
142
138
 
143
139
  /**
144
140
  * Used with {@link ./webelement.WebElement#sendKeys WebElement#sendKeys} on
@@ -155,7 +151,6 @@ Key.chord = function(...keys) {
155
151
  * [Selenium Server](https://selenium.dev/downloads/).
156
152
  */
157
153
  class FileDetector {
158
-
159
154
  /**
160
155
  * Handles the file specified by the given path, preparing it for use with
161
156
  * the current browser. If the path does not refer to a valid file, it will
@@ -170,12 +165,11 @@ class FileDetector {
170
165
  * @return {!Promise<string>} A promise for the processed file path.
171
166
  * @package
172
167
  */
173
- handleFile(driver, path) {
174
- return Promise.resolve(path);
168
+ handleFile(driver, path) { // eslint-disable-line
169
+ return Promise.resolve(path)
175
170
  }
176
171
  }
177
172
 
178
-
179
173
  /**
180
174
  * Generic description of a single action to send to the remote end.
181
175
  *
@@ -185,21 +179,20 @@ class FileDetector {
185
179
  class Action {
186
180
  constructor() {
187
181
  /** @type {!Action.Type} */
188
- this.type;
182
+ this.type
189
183
  /** @type {(number|undefined)} */
190
- this.duration;
184
+ this.duration
191
185
  /** @type {(string|undefined)} */
192
- this.value;
186
+ this.value
193
187
  /** @type {(Button|undefined)} */
194
- this.button;
188
+ this.button
195
189
  /** @type {(number|undefined)} */
196
- this.x;
190
+ this.x
197
191
  /** @type {(number|undefined)} */
198
- this.y;
192
+ this.y
199
193
  }
200
194
  }
201
195
 
202
-
203
196
  /**
204
197
  * @enum {string}
205
198
  * @package
@@ -212,9 +205,8 @@ Action.Type = {
212
205
  POINTER_DOWN: 'pointerDown',
213
206
  POINTER_UP: 'pointerUp',
214
207
  POINTER_MOVE: 'pointerMove',
215
- POINTER_CANCEL: 'pointerCancel'
216
- };
217
-
208
+ POINTER_CANCEL: 'pointerCancel',
209
+ }
218
210
 
219
211
  /**
220
212
  * Represents a user input device.
@@ -227,17 +219,16 @@ class Device {
227
219
  * @param {string} id a unique ID for this device.
228
220
  */
229
221
  constructor(type, id) {
230
- /** @private @const */ this.type_ = type;
231
- /** @private @const */ this.id_ = id;
222
+ /** @private @const */ this.type_ = type
223
+ /** @private @const */ this.id_ = id
232
224
  }
233
225
 
234
226
  /** @return {!Object} the JSON encoding for this device. */
235
227
  toJSON() {
236
- return {'type': this.type_, 'id': this.id_};
228
+ return { type: this.type_, id: this.id_ }
237
229
  }
238
230
  }
239
231
 
240
-
241
232
  /**
242
233
  * Device types supported by the WebDriver protocol.
243
234
  *
@@ -247,9 +238,8 @@ class Device {
247
238
  Device.Type = {
248
239
  KEY: 'key',
249
240
  NONE: 'none',
250
- POINTER: 'pointer'
251
- };
252
-
241
+ POINTER: 'pointer',
242
+ }
253
243
 
254
244
  /**
255
245
  * @param {(string|Key|number)} key
@@ -258,22 +248,22 @@ Device.Type = {
258
248
  */
259
249
  function checkCodePoint(key) {
260
250
  if (typeof key === 'number') {
261
- return String.fromCodePoint(key);
251
+ return String.fromCodePoint(key)
262
252
  }
263
253
 
264
254
  if (typeof key !== 'string') {
265
- throw new InvalidArgumentError(`key is not a string: ${key}`);
255
+ throw new InvalidArgumentError(`key is not a string: ${key}`)
266
256
  }
267
257
 
268
- key = key.normalize();
258
+ key = key.normalize()
269
259
  if (Array.from(key).length != 1) {
270
260
  throw new InvalidArgumentError(
271
- `key input is not a single code point: ${key}`);
261
+ `key input is not a single code point: ${key}`
262
+ )
272
263
  }
273
- return key;
264
+ return key
274
265
  }
275
266
 
276
-
277
267
  /**
278
268
  * Keyboard input device.
279
269
  *
@@ -283,7 +273,7 @@ function checkCodePoint(key) {
283
273
  class Keyboard extends Device {
284
274
  /** @param {string} id the device ID. */
285
275
  constructor(id) {
286
- super(Device.Type.KEY, id);
276
+ super(Device.Type.KEY, id)
287
277
  }
288
278
 
289
279
  /**
@@ -296,7 +286,7 @@ class Keyboard extends Device {
296
286
  * @package
297
287
  */
298
288
  keyDown(key) {
299
- return {type: Action.Type.KEY_DOWN, value: checkCodePoint(key)};
289
+ return { type: Action.Type.KEY_DOWN, value: checkCodePoint(key) }
300
290
  }
301
291
 
302
292
  /**
@@ -309,11 +299,10 @@ class Keyboard extends Device {
309
299
  * @package
310
300
  */
311
301
  keyUp(key) {
312
- return {type: Action.Type.KEY_UP, value: checkCodePoint(key)};
302
+ return { type: Action.Type.KEY_UP, value: checkCodePoint(key) }
313
303
  }
314
304
  }
315
305
 
316
-
317
306
  /**
318
307
  * Defines the reference point from which to compute offsets for
319
308
  * {@linkplain ./input.Pointer#move pointer move} actions.
@@ -324,9 +313,8 @@ const Origin = {
324
313
  /** Compute offsets relative to the pointer's current position. */
325
314
  POINTER: 'pointer',
326
315
  /** Compute offsets relative to the viewport. */
327
- VIEWPORT: 'viewport'
328
- };
329
-
316
+ VIEWPORT: 'viewport',
317
+ }
330
318
 
331
319
  /**
332
320
  * Pointer input device.
@@ -340,15 +328,16 @@ class Pointer extends Device {
340
328
  * @param {Pointer.Type} type the pointer type.
341
329
  */
342
330
  constructor(id, type) {
343
- super(Device.Type.POINTER, id);
344
- /** @private @const */ this.pointerType_ = type;
331
+ super(Device.Type.POINTER, id)
332
+ /** @private @const */ this.pointerType_ = type
345
333
  }
346
334
 
347
335
  /** @override */
348
336
  toJSON() {
349
337
  return Object.assign(
350
- {'parameters': {'pointerType': this.pointerType_}},
351
- super.toJSON());
338
+ { parameters: { pointerType: this.pointerType_ } },
339
+ super.toJSON()
340
+ )
352
341
  }
353
342
 
354
343
  /**
@@ -356,7 +345,7 @@ class Pointer extends Device {
356
345
  * @package
357
346
  */
358
347
  cancel() {
359
- return {type: Action.Type.POINTER_CANCEL};
348
+ return { type: Action.Type.POINTER_CANCEL }
360
349
  }
361
350
 
362
351
  /**
@@ -365,7 +354,7 @@ class Pointer extends Device {
365
354
  * @package
366
355
  */
367
356
  press(button = Button.LEFT) {
368
- return {type: Action.Type.POINTER_DOWN, button};
357
+ return { type: Action.Type.POINTER_DOWN, button }
369
358
  }
370
359
 
371
360
  /**
@@ -375,7 +364,7 @@ class Pointer extends Device {
375
364
  * @package
376
365
  */
377
366
  release(button = Button.LEFT) {
378
- return {type: Action.Type.POINTER_UP, button};
367
+ return { type: Action.Type.POINTER_UP, button }
379
368
  }
380
369
 
381
370
  /**
@@ -394,12 +383,11 @@ class Pointer extends Device {
394
383
  * @return {!Action} The new action.
395
384
  * @package
396
385
  */
397
- move({x = 0, y = 0, duration = 100, origin = Origin.VIEWPORT}) {
398
- return {type: Action.Type.POINTER_MOVE, origin, duration, x, y};
386
+ move({ x = 0, y = 0, duration = 100, origin = Origin.VIEWPORT }) {
387
+ return { type: Action.Type.POINTER_MOVE, origin, duration, x, y }
399
388
  }
400
389
  }
401
390
 
402
-
403
391
  /**
404
392
  * The supported types of pointers.
405
393
  * @enum {string}
@@ -407,9 +395,8 @@ class Pointer extends Device {
407
395
  Pointer.Type = {
408
396
  MOUSE: 'mouse',
409
397
  PEN: 'pen',
410
- TOUCH: 'touch'
411
- };
412
-
398
+ TOUCH: 'touch',
399
+ }
413
400
 
414
401
  /**
415
402
  * User facing API for generating complex user gestures. This class should not
@@ -502,67 +489,6 @@ Pointer.Type = {
502
489
  * | Keyboard | pause(100) | keyDown(SHIFT) |
503
490
  * | Mouse | move({duration: 300}) | |
504
491
  *
505
- *
506
- * #### Bridge Mode
507
- *
508
- * As of January 2018, only Firefox natively supports this API. For other
509
- * browsers, you may either use the
510
- * {@link ./actions.LegacyActionSequence LegacyActionSequence} class, _or_ you
511
- * can put the Actions class into bridge mode by passing `{bridge: true}` on
512
- * creation:
513
- *
514
- * const actions = driver.actions({bridge: true});
515
- * await actions.click(element).sendKeys('abc').perform();
516
- *
517
- * In bridge mode, {@link #perform perform()} will first attempt to execute the
518
- * configured action sequence using the W3C action protocol. If this is rejected
519
- * by the remote end, the sequence will be translated to and executed against
520
- * the legacy protocol.
521
- *
522
- * Bridge mode __is not enabled by default__ as there are several notable
523
- * differences between W3C-specified and legacy protocols. Care must be
524
- * taken to configure your action sequences to account for these differences:
525
- *
526
- * 1. For W3C actions, the entire action sequence is executed in a single
527
- * call to the remote end. For legacy sequences, multiple calls must be
528
- * made for each step in the sequence. This introduces additional latency
529
- * which may impact how the browser responds to the emulated user actions.
530
- *
531
- * 2. For the legacy actions, {@linkplain #pause pauses} are handled _locally_.
532
- *
533
- * 3. For legacy actions, a {@linkplain #keyDown keyDown()} for a
534
- * _non-modifier key_ **must** be followed by a {@linkplain #keyUP keyUp()}
535
- * for the same key. This will be handled for you if you use the
536
- * {@linkplain #sendKeys sendKeys()} method.
537
- *
538
- * 4. Mouse movements may not be specified relative to
539
- * {@linkplain ./input.Origin.VIEWPORT Origin.VIEWPORT}.
540
- * All movements must be relative to an element or the mouse's current
541
- * position ({@linkplain ./input.Origin.POINTER Origin.POINTER}).
542
- * The {@linkplain #move move()} method defaults to viewport relative
543
- * offsets, so you must always specify an appropriate origin in bridge mode:
544
- *
545
- * driver.actions({bridge: true})
546
- * .move({x: 0, y: 0, origin: Origin.POINTER})
547
- * .perform();
548
- * driver.actions({bridge: true})
549
- * .move({x: 0, y: 0, origin: someWebElement})
550
- * .perform();
551
- *
552
- * 5. The legacy protocol does not support specifying the duration of a
553
- * {@linkplain #move mouse movement}; any specified duration _is ignored_
554
- * when translating actions to the legacy protocol.
555
- *
556
- * 6. For W3C actions, move offsets relative to a
557
- * {@linkplain ./webdriver.WebElement WebElement} are interpreted relative
558
- * to the center of an element's _first_ [client rect] in the viewport. For
559
- * legacy actions, element offsets are relative to the top-left corner of
560
- * the element's [bounding client rect]. When translating actions to the
561
- * legacy protocol in bridge mode, an extra command must be inserted to
562
- * translate move offsets from one frame of reference to the other. This
563
- * extra command contributes to the overall latency issue outlined in
564
- * point 1.
565
- *
566
492
  * [client rect]: https://developer.mozilla.org/en-US/docs/Web/API/Element/getClientRects
567
493
  * [bounding client rect]: https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
568
494
  *
@@ -573,47 +499,38 @@ class Actions {
573
499
  /**
574
500
  * @param {!Executor} executor The object to execute the configured
575
501
  * actions with.
576
- * @param {{async: (boolean|undefined),
577
- * bridge: (boolean|undefined)}} options Options for this action
502
+ * @param {{async: (boolean|undefined)}} options Options for this action
578
503
  * sequence (see class description for details).
579
504
  */
580
- constructor(executor, {async = false, bridge = false} = {}) {
581
- if (async && bridge) {
582
- throw new InvalidArgumentError(
583
- 'Async sequences not supported with bridge mode');
584
- }
505
+ constructor(executor, { async = false } = {}) {
585
506
 
586
507
  /** @private @const */
587
- this.executor_ = executor;
508
+ this.executor_ = executor
588
509
 
589
510
  /** @private @const */
590
- this.sync_ = !async;
511
+ this.sync_ = !async
591
512
 
592
513
  /** @private @const */
593
- this.bridge_ = !!bridge;
514
+ this.keyboard_ = new Keyboard('default keyboard')
594
515
 
595
516
  /** @private @const */
596
- this.keyboard_ = new Keyboard('default keyboard');
597
-
598
- /** @private @const */
599
- this.mouse_ = new Pointer('default mouse', Pointer.Type.MOUSE);
517
+ this.mouse_ = new Pointer('default mouse', Pointer.Type.MOUSE)
600
518
 
601
519
  /** @private @const {!Map<!Device, !Array<!Action>>} */
602
520
  this.sequences_ = new Map([
603
521
  [this.keyboard_, []],
604
522
  [this.mouse_, []],
605
- ]);
523
+ ])
606
524
  }
607
525
 
608
-
609
526
  /** @return {!Keyboard} the keyboard device handle. */
610
527
  keyboard() {
611
- return this.keyboard_;
528
+ return this.keyboard_
612
529
  }
613
530
 
614
531
  /** @return {!Pointer} the mouse pointer device handle. */
615
532
  mouse() {
616
- return this.mouse_;
533
+ return this.mouse_
617
534
  }
618
535
 
619
536
  /**
@@ -622,12 +539,12 @@ class Actions {
622
539
  * @private
623
540
  */
624
541
  sequence_(device) {
625
- let sequence = this.sequences_.get(device);
542
+ let sequence = this.sequences_.get(device)
626
543
  if (!sequence) {
627
- sequence = [];
628
- this.sequences_.set(device, sequence);
544
+ sequence = []
545
+ this.sequences_.set(device, sequence)
629
546
  }
630
- return sequence;
547
+ return sequence
631
548
  }
632
549
 
633
550
  /**
@@ -641,8 +558,8 @@ class Actions {
641
558
  * @return {!Actions} a self reference.
642
559
  */
643
560
  insert(device, ...actions) {
644
- this.sequence_(device).push(...actions);
645
- return this.sync_ ? this.synchronize() : this;
561
+ this.sequence_(device).push(...actions)
562
+ return this.sync_ ? this.synchronize() : this
646
563
  }
647
564
 
648
565
  /**
@@ -657,30 +574,30 @@ class Actions {
657
574
  * @return {!Actions} a self reference.
658
575
  */
659
576
  synchronize(...devices) {
660
- let sequences;
661
- let max = 0;
577
+ let sequences
578
+ let max = 0
662
579
  if (devices.length === 0) {
663
580
  for (const s of this.sequences_.values()) {
664
- max = Math.max(max, s.length);
581
+ max = Math.max(max, s.length)
665
582
  }
666
- sequences = this.sequences_.values();
583
+ sequences = this.sequences_.values()
667
584
  } else {
668
- sequences = [];
585
+ sequences = []
669
586
  for (const device of devices) {
670
- const seq = this.sequence_(device);
671
- max = Math.max(max, seq.length);
672
- sequences.push(seq);
587
+ const seq = this.sequence_(device)
588
+ max = Math.max(max, seq.length)
589
+ sequences.push(seq)
673
590
  }
674
591
  }
675
592
 
676
- const pause = {type: Action.Type.PAUSE, duration: 0};
593
+ const pause = { type: Action.Type.PAUSE, duration: 0 }
677
594
  for (const seq of sequences) {
678
595
  while (seq.length < max) {
679
- seq.push(pause);
596
+ seq.push(pause)
680
597
  }
681
598
  }
682
599
 
683
- return this;
600
+ return this
684
601
  }
685
602
 
686
603
  /**
@@ -735,21 +652,21 @@ class Actions {
735
652
  */
736
653
  pause(duration, ...devices) {
737
654
  if (duration instanceof Device) {
738
- devices.push(duration);
739
- duration = 0;
655
+ devices.push(duration)
656
+ duration = 0
740
657
  } else if (!duration) {
741
- duration = 0;
658
+ duration = 0
742
659
  }
743
660
 
744
- const action = {type: Action.Type.PAUSE, duration};
661
+ const action = { type: Action.Type.PAUSE, duration }
745
662
 
746
663
  // NB: need a properly typed variable for type checking.
747
664
  /** @type {!Iterable<!Device>} */
748
- const iterable = devices.length === 0 ? this.sequences_.keys() : devices;
665
+ const iterable = devices.length === 0 ? this.sequences_.keys() : devices
749
666
  for (const device of iterable) {
750
- this.sequence_(device).push(action);
667
+ this.sequence_(device).push(action)
751
668
  }
752
- return this.sync_ ? this.synchronize() : this;
669
+ return this.sync_ ? this.synchronize() : this
753
670
  }
754
671
 
755
672
  /**
@@ -761,7 +678,7 @@ class Actions {
761
678
  * @return {!Actions} a self reference.
762
679
  */
763
680
  keyDown(key) {
764
- return this.insert(this.keyboard_, this.keyboard_.keyDown(key));
681
+ return this.insert(this.keyboard_, this.keyboard_.keyDown(key))
765
682
  }
766
683
 
767
684
  /**
@@ -773,7 +690,7 @@ class Actions {
773
690
  * @return {!Actions} a self reference.
774
691
  */
775
692
  keyUp(key) {
776
- return this.insert(this.keyboard_, this.keyboard_.keyUp(key));
693
+ return this.insert(this.keyboard_, this.keyboard_.keyUp(key))
777
694
  }
778
695
 
779
696
  /**
@@ -788,21 +705,20 @@ class Actions {
788
705
  * @return {!Actions} a self reference.
789
706
  */
790
707
  sendKeys(...keys) {
791
- const actions = [];
708
+ const actions = []
792
709
  for (const key of keys) {
793
710
  if (typeof key === 'string') {
794
711
  for (const symbol of key) {
795
712
  actions.push(
796
- this.keyboard_.keyDown(symbol),
797
- this.keyboard_.keyUp(symbol));
713
+ this.keyboard_.keyDown(symbol),
714
+ this.keyboard_.keyUp(symbol)
715
+ )
798
716
  }
799
717
  } else {
800
- actions.push(
801
- this.keyboard_.keyDown(key),
802
- this.keyboard_.keyUp(key));
718
+ actions.push(this.keyboard_.keyDown(key), this.keyboard_.keyUp(key))
803
719
  }
804
720
  }
805
- return this.insert(this.keyboard_, ...actions);
721
+ return this.insert(this.keyboard_, ...actions)
806
722
  }
807
723
 
808
724
  /**
@@ -812,7 +728,7 @@ class Actions {
812
728
  * @return {!Actions} a self reference.
813
729
  */
814
730
  press(button = Button.LEFT) {
815
- return this.insert(this.mouse_, this.mouse_.press(button));
731
+ return this.insert(this.mouse_, this.mouse_.press(button))
816
732
  }
817
733
 
818
734
  /**
@@ -823,7 +739,7 @@ class Actions {
823
739
  * @return {!Actions} a self reference.
824
740
  */
825
741
  release(button = Button.LEFT) {
826
- return this.insert(this.mouse_, this.mouse_.release(button));
742
+ return this.insert(this.mouse_, this.mouse_.release(button))
827
743
  }
828
744
 
829
745
  /**
@@ -847,9 +763,11 @@ class Actions {
847
763
  * corner of the viewport over 100ms.
848
764
  * @return {!Actions} a self reference.
849
765
  */
850
- move({x = 0, y = 0, duration = 100, origin = Origin.VIEWPORT} = {}) {
766
+ move({ x = 0, y = 0, duration = 100, origin = Origin.VIEWPORT } = {}) {
851
767
  return this.insert(
852
- this.mouse_, this.mouse_.move({x, y, duration, origin}));
768
+ this.mouse_,
769
+ this.mouse_.move({ x, y, duration, origin })
770
+ )
853
771
  }
854
772
 
855
773
  /**
@@ -862,9 +780,9 @@ class Actions {
862
780
  */
863
781
  click(element) {
864
782
  if (element) {
865
- this.move({origin: element});
783
+ this.move({ origin: element })
866
784
  }
867
- return this.press().release();
785
+ return this.press().release()
868
786
  }
869
787
 
870
788
  /**
@@ -877,9 +795,9 @@ class Actions {
877
795
  */
878
796
  contextClick(element) {
879
797
  if (element) {
880
- this.move({origin: element});
798
+ this.move({ origin: element })
881
799
  }
882
- return this.press(Button.RIGHT).release(Button.RIGHT);
800
+ return this.press(Button.RIGHT).release(Button.RIGHT)
883
801
  }
884
802
 
885
803
  /**
@@ -891,7 +809,7 @@ class Actions {
891
809
  * @return {!Actions} a self reference.
892
810
  */
893
811
  doubleClick(element) {
894
- return this.click(element).press().release();
812
+ return this.click(element).press().release()
895
813
  }
896
814
 
897
815
  /**
@@ -913,20 +831,23 @@ class Actions {
913
831
  */
914
832
  dragAndDrop(from, to) {
915
833
  // Do not require up top to avoid a cycle that breaks static analysis.
916
- const {WebElement} = require('./webdriver');
917
- if (!(to instanceof WebElement)
918
- && (!to || typeof to.x !== 'number' || typeof to.y !== 'number')) {
834
+ const { WebElement } = require('./webdriver')
835
+ if (
836
+ !(to instanceof WebElement) &&
837
+ (!to || typeof to.x !== 'number' || typeof to.y !== 'number')
838
+ ) {
919
839
  throw new InvalidArgumentError(
920
- 'Invalid drag target; must specify a WebElement or {x, y} offset');
840
+ 'Invalid drag target; must specify a WebElement or {x, y} offset'
841
+ )
921
842
  }
922
843
 
923
- this.move({origin: from}).press();
844
+ this.move({ origin: from }).press()
924
845
  if (to instanceof WebElement) {
925
- this.move({origin: to});
846
+ this.move({ origin: to })
926
847
  } else {
927
- this.move({x: to.x, y: to.y, origin: Origin.POINTER});
848
+ this.move({ x: to.x, y: to.y, origin: Origin.POINTER })
928
849
  }
929
- return this.release();
850
+ return this.release()
930
851
  }
931
852
 
932
853
  /**
@@ -937,9 +858,9 @@ class Actions {
937
858
  */
938
859
  clear() {
939
860
  for (const s of this.sequences_.values()) {
940
- s.length = 0;
861
+ s.length = 0
941
862
  }
942
- return this.executor_.execute(new Command(Name.CLEAR_ACTIONS));
863
+ return this.executor_.execute(new Command(Name.CLEAR_ACTIONS))
943
864
  }
944
865
 
945
866
  /**
@@ -949,219 +870,39 @@ class Actions {
949
870
  * been completed.
950
871
  */
951
872
  async perform() {
952
- const _actions = [];
873
+ const _actions = []
953
874
  this.sequences_.forEach((actions, device) => {
954
875
  if (!isIdle(actions)) {
955
- actions = actions.concat(); // Defensive copy.
956
- _actions.push(Object.assign({actions}, device.toJSON()));
876
+ actions = actions.concat() // Defensive copy.
877
+ _actions.push(Object.assign({ actions }, device.toJSON()))
957
878
  }
958
- });
879
+ })
959
880
 
960
881
  if (_actions.length === 0) {
961
- return Promise.resolve();
882
+ return Promise.resolve()
962
883
  }
963
884
 
964
885
  try {
965
886
  await this.executor_.execute(
966
- new Command(Name.ACTIONS).setParameter('actions', _actions));
887
+ new Command(Name.ACTIONS).setParameter('actions', _actions)
888
+ )
967
889
  } catch (ex) {
968
- if (this.bridge_
969
- && (ex instanceof UnknownCommandError
970
- || ex instanceof UnsupportedOperationError)) {
971
- return executeLegacy(this.executor_, this.sequences_);
972
- }
973
- throw ex;
890
+ throw ex
974
891
  }
975
892
  }
976
893
  }
977
894
 
978
-
979
895
  /**
980
896
  * @param {!Array<!Action>} actions
981
897
  * @return {boolean}
982
898
  */
983
899
  function isIdle(actions) {
984
- return actions.length === 0
985
- || actions.every(a => a.type === Action.Type.PAUSE && !a.duration);
900
+ return (
901
+ actions.length === 0 ||
902
+ actions.every((a) => a.type === Action.Type.PAUSE && !a.duration)
903
+ )
986
904
  }
987
905
 
988
-
989
- const MODIFIER_KEYS = new Set([Key.ALT, Key.CONTROL, Key.SHIFT, Key.COMMAND]);
990
-
991
-
992
- /**
993
- * @param {!Executor} executor
994
- * @param {!Map<!Device, !Array<!Action>>} sequences
995
- * @return {!Promise<void>}
996
- * @suppress {deprecated} Ignore warnings about using LegacyActionSequence.
997
- */
998
- async function executeLegacy(executor, sequences) {
999
- let maxLength = 0;
1000
- sequences.forEach(seq => maxLength = Math.max(maxLength, seq.length));
1001
-
1002
- const actions = [];
1003
- for (let i = 0; i < maxLength; i++) {
1004
- let next;
1005
- for (const device of sequences.keys()) {
1006
- const seq = sequences.get(device);
1007
-
1008
- if (device instanceof Pointer
1009
- && device.pointerType_ !== Pointer.Type.MOUSE) {
1010
- throw new UnsupportedOperationError(
1011
- `${device.pointerType_} pointer not supported in bridge mode`);
1012
- }
1013
-
1014
- const action = seq[i];
1015
- if (!action || (action.type === Action.Type.PAUSE && !action.duration)) {
1016
- continue;
1017
- }
1018
-
1019
- // - If we've already found an action for this tick:
1020
- // - If we have two pauses, use the one with a longer duration
1021
- // - If one is a pause and the other isn't, use the non-pause
1022
- // - Otherwise, two non-pauses is an error.
1023
- // - Otherwise, we haven't selected an action yet.
1024
- if (next) {
1025
- if (next.type === Action.Type.PAUSE) {
1026
- if (action.type === Action.Type.PAUSE) {
1027
- next = next.duration > action.duration ? next : action;
1028
- } else {
1029
- next = action;
1030
- }
1031
- } else if (action.type !== Action.Type.PAUSE) {
1032
- throw new UnsupportedOperationError(
1033
- 'parallel actions not supported in bridge mode');
1034
- }
1035
- } else {
1036
- next = action;
1037
- }
1038
-
1039
- if (action.type === Action.Type.KEY_DOWN) {
1040
- // If this action is a keydown for a non-modifier key, the next action
1041
- // must be a keyup for the same key, otherwise it cannot be translated
1042
- // to the legacy action API.
1043
- if (!MODIFIER_KEYS.has(action.value)) {
1044
- const nextAction = seq[i + 1];
1045
- if (!nextAction
1046
- || nextAction.type !== Action.Type.KEY_UP
1047
- || nextAction.value !== action.value) {
1048
- throw new UnsupportedOperationError(
1049
- `in bridge mode, keydown for <${action.value}> must be followed`
1050
- + ' by a keyup for the same key');
1051
- }
1052
- }
1053
- } else if (action.type === Action.Type.KEY_UP
1054
- && !MODIFIER_KEYS.has(action.value)) {
1055
- next = null;
1056
- }
1057
- }
1058
-
1059
- if (next) {
1060
- actions.push(next);
1061
- }
1062
- }
1063
-
1064
- for (let i = 0; i < actions.length; i++) {
1065
- const action = actions[i];
1066
- switch (action.type) {
1067
- case Action.Type.PAUSE:
1068
- await promise.delayed(action.duration || 0);
1069
- break;
1070
- case Action.Type.KEY_DOWN:
1071
- const keys = [action.value];
1072
- if (!MODIFIER_KEYS.has(action.value)) {
1073
- function nextIsKeyDown() {
1074
- const next = actions[i + 1];
1075
- return !!next
1076
- && next.type === Action.Type.KEY_DOWN
1077
- && !MODIFIER_KEYS.has(next.value);
1078
- }
1079
- for (; nextIsKeyDown(); i++) {
1080
- keys.push(actions[i + 1].value);
1081
- }
1082
- }
1083
- await executor.execute(
1084
- new Command(Name.LEGACY_ACTION_SEND_KEYS)
1085
- .setParameter('value', keys));
1086
- break;
1087
- case Action.Type.KEY_UP:
1088
- await executor.execute(
1089
- new Command(Name.LEGACY_ACTION_SEND_KEYS)
1090
- .setParameter('value', [action.value]));
1091
- break;
1092
- case Action.Type.POINTER_DOWN: {
1093
- function isClick(startAt) {
1094
- const first = actions[startAt];
1095
- const second = actions[startAt + 1];
1096
- return !!first && !!second
1097
- && first.type === Action.Type.POINTER_DOWN
1098
- && second.type === Action.Type.POINTER_UP
1099
- && first.button === second.button;
1100
- }
1101
-
1102
- function isDoubleClick(startAt) {
1103
- return isClick(startAt)
1104
- && isClick(startAt + 2)
1105
- && actions[startAt].button === actions[startAt = 2].button;
1106
- }
1107
-
1108
- let cmd;
1109
- if (isDoubleClick(i)) {
1110
- i += 3; // Consume the pointer up/down/up.
1111
- cmd = Name.LEGACY_ACTION_DOUBLE_CLICK;
1112
- } else if (isClick(i)) {
1113
- i++; // Consume the pointer-up.
1114
- cmd = Name.LEGACY_ACTION_CLICK;
1115
- } else {
1116
- cmd = Name.LEGACY_ACTION_MOUSE_DOWN;
1117
- }
1118
- await executor.execute(
1119
- new Command(cmd).setParameter('button', action.button));
1120
- break;
1121
- }
1122
- case Action.Type.POINTER_UP:
1123
- await executor.execute(
1124
- new Command(Name.LEGACY_ACTION_MOUSE_UP)
1125
- .setParameter('button', action.button));
1126
- break;
1127
- case Action.Type.POINTER_MOVE:
1128
- if (action.origin === Origin.VIEWPORT) {
1129
- throw new UnsupportedOperationError(
1130
- `pointer movements relative to ${Origin.VIEWPORT} are not`
1131
- + ' supported in bridge mode');
1132
-
1133
- }
1134
-
1135
- let x = action.x;
1136
- let y = action.y;
1137
- const cmd = new Command(Name.LEGACY_ACTION_MOUSE_MOVE);
1138
- if (action.origin && action.origin !== Origin.POINTER) {
1139
- const el = /** @type {!./webdriver.WebElement} */(action.origin);
1140
-
1141
- // Need to translate frame of reference from center of element's first
1142
- // client rect to the top-left of its bounding client rect. See:
1143
- // https://w3c.github.io/webdriver/webdriver-spec.html#dfn-center-point
1144
- let diff = await executor.execute(
1145
- new Command(Name.EXECUTE_SCRIPT)
1146
- .setParameter('script', INTERNAL_COMPUTE_OFFSET_SCRIPT)
1147
- .setParameter('args', [el]));
1148
- x += diff[0];
1149
- y += diff[1];
1150
-
1151
- const id = await el.getId();
1152
- cmd.setParameter('element', id);
1153
- }
1154
- cmd.setParameter('xoffset', x).setParameter('yoffset', y);
1155
- await executor.execute(cmd);
1156
- break;
1157
- default:
1158
- throw new UnsupportedOperationError(
1159
- `${action.type} actions not supported in bridge mode`);
1160
- }
1161
- }
1162
- }
1163
-
1164
-
1165
906
  /**
1166
907
  * Script used to compute the offset from the center of a DOM element's first
1167
908
  * client rect from the top-left corner of the element's bounding client rect.
@@ -1187,14 +928,12 @@ function computeOffset(el) {
1187
928
  var bbox = el.getBoundingClientRect();
1188
929
  return [x - bbox.left, y - bbox.top];
1189
930
  }
1190
- return computeOffset(arguments[0]);`;
1191
-
931
+ return computeOffset(arguments[0]);`
1192
932
 
1193
933
  // PUBLIC API
1194
934
 
1195
-
1196
935
  module.exports = {
1197
- Action, // For documentation only.
936
+ Action, // For documentation only.
1198
937
  Actions,
1199
938
  Button,
1200
939
  Device,
@@ -1204,4 +943,4 @@ module.exports = {
1204
943
  Origin,
1205
944
  Pointer,
1206
945
  INTERNAL_COMPUTE_OFFSET_SCRIPT,
1207
- };
946
+ }