selenium-webdriver 4.0.0-alpha.5 → 4.0.0-beta.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 (49) hide show
  1. package/CHANGES.md +35 -1
  2. package/LICENSE +1 -1
  3. package/NOTICE +1 -1
  4. package/README.md +4 -4
  5. package/chrome.js +72 -592
  6. package/chromium.js +829 -0
  7. package/devtools/CDPConnection.js +37 -0
  8. package/edge.js +124 -86
  9. package/example/chrome_android.js +16 -13
  10. package/example/chrome_mobile_emulation.js +18 -14
  11. package/example/firefox_channels.js +35 -28
  12. package/example/google_search.js +9 -9
  13. package/example/google_search_test.js +20 -22
  14. package/example/headless.js +27 -19
  15. package/example/logging.js +34 -38
  16. package/firefox.js +200 -200
  17. package/http/index.js +131 -115
  18. package/http/util.js +56 -64
  19. package/ie.js +180 -104
  20. package/index.js +246 -199
  21. package/io/exec.js +34 -39
  22. package/io/index.js +142 -152
  23. package/io/zip.js +75 -65
  24. package/lib/actions.js +140 -122
  25. package/lib/atoms/find-elements.js +124 -0
  26. package/lib/atoms/get-attribute.js +79 -59
  27. package/lib/atoms/is-displayed.js +72 -73
  28. package/lib/atoms/mutation-listener.js +38 -0
  29. package/lib/by.js +192 -65
  30. package/lib/capabilities.js +82 -78
  31. package/lib/command.js +20 -20
  32. package/lib/error.js +134 -168
  33. package/lib/http.js +337 -230
  34. package/lib/input.js +325 -302
  35. package/lib/logging.js +127 -138
  36. package/lib/promise.js +60 -66
  37. package/lib/proxy.js +31 -41
  38. package/lib/session.js +12 -15
  39. package/lib/symbols.js +3 -4
  40. package/lib/until.js +162 -160
  41. package/lib/webdriver.js +1024 -541
  42. package/net/index.js +30 -36
  43. package/net/portprober.js +31 -144
  44. package/opera.js +406 -0
  45. package/package.json +19 -12
  46. package/proxy.js +2 -2
  47. package/remote/index.js +190 -187
  48. package/safari.js +40 -49
  49. package/testing/index.js +166 -155
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
@@ -152,10 +148,9 @@ Key.chord = function(...keys) {
152
148
  * elements. Of particular note is the
153
149
  * {@link selenium-webdriver/remote.FileDetector}, which should be used when
154
150
  * running against a remote
155
- * [Selenium Server](http://docs.seleniumhq.org/download/).
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
@@ -478,7 +465,7 @@ Pointer.Type = {
478
465
  *
479
466
  * The length of each action tick is however long it takes the remote end to
480
467
  * execute the actions for every device in that tick. Most actions are
481
- * "instaneous", however, {@linkplain #pause pause} and
468
+ * "instantaneous", however, {@linkplain #pause pause} and
482
469
  * {@linkplain #move pointer move} actions allow you to specify a duration for
483
470
  * how long that action should take. The remote end will always wait for all
484
471
  * actions within a tick to finish before starting the next tick, so a device
@@ -495,7 +482,7 @@ Pointer.Type = {
495
482
  *
496
483
  * This implicit waiting also applies to pauses. In the table below, even though
497
484
  * the keyboard only defines a pause of 100 ms, the remote end will wait an
498
- * additional 200 ms for the mouse mmove to finish before moving to Tick 2.
485
+ * additional 200 ms for the mouse move to finish before moving to Tick 2.
499
486
  *
500
487
  * | Device | Tick 1 | Tick 2 |
501
488
  * | -------- | --------------------- | -------------- |
@@ -554,13 +541,13 @@ Pointer.Type = {
554
541
  * when translating actions to the legacy protocol.
555
542
  *
556
543
  * 6. For W3C actions, move offsets relative to a
557
- * {@linkplain ./webdriver.WebElement WebElement} are interpretted relative
544
+ * {@linkplain ./webdriver.WebElement WebElement} are interpreted relative
558
545
  * to the center of an element's _first_ [client rect] in the viewport. For
559
546
  * legacy actions, element offsets are relative to the top-left corner of
560
547
  * the element's [bounding client rect]. When translating actions to the
561
548
  * legacy protocol in bridge mode, an extra command must be inserted to
562
549
  * translate move offsets from one frame of reference to the other. This
563
- * extra command conributes to the overall latency issue outlined in
550
+ * extra command contributes to the overall latency issue outlined in
564
551
  * point 1.
565
552
  *
566
553
  * [client rect]: https://developer.mozilla.org/en-US/docs/Web/API/Element/getClientRects
@@ -577,43 +564,43 @@ class Actions {
577
564
  * bridge: (boolean|undefined)}} options Options for this action
578
565
  * sequence (see class description for details).
579
566
  */
580
- constructor(executor, {async = false, bridge = false} = {}) {
567
+ constructor(executor, { async = false, bridge = false } = {}) {
581
568
  if (async && bridge) {
582
569
  throw new InvalidArgumentError(
583
- 'Async sequences not supported with bridge mode');
570
+ 'Async sequences not supported with bridge mode'
571
+ )
584
572
  }
585
573
 
586
574
  /** @private @const */
587
- this.executor_ = executor;
575
+ this.executor_ = executor
588
576
 
589
577
  /** @private @const */
590
- this.sync_ = !async;
578
+ this.sync_ = !async
591
579
 
592
580
  /** @private @const */
593
- this.bridge_ = !!bridge;
581
+ this.bridge_ = !!bridge
594
582
 
595
583
  /** @private @const */
596
- this.keyboard_ = new Keyboard('default keyboard');
584
+ this.keyboard_ = new Keyboard('default keyboard')
597
585
 
598
586
  /** @private @const */
599
- this.mouse_ = new Pointer('default mouse', Pointer.Type.MOUSE);
587
+ this.mouse_ = new Pointer('default mouse', Pointer.Type.MOUSE)
600
588
 
601
589
  /** @private @const {!Map<!Device, !Array<!Action>>} */
602
590
  this.sequences_ = new Map([
603
591
  [this.keyboard_, []],
604
592
  [this.mouse_, []],
605
- ]);
593
+ ])
606
594
  }
607
595
 
608
-
609
596
  /** @return {!Keyboard} the keyboard device handle. */
610
597
  keyboard() {
611
- return this.keyboard_;
598
+ return this.keyboard_
612
599
  }
613
600
 
614
601
  /** @return {!Pointer} the mouse pointer device handle. */
615
602
  mouse() {
616
- return this.mouse_;
603
+ return this.mouse_
617
604
  }
618
605
 
619
606
  /**
@@ -622,12 +609,12 @@ class Actions {
622
609
  * @private
623
610
  */
624
611
  sequence_(device) {
625
- let sequence = this.sequences_.get(device);
612
+ let sequence = this.sequences_.get(device)
626
613
  if (!sequence) {
627
- sequence = [];
628
- this.sequences_.set(device, sequence);
614
+ sequence = []
615
+ this.sequences_.set(device, sequence)
629
616
  }
630
- return sequence;
617
+ return sequence
631
618
  }
632
619
 
633
620
  /**
@@ -641,8 +628,8 @@ class Actions {
641
628
  * @return {!Actions} a self reference.
642
629
  */
643
630
  insert(device, ...actions) {
644
- this.sequence_(device).push(...actions);
645
- return this.sync_ ? this.synchronize() : this;
631
+ this.sequence_(device).push(...actions)
632
+ return this.sync_ ? this.synchronize() : this
646
633
  }
647
634
 
648
635
  /**
@@ -657,30 +644,30 @@ class Actions {
657
644
  * @return {!Actions} a self reference.
658
645
  */
659
646
  synchronize(...devices) {
660
- let sequences;
661
- let max = 0;
647
+ let sequences
648
+ let max = 0
662
649
  if (devices.length === 0) {
663
650
  for (const s of this.sequences_.values()) {
664
- max = Math.max(max, s.length);
651
+ max = Math.max(max, s.length)
665
652
  }
666
- sequences = this.sequences_.values();
653
+ sequences = this.sequences_.values()
667
654
  } else {
668
- sequences = [];
655
+ sequences = []
669
656
  for (const device of devices) {
670
- const seq = this.sequence_(device);
671
- max = Math.max(max, seq.length);
672
- sequences.push(seq);
657
+ const seq = this.sequence_(device)
658
+ max = Math.max(max, seq.length)
659
+ sequences.push(seq)
673
660
  }
674
661
  }
675
662
 
676
- const pause = {type: Action.Type.PAUSE, duration: 0};
663
+ const pause = { type: Action.Type.PAUSE, duration: 0 }
677
664
  for (const seq of sequences) {
678
665
  while (seq.length < max) {
679
- seq.push(pause);
666
+ seq.push(pause)
680
667
  }
681
668
  }
682
669
 
683
- return this;
670
+ return this
684
671
  }
685
672
 
686
673
  /**
@@ -692,7 +679,7 @@ class Actions {
692
679
  * If no devices are specified, a pause action will be created (using the same
693
680
  * duration) for every device.
694
681
  *
695
- * When device synchroniation is enabled (the default for new {@link Actions}
682
+ * When device synchronization is enabled (the default for new {@link Actions}
696
683
  * objects), there is no need to specify devices as pausing one automatically
697
684
  * pauses the others for the same duration. In other words, the following are
698
685
  * all equivalent:
@@ -735,21 +722,21 @@ class Actions {
735
722
  */
736
723
  pause(duration, ...devices) {
737
724
  if (duration instanceof Device) {
738
- devices.push(duration);
739
- duration = 0;
725
+ devices.push(duration)
726
+ duration = 0
740
727
  } else if (!duration) {
741
- duration = 0;
728
+ duration = 0
742
729
  }
743
730
 
744
- const action = {type: Action.Type.PAUSE, duration};
731
+ const action = { type: Action.Type.PAUSE, duration }
745
732
 
746
733
  // NB: need a properly typed variable for type checking.
747
734
  /** @type {!Iterable<!Device>} */
748
- const iterable = devices.length === 0 ? this.sequences_.keys() : devices;
735
+ const iterable = devices.length === 0 ? this.sequences_.keys() : devices
749
736
  for (const device of iterable) {
750
- this.sequence_(device).push(action);
737
+ this.sequence_(device).push(action)
751
738
  }
752
- return this.sync_ ? this.synchronize() : this;
739
+ return this.sync_ ? this.synchronize() : this
753
740
  }
754
741
 
755
742
  /**
@@ -761,7 +748,7 @@ class Actions {
761
748
  * @return {!Actions} a self reference.
762
749
  */
763
750
  keyDown(key) {
764
- return this.insert(this.keyboard_, this.keyboard_.keyDown(key));
751
+ return this.insert(this.keyboard_, this.keyboard_.keyDown(key))
765
752
  }
766
753
 
767
754
  /**
@@ -773,7 +760,7 @@ class Actions {
773
760
  * @return {!Actions} a self reference.
774
761
  */
775
762
  keyUp(key) {
776
- return this.insert(this.keyboard_, this.keyboard_.keyUp(key));
763
+ return this.insert(this.keyboard_, this.keyboard_.keyUp(key))
777
764
  }
778
765
 
779
766
  /**
@@ -788,21 +775,20 @@ class Actions {
788
775
  * @return {!Actions} a self reference.
789
776
  */
790
777
  sendKeys(...keys) {
791
- const actions = [];
778
+ const actions = []
792
779
  for (const key of keys) {
793
780
  if (typeof key === 'string') {
794
781
  for (const symbol of key) {
795
782
  actions.push(
796
- this.keyboard_.keyDown(symbol),
797
- this.keyboard_.keyUp(symbol));
783
+ this.keyboard_.keyDown(symbol),
784
+ this.keyboard_.keyUp(symbol)
785
+ )
798
786
  }
799
787
  } else {
800
- actions.push(
801
- this.keyboard_.keyDown(key),
802
- this.keyboard_.keyUp(key));
788
+ actions.push(this.keyboard_.keyDown(key), this.keyboard_.keyUp(key))
803
789
  }
804
790
  }
805
- return this.insert(this.keyboard_, ...actions);
791
+ return this.insert(this.keyboard_, ...actions)
806
792
  }
807
793
 
808
794
  /**
@@ -812,7 +798,7 @@ class Actions {
812
798
  * @return {!Actions} a self reference.
813
799
  */
814
800
  press(button = Button.LEFT) {
815
- return this.insert(this.mouse_, this.mouse_.press(button));
801
+ return this.insert(this.mouse_, this.mouse_.press(button))
816
802
  }
817
803
 
818
804
  /**
@@ -823,7 +809,7 @@ class Actions {
823
809
  * @return {!Actions} a self reference.
824
810
  */
825
811
  release(button = Button.LEFT) {
826
- return this.insert(this.mouse_, this.mouse_.release(button));
812
+ return this.insert(this.mouse_, this.mouse_.release(button))
827
813
  }
828
814
 
829
815
  /**
@@ -847,9 +833,11 @@ class Actions {
847
833
  * corner of the viewport over 100ms.
848
834
  * @return {!Actions} a self reference.
849
835
  */
850
- move({x = 0, y = 0, duration = 100, origin = Origin.VIEWPORT} = {}) {
836
+ move({ x = 0, y = 0, duration = 100, origin = Origin.VIEWPORT } = {}) {
851
837
  return this.insert(
852
- this.mouse_, this.mouse_.move({x, y, duration, origin}));
838
+ this.mouse_,
839
+ this.mouse_.move({ x, y, duration, origin })
840
+ )
853
841
  }
854
842
 
855
843
  /**
@@ -862,9 +850,9 @@ class Actions {
862
850
  */
863
851
  click(element) {
864
852
  if (element) {
865
- this.move({origin: element});
853
+ this.move({ origin: element })
866
854
  }
867
- return this.press().release();
855
+ return this.press().release()
868
856
  }
869
857
 
870
858
  /**
@@ -877,9 +865,9 @@ class Actions {
877
865
  */
878
866
  contextClick(element) {
879
867
  if (element) {
880
- this.move({origin: element});
868
+ this.move({ origin: element })
881
869
  }
882
- return this.press(Button.RIGHT).release(Button.RIGHT);
870
+ return this.press(Button.RIGHT).release(Button.RIGHT)
883
871
  }
884
872
 
885
873
  /**
@@ -891,7 +879,7 @@ class Actions {
891
879
  * @return {!Actions} a self reference.
892
880
  */
893
881
  doubleClick(element) {
894
- return this.click(element).press().release();
882
+ return this.click(element).press().release()
895
883
  }
896
884
 
897
885
  /**
@@ -913,20 +901,23 @@ class Actions {
913
901
  */
914
902
  dragAndDrop(from, to) {
915
903
  // 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')) {
904
+ const { WebElement } = require('./webdriver')
905
+ if (
906
+ !(to instanceof WebElement) &&
907
+ (!to || typeof to.x !== 'number' || typeof to.y !== 'number')
908
+ ) {
919
909
  throw new InvalidArgumentError(
920
- 'Invalid drag target; must specify a WebElement or {x, y} offset');
910
+ 'Invalid drag target; must specify a WebElement or {x, y} offset'
911
+ )
921
912
  }
922
913
 
923
- this.move({origin: from}).press();
914
+ this.move({ origin: from }).press()
924
915
  if (to instanceof WebElement) {
925
- this.move({origin: to});
916
+ this.move({ origin: to })
926
917
  } else {
927
- this.move({x: to.x, y: to.y, origin: Origin.POINTER});
918
+ this.move({ x: to.x, y: to.y, origin: Origin.POINTER })
928
919
  }
929
- return this.release();
920
+ return this.release()
930
921
  }
931
922
 
932
923
  /**
@@ -937,9 +928,9 @@ class Actions {
937
928
  */
938
929
  clear() {
939
930
  for (const s of this.sequences_.values()) {
940
- s.length = 0;
931
+ s.length = 0
941
932
  }
942
- return this.executor_.execute(new Command(Name.CLEAR_ACTIONS));
933
+ return this.executor_.execute(new Command(Name.CLEAR_ACTIONS))
943
934
  }
944
935
 
945
936
  /**
@@ -949,45 +940,47 @@ class Actions {
949
940
  * been completed.
950
941
  */
951
942
  async perform() {
952
- const _actions = [];
943
+ const _actions = []
953
944
  this.sequences_.forEach((actions, device) => {
954
945
  if (!isIdle(actions)) {
955
- actions = actions.concat(); // Defensive copy.
956
- _actions.push(Object.assign({actions}, device.toJSON()));
946
+ actions = actions.concat() // Defensive copy.
947
+ _actions.push(Object.assign({ actions }, device.toJSON()))
957
948
  }
958
- });
949
+ })
959
950
 
960
951
  if (_actions.length === 0) {
961
- return Promise.resolve();
952
+ return Promise.resolve()
962
953
  }
963
954
 
964
955
  try {
965
956
  await this.executor_.execute(
966
- new Command(Name.ACTIONS).setParameter('actions', _actions));
957
+ new Command(Name.ACTIONS).setParameter('actions', _actions)
958
+ )
967
959
  } catch (ex) {
968
- if (this.bridge_
969
- && (ex instanceof UnknownCommandError
970
- || ex instanceof UnsupportedOperationError)) {
971
- return executeLegacy(this.executor_, this.sequences_);
960
+ if (
961
+ this.bridge_ &&
962
+ (ex instanceof UnknownCommandError ||
963
+ ex instanceof UnsupportedOperationError)
964
+ ) {
965
+ return executeLegacy(this.executor_, this.sequences_)
972
966
  }
973
- throw ex;
967
+ throw ex
974
968
  }
975
969
  }
976
970
  }
977
971
 
978
-
979
972
  /**
980
973
  * @param {!Array<!Action>} actions
981
974
  * @return {boolean}
982
975
  */
983
976
  function isIdle(actions) {
984
- return actions.length === 0
985
- || actions.every(a => a.type === Action.Type.PAUSE && !a.duration);
977
+ return (
978
+ actions.length === 0 ||
979
+ actions.every((a) => a.type === Action.Type.PAUSE && !a.duration)
980
+ )
986
981
  }
987
982
 
988
-
989
- const MODIFIER_KEYS = new Set([Key.ALT, Key.CONTROL, Key.SHIFT, Key.COMMAND]);
990
-
983
+ const MODIFIER_KEYS = new Set([Key.ALT, Key.CONTROL, Key.SHIFT, Key.COMMAND])
991
984
 
992
985
  /**
993
986
  * @param {!Executor} executor
@@ -996,24 +989,27 @@ const MODIFIER_KEYS = new Set([Key.ALT, Key.CONTROL, Key.SHIFT, Key.COMMAND]);
996
989
  * @suppress {deprecated} Ignore warnings about using LegacyActionSequence.
997
990
  */
998
991
  async function executeLegacy(executor, sequences) {
999
- let maxLength = 0;
1000
- sequences.forEach(seq => maxLength = Math.max(maxLength, seq.length));
992
+ let maxLength = 0
993
+ sequences.forEach((seq) => (maxLength = Math.max(maxLength, seq.length)))
1001
994
 
1002
- const actions = [];
995
+ const actions = []
1003
996
  for (let i = 0; i < maxLength; i++) {
1004
- let next;
997
+ let next
1005
998
  for (const device of sequences.keys()) {
1006
- const seq = sequences.get(device);
999
+ const seq = sequences.get(device)
1007
1000
 
1008
- if (device instanceof Pointer
1009
- && device.pointerType_ !== Pointer.Type.MOUSE) {
1001
+ if (
1002
+ device instanceof Pointer &&
1003
+ device.pointerType_ !== Pointer.Type.MOUSE
1004
+ ) {
1010
1005
  throw new UnsupportedOperationError(
1011
- `${device.pointerType_} pointer not supported in bridge mode`);
1006
+ `${device.pointerType_} pointer not supported in bridge mode`
1007
+ )
1012
1008
  }
1013
1009
 
1014
- const action = seq[i];
1010
+ const action = seq[i]
1015
1011
  if (!action || (action.type === Action.Type.PAUSE && !action.duration)) {
1016
- continue;
1012
+ continue
1017
1013
  }
1018
1014
 
1019
1015
  // - If we've already found an action for this tick:
@@ -1024,16 +1020,17 @@ async function executeLegacy(executor, sequences) {
1024
1020
  if (next) {
1025
1021
  if (next.type === Action.Type.PAUSE) {
1026
1022
  if (action.type === Action.Type.PAUSE) {
1027
- next = next.duration > action.duration ? next : action;
1023
+ next = next.duration > action.duration ? next : action
1028
1024
  } else {
1029
- next = action;
1025
+ next = action
1030
1026
  }
1031
1027
  } else if (action.type !== Action.Type.PAUSE) {
1032
1028
  throw new UnsupportedOperationError(
1033
- 'parallel actions not supported in bridge mode');
1029
+ 'parallel actions not supported in bridge mode'
1030
+ )
1034
1031
  }
1035
1032
  } else {
1036
- next = action;
1033
+ next = action
1037
1034
  }
1038
1035
 
1039
1036
  if (action.type === Action.Type.KEY_DOWN) {
@@ -1041,127 +1038,155 @@ async function executeLegacy(executor, sequences) {
1041
1038
  // must be a keyup for the same key, otherwise it cannot be translated
1042
1039
  // to the legacy action API.
1043
1040
  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) {
1041
+ const nextAction = seq[i + 1]
1042
+ if (
1043
+ !nextAction ||
1044
+ nextAction.type !== Action.Type.KEY_UP ||
1045
+ nextAction.value !== action.value
1046
+ ) {
1048
1047
  throw new UnsupportedOperationError(
1049
- `in bridge mode, keydown for <${action.value}> must be followed`
1050
- + ' by a keyup for the same key');
1048
+ `in bridge mode, keydown for <${action.value}> must be followed` +
1049
+ ' by a keyup for the same key'
1050
+ )
1051
1051
  }
1052
1052
  }
1053
- } else if (action.type === Action.Type.KEY_UP
1054
- && !MODIFIER_KEYS.has(action.value)) {
1055
- next = null;
1053
+ } else if (
1054
+ action.type === Action.Type.KEY_UP &&
1055
+ !MODIFIER_KEYS.has(action.value)
1056
+ ) {
1057
+ next = null
1056
1058
  }
1057
1059
  }
1058
1060
 
1059
1061
  if (next) {
1060
- actions.push(next);
1062
+ actions.push(next)
1061
1063
  }
1062
1064
  }
1063
1065
 
1064
1066
  for (let i = 0; i < actions.length; i++) {
1065
- const action = actions[i];
1067
+ const action = actions[i]
1066
1068
  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];
1069
+ case Action.Type.PAUSE: {
1070
+ await promise.delayed(action.duration || 0)
1071
+ break
1072
+ }
1073
+ case Action.Type.KEY_DOWN: {
1074
+ const keys = [action.value]
1072
1075
  if (!MODIFIER_KEYS.has(action.value)) {
1076
+ // eslint-disable-next-line no-inner-declarations
1073
1077
  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
+ const next = actions[i + 1]
1079
+ return (
1080
+ !!next &&
1081
+ next.type === Action.Type.KEY_DOWN &&
1082
+ !MODIFIER_KEYS.has(next.value)
1083
+ )
1078
1084
  }
1079
1085
  for (; nextIsKeyDown(); i++) {
1080
- keys.push(actions[i + 1].value);
1086
+ keys.push(actions[i + 1].value)
1081
1087
  }
1082
1088
  }
1083
1089
  await executor.execute(
1084
- new Command(Name.LEGACY_ACTION_SEND_KEYS)
1085
- .setParameter('value', keys));
1086
- break;
1087
- case Action.Type.KEY_UP:
1090
+ new Command(Name.LEGACY_ACTION_SEND_KEYS).setParameter('value', keys)
1091
+ )
1092
+ break
1093
+ }
1094
+ case Action.Type.KEY_UP: {
1088
1095
  await executor.execute(
1089
- new Command(Name.LEGACY_ACTION_SEND_KEYS)
1090
- .setParameter('value', [action.value]));
1091
- break;
1096
+ new Command(Name.LEGACY_ACTION_SEND_KEYS).setParameter('value', [
1097
+ action.value,
1098
+ ])
1099
+ )
1100
+ break
1101
+ }
1092
1102
  case Action.Type.POINTER_DOWN: {
1103
+ // eslint-disable-next-line no-inner-declarations
1093
1104
  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;
1105
+ const first = actions[startAt]
1106
+ const second = actions[startAt + 1]
1107
+ return (
1108
+ !!first &&
1109
+ !!second &&
1110
+ first.type === Action.Type.POINTER_DOWN &&
1111
+ second.type === Action.Type.POINTER_UP &&
1112
+ first.button === second.button
1113
+ )
1100
1114
  }
1101
1115
 
1116
+ // eslint-disable-next-line no-inner-declarations
1102
1117
  function isDoubleClick(startAt) {
1103
- return isClick(startAt)
1104
- && isClick(startAt + 2)
1105
- && actions[startAt].button === actions[startAt = 2].button;
1118
+ return (
1119
+ isClick(startAt) &&
1120
+ isClick(startAt + 2) &&
1121
+ actions[startAt].button === actions[(startAt = 2)].button
1122
+ )
1106
1123
  }
1107
1124
 
1108
- let cmd;
1125
+ let cmd
1109
1126
  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;
1127
+ i += 3 // Consume the pointer up/down/up.
1128
+ cmd = Name.LEGACY_ACTION_DOUBLE_CLICK
1129
+ } else if (isClick(i)) {
1130
+ i++ // Consume the pointer-up.
1131
+ cmd = Name.LEGACY_ACTION_CLICK
1115
1132
  } else {
1116
- cmd = Name.LEGACY_ACTION_MOUSE_DOWN;
1133
+ cmd = Name.LEGACY_ACTION_MOUSE_DOWN
1117
1134
  }
1118
1135
  await executor.execute(
1119
- new Command(cmd).setParameter('button', action.button));
1120
- break;
1136
+ new Command(cmd).setParameter('button', action.button)
1137
+ )
1138
+ break
1121
1139
  }
1122
- case Action.Type.POINTER_UP:
1140
+ case Action.Type.POINTER_UP: {
1123
1141
  await executor.execute(
1124
- new Command(Name.LEGACY_ACTION_MOUSE_UP)
1125
- .setParameter('button', action.button));
1126
- break;
1127
- case Action.Type.POINTER_MOVE:
1142
+ new Command(Name.LEGACY_ACTION_MOUSE_UP).setParameter(
1143
+ 'button',
1144
+ action.button
1145
+ )
1146
+ )
1147
+ break
1148
+ }
1149
+ case Action.Type.POINTER_MOVE: {
1128
1150
  if (action.origin === Origin.VIEWPORT) {
1129
1151
  throw new UnsupportedOperationError(
1130
- `pointer movements relative to ${Origin.VIEWPORT} are not`
1131
- + ' supported in bridge mode');
1132
-
1152
+ `pointer movements relative to ${Origin.VIEWPORT} are not` +
1153
+ ' supported in bridge mode'
1154
+ )
1133
1155
  }
1134
1156
 
1135
- let x = action.x;
1136
- let y = action.y;
1137
- const cmd = new Command(Name.LEGACY_ACTION_MOUSE_MOVE);
1157
+ let x = action.x
1158
+ let y = action.y
1159
+ const cmd = new Command(Name.LEGACY_ACTION_MOUSE_MOVE)
1138
1160
  if (action.origin && action.origin !== Origin.POINTER) {
1139
- const el = /** @type {!./webdriver.WebElement} */(action.origin);
1161
+ const el = /** @type {!./webdriver.WebElement} */ (action.origin)
1140
1162
 
1141
1163
  // Need to translate frame of reference from center of element's first
1142
1164
  // client rect to the top-left of its bounding client rect. See:
1143
1165
  // https://w3c.github.io/webdriver/webdriver-spec.html#dfn-center-point
1144
1166
  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);
1167
+ new Command(Name.EXECUTE_SCRIPT)
1168
+ .setParameter('script', INTERNAL_COMPUTE_OFFSET_SCRIPT)
1169
+ .setParameter('args', [el])
1170
+ )
1171
+ x += diff[0]
1172
+ y += diff[1]
1173
+
1174
+ const id = await el.getId()
1175
+ cmd.setParameter('element', id)
1153
1176
  }
1154
- cmd.setParameter('xoffset', x).setParameter('yoffset', y);
1155
- await executor.execute(cmd);
1156
- break;
1157
- default:
1177
+ cmd.setParameter('xoffset', x).setParameter('yoffset', y)
1178
+ await executor.execute(cmd)
1179
+ break
1180
+ }
1181
+ default: {
1158
1182
  throw new UnsupportedOperationError(
1159
- `${action.type} actions not supported in bridge mode`);
1183
+ `${action.type} actions not supported in bridge mode`
1184
+ )
1185
+ }
1160
1186
  }
1161
1187
  }
1162
1188
  }
1163
1189
 
1164
-
1165
1190
  /**
1166
1191
  * Script used to compute the offset from the center of a DOM element's first
1167
1192
  * client rect from the top-left corner of the element's bounding client rect.
@@ -1187,14 +1212,12 @@ function computeOffset(el) {
1187
1212
  var bbox = el.getBoundingClientRect();
1188
1213
  return [x - bbox.left, y - bbox.top];
1189
1214
  }
1190
- return computeOffset(arguments[0]);`;
1191
-
1215
+ return computeOffset(arguments[0]);`
1192
1216
 
1193
1217
  // PUBLIC API
1194
1218
 
1195
-
1196
1219
  module.exports = {
1197
- Action, // For documentation only.
1220
+ Action, // For documentation only.
1198
1221
  Actions,
1199
1222
  Button,
1200
1223
  Device,
@@ -1204,4 +1227,4 @@ module.exports = {
1204
1227
  Origin,
1205
1228
  Pointer,
1206
1229
  INTERNAL_COMPUTE_OFFSET_SCRIPT,
1207
- };
1230
+ }