selenium-webdriver 3.6.0 → 4.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/CHANGES.md +181 -0
  2. package/README.md +25 -27
  3. package/chrome.js +113 -127
  4. package/edge.js +42 -117
  5. package/example/chrome_android.js +8 -8
  6. package/example/chrome_mobile_emulation.js +8 -8
  7. package/example/firefox_channels.js +22 -18
  8. package/example/google_search_test.js +39 -26
  9. package/example/logging.js +39 -6
  10. package/firefox.js +769 -0
  11. package/http/index.js +41 -4
  12. package/http/util.js +11 -6
  13. package/ie.js +56 -97
  14. package/index.js +178 -114
  15. package/jasmine.json +11 -0
  16. package/lib/actions.js +68 -63
  17. package/lib/by.js +1 -1
  18. package/lib/capabilities.js +255 -192
  19. package/lib/command.js +26 -50
  20. package/lib/error.js +85 -44
  21. package/lib/http.js +133 -110
  22. package/lib/input.js +1044 -8
  23. package/lib/promise.js +222 -3323
  24. package/lib/proxy.js +134 -39
  25. package/lib/test/bootstrap_jasmine.js +28 -0
  26. package/lib/test/data/actions/click.html +24 -0
  27. package/lib/test/data/actions/drag.html +77 -0
  28. package/lib/test/data/actions/record_click.html +21 -0
  29. package/lib/test/data/chrome/download.html +2 -0
  30. package/lib/test/data/inputs.html +42 -0
  31. package/lib/test/data/selectPage.html +12 -0
  32. package/lib/test/data/simpleTest.html +5 -0
  33. package/lib/test/data/upload_invisible.html +45 -0
  34. package/lib/test/fileserver.js +23 -19
  35. package/lib/test/index.js +30 -212
  36. package/lib/test/resources.js +0 -1
  37. package/lib/webdriver.js +675 -936
  38. package/net/index.js +21 -25
  39. package/net/portprober.js +51 -68
  40. package/package.json +5 -3
  41. package/remote/index.js +5 -19
  42. package/safari.js +41 -128
  43. package/test/actions_test.js +173 -18
  44. package/test/{session_test.js → builder_test.js} +44 -37
  45. package/test/chrome/devtools_test.js +93 -0
  46. package/test/chrome/options_test.js +48 -154
  47. package/test/chrome/service_test.js +7 -7
  48. package/test/cookie_test.js +77 -63
  49. package/test/element_finding_test.js +206 -201
  50. package/test/execute_script_test.js +115 -114
  51. package/test/fingerprint_test.js +16 -15
  52. package/test/firefox_test.js +251 -0
  53. package/test/http/http_test.js +0 -1
  54. package/test/http/util_test.js +2 -2
  55. package/test/io/zip_test.js +6 -7
  56. package/test/lib/error_test.js +34 -7
  57. package/test/lib/http_test.js +8 -128
  58. package/test/lib/input_test.js +1379 -0
  59. package/test/lib/promise_test.js +473 -908
  60. package/test/lib/webdriver_test.js +296 -868
  61. package/test/logging_test.js +37 -43
  62. package/test/page_loading_test.js +71 -81
  63. package/test/proxy_test.js +64 -72
  64. package/test/rect_test.js +14 -25
  65. package/test/remote_test.js +10 -29
  66. package/test/safari_test.js +7 -71
  67. package/test/stale_element_test.js +20 -23
  68. package/test/tag_name_test.js +10 -9
  69. package/test/upload_test.js +27 -35
  70. package/test/window_test.js +72 -85
  71. package/testing/index.js +386 -314
  72. package/.npmignore +0 -2
  73. package/example/async_await_test.js +0 -69
  74. package/example/google_search_generator.js +0 -47
  75. package/example/parallel_flows.js +0 -51
  76. package/firefox/binary.js +0 -347
  77. package/firefox/extension.js +0 -224
  78. package/firefox/index.js +0 -576
  79. package/firefox/profile.js +0 -311
  80. package/lib/events.js +0 -210
  81. package/lib/test/data/firefox/jetpack-sample.xpi +0 -0
  82. package/lib/test/data/firefox/sample.xpi +0 -0
  83. package/lib/test/promise.js +0 -79
  84. package/opera.js +0 -405
  85. package/phantomjs.js +0 -282
  86. package/test/firefox/extension_test.js +0 -120
  87. package/test/firefox/firefox_test.js +0 -244
  88. package/test/firefox/profile_test.js +0 -140
  89. package/test/lib/events_test.js +0 -177
  90. package/test/lib/promise_aplus_test.js +0 -78
  91. package/test/lib/promise_error_test.js +0 -884
  92. package/test/lib/promise_flow_test.js +0 -2288
  93. package/test/lib/promise_generator_test.js +0 -310
  94. package/test/phantomjs/execute_phantomjs_test.js +0 -59
  95. package/test/testing/assert_test.js +0 -373
  96. package/test/testing/index_test.js +0 -224
  97. package/testing/assert.js +0 -378
@@ -17,76 +17,33 @@
17
17
 
18
18
  'use strict';
19
19
 
20
- const testutil = require('./testutil');
20
+ const {StubError, assertIsInstance, assertIsStubError, throwStubError} =
21
+ require('./testutil');
21
22
 
22
- const By = require('../../lib/by').By;
23
- const Capabilities = require('../../lib/capabilities').Capabilities;
24
- const Executor = require('../../lib/command').Executor;
25
- const CName = require('../../lib/command').Name;
26
23
  const error = require('../../lib/error');
27
- const Button = require('../../lib/input').Button;
28
- const Key = require('../../lib/input').Key;
29
24
  const logging = require('../../lib/logging');
30
- const Session = require('../../lib/session').Session;
31
25
  const promise = require('../../lib/promise');
32
- const {enablePromiseManager, promiseManagerSuite} = require('../../lib/test/promise');
33
26
  const until = require('../../lib/until');
34
- const Alert = require('../../lib/webdriver').Alert;
35
- const AlertPromise = require('../../lib/webdriver').AlertPromise;
36
- const UnhandledAlertError = require('../../lib/webdriver').UnhandledAlertError;
37
- const WebDriver = require('../../lib/webdriver').WebDriver;
38
- const WebElement = require('../../lib/webdriver').WebElement;
39
- const WebElementPromise = require('../../lib/webdriver').WebElementPromise;
27
+ const {Alert, AlertPromise, WebDriver, WebElement, WebElementPromise} =
28
+ require('../../lib/webdriver');
29
+ const {Button, Key} = require('../../lib/input');
30
+ const {By} = require('../../lib/by');
31
+ const {Capabilities} = require('../../lib/capabilities');
32
+ const {Executor, Name} = require('../../lib/command');
33
+ const {Session} = require('../../lib/session');
40
34
 
41
35
  const assert = require('assert');
42
36
  const sinon = require('sinon');
43
37
 
44
- const SESSION_ID = 'test_session_id';
38
+ const CName = Name;
45
39
 
46
- // Aliases for readability.
47
- const NativePromise = Promise;
48
- const StubError = testutil.StubError;
49
- const assertIsInstance = testutil.assertIsInstance;
50
- const assertIsStubError = testutil.assertIsStubError;
51
- const throwStubError = testutil.throwStubError;
40
+ const SESSION_ID = 'test_session_id';
52
41
  const fail = (msg) => assert.fail(msg);
53
42
 
54
43
  describe('WebDriver', function() {
55
44
  const LOG = logging.getLogger('webdriver.test');
56
45
 
57
- // before(function() {
58
- // logging.getLogger('webdriver').setLevel(logging.Level.ALL);
59
- // logging.installConsoleHandler();
60
- // });
61
-
62
- // after(function() {
63
- // logging.getLogger('webdriver').setLevel(null);
64
- // logging.removeConsoleHandler();
65
- // });
66
-
67
46
  var driver;
68
- var flow;
69
- var uncaughtExceptions;
70
-
71
- beforeEach(function setUp() {
72
- flow = promise.controlFlow();
73
- uncaughtExceptions = [];
74
- flow.on('uncaughtException', onUncaughtException);
75
- });
76
-
77
- afterEach(function tearDown() {
78
- if (!promise.USE_PROMISE_MANAGER) {
79
- return;
80
- }
81
- return waitForIdle(flow).then(function() {
82
- assert.deepEqual([], uncaughtExceptions);
83
- flow.reset();
84
- });
85
- });
86
-
87
- function onUncaughtException(e) {
88
- uncaughtExceptions.push(e);
89
- }
90
47
 
91
48
  function defer() {
92
49
  let d = {};
@@ -97,43 +54,6 @@ describe('WebDriver', function() {
97
54
  return d;
98
55
  }
99
56
 
100
- function waitForIdle(opt_flow) {
101
- if (!promise.USE_PROMISE_MANAGER) {
102
- return Promise.resolve();
103
- }
104
- var theFlow = opt_flow || flow;
105
- return new Promise(function(fulfill, reject) {
106
- if (theFlow.isIdle()) {
107
- fulfill();
108
- return;
109
- }
110
- theFlow.once('idle', fulfill);
111
- theFlow.once('uncaughtException', reject);
112
- });
113
- }
114
-
115
- function waitForAbort(opt_flow, opt_n) {
116
- var n = opt_n || 1;
117
- var theFlow = opt_flow || flow;
118
- theFlow.removeAllListeners(
119
- promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION);
120
- return new Promise(function(fulfill, reject) {
121
- theFlow.once('idle', function() {
122
- reject(Error('expected flow to report an unhandled error'));
123
- });
124
-
125
- var errors = [];
126
- theFlow.on('uncaughtException', onError);
127
- function onError(e) {
128
- errors.push(e);
129
- if (errors.length === n) {
130
- theFlow.removeListener('uncaughtException', onError);
131
- fulfill(n === 1 ? errors[0] : errors);
132
- }
133
- }
134
- });
135
- }
136
-
137
57
  function expectedError(ctor, message) {
138
58
  return function(e) {
139
59
  assertIsInstance(ctor, e);
@@ -210,7 +130,7 @@ describe('WebDriver', function() {
210
130
  }
211
131
 
212
132
  execute(command) {
213
- assert.deepEqual(this.parameters_, command.getParameters());
133
+ assert.deepEqual(command.getParameters(), this.parameters_);
214
134
  return this.toDo_(command);
215
135
  }
216
136
  }
@@ -261,87 +181,16 @@ describe('WebDriver', function() {
261
181
  /////////////////////////////////////////////////////////////////////////////
262
182
 
263
183
 
264
- describe('testAttachToSession', function() {
265
- it('sessionIsAvailable', function() {
266
- let aSession = new Session(SESSION_ID, {'browserName': 'firefox'});
267
- let executor = new FakeExecutor().
268
- expect(CName.DESCRIBE_SESSION).
269
- withParameters({'sessionId': SESSION_ID}).
270
- andReturnSuccess(aSession).
271
- end();
272
-
273
- let driver = WebDriver.attachToSession(executor, SESSION_ID);
274
- return driver.getSession().then(v => assert.strictEqual(v, aSession));
275
- });
276
-
277
- it('failsToGetSessionInfo', function() {
278
- let e = new Error('boom');
279
- let executor = new FakeExecutor().
280
- expect(CName.DESCRIBE_SESSION).
281
- withParameters({'sessionId': SESSION_ID}).
282
- andReturnError(e).
283
- end();
284
-
285
- let driver = WebDriver.attachToSession(executor, SESSION_ID);
286
- return driver.getSession()
287
- .then(() => assert.fail('should have failed!'),
288
- (actual) => assert.strictEqual(actual, e));
289
- });
290
-
291
- it('remote end does not recognize DESCRIBE_SESSION command', function() {
292
- let e = new error.UnknownCommandError;
293
- let executor = new FakeExecutor().
294
- expect(CName.DESCRIBE_SESSION).
295
- withParameters({'sessionId': SESSION_ID}).
296
- andReturnError(e).
297
- end();
298
-
299
- let driver = WebDriver.attachToSession(executor, SESSION_ID);
300
- return driver.getSession().then(session => {
301
- assert.ok(session instanceof Session);
302
- assert.strictEqual(session.getId(), SESSION_ID);
303
- assert.equal(session.getCapabilities().size, 0);
304
- });
305
- });
306
-
307
- it('usesActiveFlowByDefault', function() {
308
- let executor = new FakeExecutor().
309
- expect(CName.DESCRIBE_SESSION).
310
- withParameters({'sessionId': SESSION_ID}).
311
- andReturnSuccess({}).
312
- end();
313
-
314
- var driver = WebDriver.attachToSession(executor, SESSION_ID);
315
- assert.equal(driver.controlFlow(), promise.controlFlow());
316
-
317
- return waitForIdle(driver.controlFlow());
318
- });
319
-
320
- enablePromiseManager(() => {
321
- it('canAttachInCustomFlow', function() {
322
- let executor = new FakeExecutor().
323
- expect(CName.DESCRIBE_SESSION).
324
- withParameters({'sessionId': SESSION_ID}).
325
- andReturnSuccess({}).
326
- end();
327
-
328
- var otherFlow = new promise.ControlFlow();
329
- var driver = WebDriver.attachToSession(executor, SESSION_ID, otherFlow);
330
- assert.equal(otherFlow, driver.controlFlow());
331
- assert.notEqual(otherFlow, promise.controlFlow());
332
-
333
- return waitForIdle(otherFlow);
334
- });
335
- });
336
- });
337
-
338
184
  describe('testCreateSession', function() {
339
185
  it('happyPathWithCapabilitiesHashObject', function() {
340
186
  let aSession = new Session(SESSION_ID, {'browserName': 'firefox'});
341
187
  let executor = new FakeExecutor().
342
188
  expect(CName.NEW_SESSION).
343
189
  withParameters({
344
- 'desiredCapabilities': {'browserName': 'firefox'}
190
+ 'desiredCapabilities': {'browserName': 'firefox'},
191
+ 'capabilities': {
192
+ 'alwaysMatch': {'browserName': 'firefox'},
193
+ },
345
194
  }).
346
195
  andReturnSuccess(aSession).
347
196
  end();
@@ -356,7 +205,12 @@ describe('WebDriver', function() {
356
205
  let aSession = new Session(SESSION_ID, {'browserName': 'firefox'});
357
206
  let executor = new FakeExecutor().
358
207
  expect(CName.NEW_SESSION).
359
- withParameters({'desiredCapabilities': {'browserName': 'firefox'}}).
208
+ withParameters({
209
+ 'desiredCapabilities': {'browserName': 'firefox'},
210
+ 'capabilities': {
211
+ 'alwaysMatch': {'browserName': 'firefox'},
212
+ },
213
+ }).
360
214
  andReturnSuccess(aSession).
361
215
  end();
362
216
 
@@ -364,27 +218,35 @@ describe('WebDriver', function() {
364
218
  return driver.getSession().then(v => assert.strictEqual(v, aSession));
365
219
  });
366
220
 
367
- it('handles desired and required capabilities', function() {
221
+ it('drops non-W3C capability names from W3C capabilities', function() {
368
222
  let aSession = new Session(SESSION_ID, {'browserName': 'firefox'});
369
223
  let executor = new FakeExecutor().
370
224
  expect(CName.NEW_SESSION).
371
225
  withParameters({
372
- 'desiredCapabilities': {'foo': 'bar'},
373
- 'requiredCapabilities': {'bim': 'baz'}
226
+ 'desiredCapabilities': {'browserName': 'firefox', 'foo': 'bar'},
227
+ 'capabilities': {
228
+ 'alwaysMatch': {'browserName': 'firefox'},
229
+ },
374
230
  }).
375
231
  andReturnSuccess(aSession).
376
232
  end();
377
233
 
378
- let desired = new Capabilities().set('foo', 'bar');
379
- let required = new Capabilities().set('bim', 'baz');
380
- var driver = WebDriver.createSession(executor, {desired, required});
234
+ var driver = WebDriver.createSession(executor, {
235
+ 'browserName': 'firefox',
236
+ 'foo': 'bar',
237
+ });
381
238
  return driver.getSession().then(v => assert.strictEqual(v, aSession));
382
239
  });
383
240
 
384
241
  it('failsToCreateSession', function() {
385
242
  let executor = new FakeExecutor().
386
243
  expect(CName.NEW_SESSION).
387
- withParameters({'desiredCapabilities': {'browserName': 'firefox'}}).
244
+ withParameters({
245
+ 'desiredCapabilities': {'browserName': 'firefox'},
246
+ 'capabilities': {
247
+ 'alwaysMatch': {'browserName': 'firefox'},
248
+ },
249
+ }).
388
250
  andReturnError(new StubError()).
389
251
  end();
390
252
 
@@ -397,78 +259,23 @@ describe('WebDriver', function() {
397
259
  let called = false;
398
260
  let executor = new FakeExecutor()
399
261
  .expect(CName.NEW_SESSION)
400
- .withParameters({'desiredCapabilities': {'browserName': 'firefox'}})
262
+ .withParameters({
263
+ 'desiredCapabilities': {'browserName': 'firefox'},
264
+ 'capabilities': {
265
+ 'alwaysMatch': {'browserName': 'firefox'},
266
+ },
267
+ })
401
268
  .andReturnError(new StubError())
402
269
  .end();
403
270
 
404
- var driver =
405
- WebDriver.createSession(executor, {'browserName': 'firefox'},
406
- null, () => called = true);
271
+ let driver =
272
+ WebDriver.createSession(
273
+ executor, {'browserName': 'firefox'}, () => called = true);
407
274
  return driver.getSession().then(fail, err => {
408
275
  assert.ok(called);
409
276
  assertIsStubError(err);
410
277
  });
411
278
  });
412
-
413
- it('usesActiveFlowByDefault', function() {
414
- let executor = new FakeExecutor().
415
- expect(CName.NEW_SESSION).
416
- withParameters({'desiredCapabilities': {}}).
417
- andReturnSuccess(new Session(SESSION_ID)).
418
- end();
419
-
420
- var driver = WebDriver.createSession(executor, {});
421
- assert.equal(promise.controlFlow(), driver.controlFlow());
422
-
423
- return waitForIdle(driver.controlFlow());
424
- });
425
-
426
- enablePromiseManager(() => {
427
- it('canCreateInCustomFlow', function() {
428
- let executor = new FakeExecutor().
429
- expect(CName.NEW_SESSION).
430
- withParameters({'desiredCapabilities': {}}).
431
- andReturnSuccess({}).
432
- end();
433
-
434
- var otherFlow = new promise.ControlFlow();
435
- var driver = WebDriver.createSession(executor, {}, otherFlow);
436
- assert.equal(otherFlow, driver.controlFlow());
437
- assert.notEqual(otherFlow, promise.controlFlow());
438
-
439
- return waitForIdle(otherFlow);
440
- });
441
-
442
- describe('creation failures bubble up in control flow', function() {
443
- function runTest(...args) {
444
- let executor = new FakeExecutor()
445
- .expect(CName.NEW_SESSION)
446
- .withParameters({'desiredCapabilities': {'browserName': 'firefox'}})
447
- .andReturnError(new StubError())
448
- .end();
449
-
450
- WebDriver.createSession(
451
- executor, {'browserName': 'firefox'}, ...args);
452
- return waitForAbort().then(assertIsStubError);
453
- }
454
-
455
- it('no onQuit callback', () => runTest());
456
- it('has onQuit callback', () => runTest(null, null, function() {}));
457
-
458
- it('onQuit callback failure suppress creation failure', function() {
459
- let e = new Error('hi!');
460
- let executor = new FakeExecutor()
461
- .expect(CName.NEW_SESSION)
462
- .withParameters({'desiredCapabilities': {'browserName': 'firefox'}})
463
- .andReturnError(new StubError())
464
- .end();
465
-
466
- WebDriver.createSession(
467
- executor, {'browserName': 'firefox'}, null, () => {throw e});
468
- return waitForAbort().then(err => assert.strictEqual(err, e));
469
- });
470
- });
471
- });
472
279
  });
473
280
 
474
281
  it('testDoesNotExecuteCommandIfSessionDoesNotResolve', function() {
@@ -506,26 +313,6 @@ describe('WebDriver', function() {
506
313
  v => assert.strictEqual(v, e));
507
314
  });
508
315
 
509
- it('testCanSuppressCommandFailures', function() {
510
- let e = new error.NoSuchWindowError('window not found');
511
- let executor = new FakeExecutor().
512
- expect(CName.SWITCH_TO_WINDOW).
513
- withParameters({
514
- 'name': 'foo',
515
- 'handle': 'foo'
516
- }).
517
- andReturnError(e).
518
- expect(CName.GET_TITLE).
519
- andReturnSuccess('Google Search').
520
- end();
521
-
522
- var driver = executor.createDriver();
523
- driver.switchTo().window('foo')
524
- .catch(v => assert.strictEqual(v, e));
525
- driver.getTitle();
526
- return waitForIdle();
527
- });
528
-
529
316
  it('testErrorsPropagateUpToTheRunningApplication', function() {
530
317
  let e = new error.NoSuchWindowError('window not found');
531
318
  let executor = new FakeExecutor().
@@ -589,53 +376,6 @@ describe('WebDriver', function() {
589
376
  .then(assert.fail, verifyError);
590
377
  });
591
378
 
592
- it('testCallbackCommandsExecuteBeforeNextCommand', function() {
593
- let executor = new FakeExecutor().
594
- expect(CName.GET_CURRENT_URL).
595
- expect(CName.GET, {'url': 'http://www.google.com'}).
596
- expect(CName.CLOSE).
597
- expect(CName.GET_TITLE).
598
- end();
599
-
600
- var driver = executor.createDriver();
601
- driver.getCurrentUrl().then(function() {
602
- driver.get('http://www.google.com').then(function() {
603
- driver.close();
604
- });
605
- });
606
- driver.getTitle();
607
-
608
- return waitForIdle();
609
- });
610
-
611
- enablePromiseManager(() => {
612
- it('testEachCallbackFrameRunsToCompletionBeforeTheNext', function() {
613
- let executor = new FakeExecutor().
614
- expect(CName.GET_TITLE).
615
- expect(CName.GET_CURRENT_URL).
616
- expect(CName.GET_CURRENT_WINDOW_HANDLE).
617
- expect(CName.CLOSE).
618
- expect(CName.QUIT).
619
- end();
620
-
621
- var driver = executor.createDriver();
622
- driver.getTitle().
623
- // Everything in this callback...
624
- then(function() {
625
- driver.getCurrentUrl();
626
- driver.getWindowHandle();
627
- }).
628
- // ...should execute before everything in this callback.
629
- then(function() {
630
- driver.close();
631
- });
632
- // This should execute after everything above
633
- driver.quit();
634
-
635
- return waitForIdle();
636
- });
637
- });
638
-
639
379
  describe('returningAPromise', function() {
640
380
  it('fromACallback', function() {
641
381
  let executor = new FakeExecutor().
@@ -675,274 +415,6 @@ describe('WebDriver', function() {
675
415
  });
676
416
  });
677
417
 
678
- describe('customFunctions', function() {
679
- it('returnsANonPromiseValue', function() {
680
- var driver = new FakeExecutor().createDriver();
681
- return driver.call(() => 'abc123').then(function(value) {
682
- assert.equal('abc123', value);
683
- });
684
- });
685
-
686
- enablePromiseManager(() => {
687
- it('executionOrderWithCustomFunctions', function() {
688
- var msg = [];
689
- let executor = new FakeExecutor().
690
- expect(CName.GET_TITLE).andReturnSuccess('cheese ').
691
- expect(CName.GET_CURRENT_URL).andReturnSuccess('tasty').
692
- end();
693
-
694
- var driver = executor.createDriver();
695
-
696
- var pushMsg = msg.push.bind(msg);
697
- driver.getTitle().then(pushMsg);
698
- driver.call(() => 'is ').then(pushMsg);
699
- driver.getCurrentUrl().then(pushMsg);
700
- driver.call(() => '!').then(pushMsg);
701
-
702
- return waitForIdle().then(function() {
703
- assert.equal('cheese is tasty!', msg.join(''));
704
- });
705
- });
706
- });
707
-
708
- it('passingArgumentsToACustomFunction', function() {
709
- var add = function(a, b) {
710
- return a + b;
711
- };
712
- var driver = new FakeExecutor().createDriver();
713
- return driver.call(add, null, 1, 2).then(function(value) {
714
- assert.equal(3, value);
715
- });
716
- });
717
-
718
- it('passingPromisedArgumentsToACustomFunction', function() {
719
- var promisedArg = Promise.resolve(2);
720
- var add = function(a, b) {
721
- return a + b;
722
- };
723
- var driver = new FakeExecutor().createDriver();
724
- return driver.call(add, null, 1, promisedArg).then(function(value) {
725
- assert.equal(3, value);
726
- });
727
- });
728
-
729
- it('passingArgumentsAndScopeToACustomFunction', function() {
730
- function Foo(name) {
731
- this.name = name;
732
- }
733
- Foo.prototype.getName = function() {
734
- return this.name;
735
- };
736
- var foo = new Foo('foo');
737
-
738
- var driver = new FakeExecutor().createDriver();
739
- return driver.call(foo.getName, foo).then(function(value) {
740
- assert.equal('foo', value);
741
- });
742
- });
743
-
744
- it('customFunctionThrowsAnError', function() {
745
- var driver = new FakeExecutor().createDriver();
746
- return driver.call(throwStubError).then(fail, assertIsStubError);
747
- });
748
-
749
- it('customFunctionSchedulesCommands', function() {
750
- let executor = new FakeExecutor().
751
- expect(CName.GET_TITLE).
752
- expect(CName.CLOSE).
753
- expect(CName.QUIT).
754
- end();
755
-
756
- var driver = executor.createDriver();
757
- driver.call(function() {
758
- driver.getTitle();
759
- driver.close();
760
- });
761
- driver.quit();
762
- return waitForIdle();
763
- });
764
-
765
- it('returnsATaskResultAfterSchedulingAnother', function() {
766
- let executor = new FakeExecutor().
767
- expect(CName.GET_TITLE).
768
- andReturnSuccess('Google Search').
769
- expect(CName.CLOSE).
770
- end();
771
-
772
- var driver = executor.createDriver();
773
- return driver.call(function() {
774
- var title = driver.getTitle();
775
- driver.close();
776
- return title;
777
- }).then(function(title) {
778
- assert.equal('Google Search', title);
779
- });
780
- });
781
-
782
- it('hasANestedCommandThatFails', function() {
783
- let executor = new FakeExecutor().
784
- expect(CName.SWITCH_TO_WINDOW, {
785
- 'name': 'foo',
786
- 'handle': 'foo'
787
- }).
788
- andReturnError(new StubError()).
789
- end();
790
-
791
- var driver = executor.createDriver();
792
- return driver.call(function() {
793
- return driver.switchTo().window('foo');
794
- }).then(fail, assertIsStubError);
795
- });
796
-
797
- enablePromiseManager(() => {
798
- it('doesNotCompleteUntilReturnedPromiseIsResolved', function() {
799
- var order = [];
800
- var driver = new FakeExecutor().createDriver();
801
-
802
- var d = promise.defer();
803
- d.promise.then(function() {
804
- order.push('b');
805
- });
806
-
807
- driver.call(function() {
808
- order.push('a');
809
- return d.promise;
810
- });
811
- driver.call(function() {
812
- order.push('c');
813
- });
814
-
815
- // timeout to ensure the first function starts its execution before we
816
- // trigger d's callbacks.
817
- return new Promise(f => setTimeout(f, 0)).then(function() {
818
- assert.deepEqual(['a'], order);
819
- d.fulfill();
820
- return waitForIdle().then(function() {
821
- assert.deepEqual(['a', 'b', 'c'], order);
822
- });
823
- });
824
- });
825
- });
826
-
827
- it('returnsADeferredAction', function() {
828
- let executor = new FakeExecutor().
829
- expect(CName.GET_TITLE).andReturnSuccess('Google').
830
- end();
831
-
832
- var driver = executor.createDriver();
833
- driver.call(function() {
834
- return driver.getTitle();
835
- }).then(function(title) {
836
- assert.equal('Google', title);
837
- });
838
- return waitForIdle();
839
- });
840
- });
841
-
842
- describe('nestedCommands', function() {
843
- enablePromiseManager(() => {
844
- it('commandExecutionOrder', function() {
845
- var msg = [];
846
- var driver = new FakeExecutor().createDriver();
847
- driver.call(msg.push, msg, 'a');
848
- driver.call(function() {
849
- driver.call(msg.push, msg, 'c');
850
- driver.call(function() {
851
- driver.call(msg.push, msg, 'e');
852
- driver.call(msg.push, msg, 'f');
853
- });
854
- driver.call(msg.push, msg, 'd');
855
- });
856
- driver.call(msg.push, msg, 'b');
857
- return waitForIdle().then(function() {
858
- assert.equal('acefdb', msg.join(''));
859
- });
860
- });
861
-
862
- it('basicUsage', function() {
863
- var msg = [];
864
- var driver = new FakeExecutor().createDriver();
865
- var pushMsg = msg.push.bind(msg);
866
- driver.call(() => 'cheese ').then(pushMsg);
867
- driver.call(function() {
868
- driver.call(() => 'is ').then(pushMsg);
869
- driver.call(() => 'tasty').then(pushMsg);
870
- });
871
- driver.call(() => '!').then(pushMsg);
872
- return waitForIdle().then(function() {
873
- assert.equal('cheese is tasty!', msg.join(''));
874
- });
875
- });
876
-
877
- it('normalCommandAfterNestedCommandThatReturnsAnAction', function() {
878
- var msg = [];
879
- let executor = new FakeExecutor().
880
- expect(CName.CLOSE).
881
- end();
882
- var driver = executor.createDriver();
883
- driver.call(function() {
884
- return driver.call(function() {
885
- msg.push('a');
886
- return driver.call(() => 'foobar');
887
- });
888
- });
889
- driver.close().then(function() {
890
- msg.push('b');
891
- });
892
- return waitForIdle().then(function() {
893
- assert.equal('ab', msg.join(''));
894
- });
895
- });
896
- });
897
-
898
- it('canReturnValueFromNestedFunction', function() {
899
- var driver = new FakeExecutor().createDriver();
900
- return driver.call(function() {
901
- return driver.call(function() {
902
- return driver.call(() => 'foobar');
903
- });
904
- }).then(function(value) {
905
- assert.equal('foobar', value);
906
- });
907
- });
908
-
909
- it('errorsBubbleUp_caught', function() {
910
- var driver = new FakeExecutor().createDriver();
911
- var result = driver.call(function() {
912
- return driver.call(function() {
913
- return driver.call(throwStubError);
914
- });
915
- }).then(fail, assertIsStubError);
916
- return Promise.all([waitForIdle(), result]);
917
- });
918
-
919
- it('errorsBubbleUp_uncaught', function() {
920
- var driver = new FakeExecutor().createDriver();
921
- return driver.call(function() {
922
- return driver.call(function() {
923
- return driver.call(throwStubError);
924
- });
925
- })
926
- .then(_ => assert.fail('should have failed'), assertIsStubError);
927
- });
928
-
929
- it('canScheduleCommands', function() {
930
- let executor = new FakeExecutor().
931
- expect(CName.GET_TITLE).
932
- expect(CName.CLOSE).
933
- end();
934
-
935
- var driver = executor.createDriver();
936
- driver.call(function() {
937
- driver.call(function() {
938
- driver.getTitle();
939
- });
940
- driver.close();
941
- });
942
- return waitForIdle();
943
- });
944
- });
945
-
946
418
  describe('WebElementPromise', function() {
947
419
  let driver = new FakeExecutor().createDriver();
948
420
 
@@ -1227,8 +699,7 @@ describe('WebDriver', function() {
1227
699
 
1228
700
  var driver = executor.createDriver();
1229
701
  var element = driver.findElement(By.id('foo'));
1230
- element.click();
1231
- return waitForIdle();
702
+ return element.click();
1232
703
  });
1233
704
 
1234
705
  it('canUseElementInCallback', function() {
@@ -1241,10 +712,7 @@ describe('WebDriver', function() {
1241
712
  end();
1242
713
 
1243
714
  var driver = executor.createDriver();
1244
- driver.findElement(By.id('foo')).then(function(element) {
1245
- element.click();
1246
- });
1247
- return waitForIdle();
715
+ return driver.findElement(By.id('foo')).then(e => e.click());
1248
716
  });
1249
717
 
1250
718
  it('byJs', function() {
@@ -1258,9 +726,8 @@ describe('WebDriver', function() {
1258
726
  end();
1259
727
 
1260
728
  var driver = executor.createDriver();
1261
- var element = driver.findElement(By.js('return document.body'));
1262
- element.click(); // just to make sure
1263
- return waitForIdle();
729
+ return driver.findElement(By.js('return document.body'))
730
+ .then(e => e.click());
1264
731
  });
1265
732
 
1266
733
  it('byJs_returnsNonWebElementValue', function() {
@@ -1288,8 +755,7 @@ describe('WebDriver', function() {
1288
755
  andReturnSuccess(WebElement.buildId('one')).
1289
756
  end();
1290
757
  var driver = executor.createDriver();
1291
- driver.findElement(By.js(script, 'div'));
1292
- return waitForIdle();
758
+ return driver.findElement(By.js(script, 'div'));
1293
759
  });
1294
760
 
1295
761
  it('customLocator', function() {
@@ -1332,7 +798,7 @@ describe('WebDriver', function() {
1332
798
  var driver = executor.createDriver();
1333
799
  return driver.findElements(By.tagName('a'))
1334
800
  .then(function(elements) {
1335
- return promise.all(elements.map(function(e) {
801
+ return Promise.all(elements.map(function(e) {
1336
802
  assert.ok(e instanceof WebElement);
1337
803
  return e.getId();
1338
804
  }));
@@ -1355,7 +821,7 @@ describe('WebDriver', function() {
1355
821
  return driver.
1356
822
  findElements(By.js('return document.getElementsByTagName("div");')).
1357
823
  then(function(elements) {
1358
- return promise.all(elements.map(function(e) {
824
+ return Promise.all(elements.map(function(e) {
1359
825
  assert.ok(e instanceof WebElement);
1360
826
  return e.getId();
1361
827
  }));
@@ -1383,15 +849,14 @@ describe('WebDriver', function() {
1383
849
  end();
1384
850
 
1385
851
  var driver = executor.createDriver();
1386
- driver.findElements(By.js('return document.getElementsByTagName("div");')).
852
+ return driver.findElements(By.js('return document.getElementsByTagName("div");')).
1387
853
  then(function(elements) {
1388
- return promise.all(elements.map(function(e) {
854
+ return Promise.all(elements.map(function(e) {
1389
855
  assert.ok(e instanceof WebElement);
1390
856
  return e.getId();
1391
857
  }));
1392
858
  }).
1393
859
  then((actual) => assert.deepEqual(ids, actual));
1394
- return waitForIdle();
1395
860
  });
1396
861
 
1397
862
  it('byJs_convertsSingleWebElementResponseToArray', function() {
@@ -1407,7 +872,7 @@ describe('WebDriver', function() {
1407
872
  return driver.
1408
873
  findElements(By.js('return document.getElementsByTagName("div");')).
1409
874
  then(function(elements) {
1410
- return promise.all(elements.map(function(e) {
875
+ return Promise.all(elements.map(function(e) {
1411
876
  assert.ok(e instanceof WebElement);
1412
877
  return e.getId();
1413
878
  }));
@@ -1431,7 +896,7 @@ describe('WebDriver', function() {
1431
896
  var driver = executor.createDriver();
1432
897
  return driver.findElements(By.js(script, 'div'))
1433
898
  then(function(elements) {
1434
- return promise.all(elements.map(function(e) {
899
+ return Promise.all(elements.map(function(e) {
1435
900
  assert.ok(e instanceof WebElement);
1436
901
  return e.getId();
1437
902
  }));
@@ -1452,8 +917,7 @@ describe('WebDriver', function() {
1452
917
 
1453
918
  var driver = executor.createDriver();
1454
919
  var element = new WebElement(driver, 'one');
1455
- element.sendKeys(1, 2, 'abc', 3);
1456
- return waitForIdle();
920
+ return element.sendKeys(1, 2, 'abc', 3);
1457
921
  });
1458
922
 
1459
923
  it('convertsVarArgsIntoStrings_promisedArgs', function() {
@@ -1512,8 +976,7 @@ describe('WebDriver', function() {
1512
976
  andReturnSuccess().
1513
977
  end();
1514
978
 
1515
- executor.createDriver().switchTo().window('foo');
1516
- return waitForIdle();
979
+ return executor.createDriver().switchTo().window('foo');
1517
980
  });
1518
981
 
1519
982
  it('should propagate exceptions', function() {
@@ -1552,6 +1015,174 @@ describe('WebDriver', function() {
1552
1015
  });
1553
1016
 
1554
1017
  describe('waiting', function() {
1018
+ it('on a condition that always returns true', function() {
1019
+ let executor = new FakeExecutor();
1020
+ let driver = executor.createDriver();
1021
+ let count = 0;
1022
+ function condition() {
1023
+ count++;
1024
+ return true;
1025
+ }
1026
+ return driver.wait(condition, 1)
1027
+ .then(() => assert.equal(1, count));
1028
+ });
1029
+
1030
+ it('on a simple counting condition', function() {
1031
+ let executor = new FakeExecutor();
1032
+ let driver = executor.createDriver();
1033
+ let count = 0;
1034
+ function condition() {
1035
+ return ++count === 3;
1036
+ }
1037
+ return driver.wait(condition, 250)
1038
+ .then(() => assert.equal(3, count));
1039
+ });
1040
+
1041
+ it('on a condition that returns a promise', function() {
1042
+ let executor = new FakeExecutor();
1043
+ let driver = executor.createDriver();
1044
+
1045
+ let count = 0;
1046
+ function condition() {
1047
+ count += 1;
1048
+ return new Promise(resolve => {
1049
+ setTimeout(() => resolve(true), 50);
1050
+ });
1051
+ }
1052
+
1053
+ return driver.wait(condition, 75)
1054
+ .then(() => assert.equal(1, count));
1055
+ });
1056
+
1057
+ it('on a condition that returns a promise', function() {
1058
+ let executor = new FakeExecutor();
1059
+ let driver = executor.createDriver();
1060
+
1061
+ let count = 0;
1062
+ function condition() {
1063
+ count += 1;
1064
+ return new Promise(resolve => {
1065
+ setTimeout(() => resolve(count === 3), 25);
1066
+ });
1067
+ }
1068
+
1069
+ return driver.wait(condition, 100)
1070
+ .then(() => assert.equal(3, count));
1071
+ });
1072
+
1073
+ it('fails if condition throws', function() {
1074
+ let executor = new FakeExecutor();
1075
+ let driver = executor.createDriver();
1076
+ return driver.wait(throwStubError, 0, 'goes boom')
1077
+ .then(fail, assertIsStubError);
1078
+ });
1079
+
1080
+ it('fails if condition returns a rejected promise', function() {
1081
+ let executor = new FakeExecutor();
1082
+ let driver = executor.createDriver();
1083
+ function condition() {
1084
+ return new Promise((_, reject) => reject(new StubError));
1085
+ }
1086
+ return driver.wait(condition, 0, 'goes boom')
1087
+ .then(fail, assertIsStubError);
1088
+ });
1089
+
1090
+ it('waits forever on a zero timeout', function() {
1091
+ let done = false;
1092
+ setTimeout(() => done = true, 150);
1093
+
1094
+ let executor = new FakeExecutor();
1095
+ let driver = executor.createDriver();
1096
+ let waitResult = driver.wait(() => done, 0);
1097
+
1098
+ return driver.sleep(75).then(function() {
1099
+ assert.ok(!done);
1100
+ return driver.sleep(100);
1101
+ }).then(function() {
1102
+ assert.ok(done);
1103
+ return waitResult;
1104
+ });
1105
+ });
1106
+
1107
+ it('waits forever if timeout omitted', function() {
1108
+ let done = false;
1109
+ setTimeout(() => done = true, 150);
1110
+
1111
+ let executor = new FakeExecutor();
1112
+ let driver = executor.createDriver();
1113
+ let waitResult = driver.wait(() => done);
1114
+
1115
+ return driver.sleep(75).then(function() {
1116
+ assert.ok(!done);
1117
+ return driver.sleep(100);
1118
+ }).then(function() {
1119
+ assert.ok(done);
1120
+ return waitResult;
1121
+ });
1122
+ });
1123
+
1124
+ it('times out when timer expires', function() {
1125
+ let executor = new FakeExecutor();
1126
+ let driver = executor.createDriver();
1127
+
1128
+ let count = 0;
1129
+ let wait = driver.wait(function() {
1130
+ count += 1;
1131
+ let ms = count === 2 ? 65 : 5;
1132
+ return promise.delayed(ms).then(function() {
1133
+ return false;
1134
+ });
1135
+ }, 60, 'counting to 3')
1136
+
1137
+ return wait.then(fail, function(e) {
1138
+ assert.equal(2, count);
1139
+ assert.ok(e instanceof error.TimeoutError, 'Unexpected error: ' + e);
1140
+ assert.ok(
1141
+ /^counting to 3\nWait timed out after \d+ms$/.test(e.message));
1142
+ });
1143
+ });
1144
+
1145
+ it('requires condition to be a promise or function', function() {
1146
+ let executor = new FakeExecutor();
1147
+ let driver = executor.createDriver();
1148
+ assert.throws(() => driver.wait(1234, 0));
1149
+ });
1150
+
1151
+ it('promise that does not resolve before timeout', function() {
1152
+ let d = defer();
1153
+
1154
+ let executor = new FakeExecutor();
1155
+ let driver = executor.createDriver();
1156
+ return driver.wait(d.promise, 5).then(fail, e => {
1157
+ assert.ok(e instanceof error.TimeoutError, 'Unexpected error: ' + e);
1158
+ assert.ok(
1159
+ /Timed out waiting for promise to resolve after \d+ms/
1160
+ .test(e.message),
1161
+ 'unexpected error message: ' + e.message);
1162
+ });
1163
+ });
1164
+
1165
+ it('unbounded wait on promise resolution', function() {
1166
+ let messages = [];
1167
+ let d = defer();
1168
+
1169
+ let executor = new FakeExecutor();
1170
+ let driver = executor.createDriver();
1171
+ let waitResult = driver.wait(d.promise).then(function(value) {
1172
+ messages.push('b');
1173
+ assert.equal(1234, value);
1174
+ });
1175
+
1176
+ setTimeout(() => messages.push('a'), 5);
1177
+ return driver.sleep(10).then(function() {
1178
+ assert.deepEqual(['a'], messages);
1179
+ d.resolve(1234);
1180
+ return waitResult;
1181
+ }).then(function() {
1182
+ assert.deepEqual(['a', 'b'], messages);
1183
+ });
1184
+ });
1185
+
1555
1186
  describe('supports custom wait functions', function() {
1556
1187
  it('waitSucceeds', function() {
1557
1188
  let executor = new FakeExecutor().
@@ -1565,10 +1196,9 @@ describe('WebDriver', function() {
1565
1196
  end();
1566
1197
 
1567
1198
  var driver = executor.createDriver();
1568
- driver.wait(function() {
1199
+ return driver.wait(function() {
1569
1200
  return driver.findElements(By.id('foo')).then(els => els.length > 0);
1570
1201
  }, 200);
1571
- return waitForIdle();
1572
1202
  });
1573
1203
 
1574
1204
  it('waitTimesout_timeoutCaught', function() {
@@ -1587,26 +1217,6 @@ describe('WebDriver', function() {
1587
1217
  e.message.substring(0, 'Wait timed out after '.length));
1588
1218
  });
1589
1219
  });
1590
-
1591
- enablePromiseManager(() => {
1592
- it('waitTimesout_timeoutNotCaught', function() {
1593
- let executor = new FakeExecutor().
1594
- expect(CName.FIND_ELEMENTS,
1595
- {using: 'css selector', value: '*[id="foo"]'}).
1596
- andReturnSuccess([]).
1597
- anyTimes().
1598
- end();
1599
-
1600
- var driver = executor.createDriver();
1601
- driver.wait(function() {
1602
- return driver.findElements(By.id('foo')).then(els => els.length > 0);
1603
- }, 25);
1604
- return waitForAbort().then(function(e) {
1605
- assert.equal('Wait timed out after ',
1606
- e.message.substring(0, 'Wait timed out after '.length));
1607
- });
1608
- });
1609
- });
1610
1220
  });
1611
1221
 
1612
1222
  describe('supports condition objects', function() {
@@ -1694,30 +1304,6 @@ describe('WebDriver', function() {
1694
1304
  .then(assert.fail, v => assert.strictEqual(v, e));
1695
1305
  });
1696
1306
 
1697
- enablePromiseManager(() => {
1698
- it('alertsBelongToSameFlowAsParentDriver', function() {
1699
- let executor = new FakeExecutor()
1700
- .expect(CName.GET_ALERT_TEXT).andReturnSuccess('hello')
1701
- .end();
1702
-
1703
- var driver = executor.createDriver();
1704
- var otherFlow = new promise.ControlFlow();
1705
- otherFlow.execute(function() {
1706
- driver.switchTo().alert().then(function() {
1707
- assert.strictEqual(
1708
- driver.controlFlow(), promise.controlFlow(),
1709
- 'Alert should belong to the same flow as its parent driver');
1710
- });
1711
- });
1712
-
1713
- assert.notEqual(otherFlow, driver.controlFlow);
1714
- return Promise.all([
1715
- waitForIdle(otherFlow),
1716
- waitForIdle(driver.controlFlow())
1717
- ]);
1718
- });
1719
- });
1720
-
1721
1307
  it('commandsFailIfAlertNotPresent', function() {
1722
1308
  let e = new error.NoSuchAlertError;
1723
1309
  let executor = new FakeExecutor()
@@ -1741,30 +1327,6 @@ describe('WebDriver', function() {
1741
1327
  });
1742
1328
  });
1743
1329
 
1744
- enablePromiseManager(() => {
1745
- it('testWebElementsBelongToSameFlowAsParentDriver', function() {
1746
- let executor = new FakeExecutor()
1747
- .expect(CName.FIND_ELEMENT,
1748
- {using: 'css selector', value: '*[id="foo"]'})
1749
- .andReturnSuccess(WebElement.buildId('abc123'))
1750
- .end();
1751
-
1752
- var driver = executor.createDriver();
1753
- var otherFlow = new promise.ControlFlow();
1754
- otherFlow.execute(function() {
1755
- driver.findElement({id: 'foo'}).then(function() {
1756
- assert.equal(driver.controlFlow(), promise.controlFlow());
1757
- });
1758
- });
1759
-
1760
- assert.notEqual(otherFlow, driver.controlFlow);
1761
- return Promise.all([
1762
- waitForIdle(otherFlow),
1763
- waitForIdle(driver.controlFlow())
1764
- ]);
1765
- });
1766
- });
1767
-
1768
1330
  it('testFetchingLogs', function() {
1769
1331
  let executor = new FakeExecutor().
1770
1332
  expect(CName.GET_LOG, {'type': 'browser'}).
@@ -1796,10 +1358,7 @@ describe('WebDriver', function() {
1796
1358
  var driver = new FakeExecutor().createDriver(session);
1797
1359
  var navigateResult = driver.get('some-url').then(fail, assertIsStubError);
1798
1360
  var quitResult = driver.quit().then(fail, assertIsStubError);
1799
-
1800
- return waitForIdle().then(function() {
1801
- return promise.all(navigateResult, quitResult);
1802
- });
1361
+ return Promise.all([navigateResult, quitResult]);
1803
1362
  });
1804
1363
 
1805
1364
  it('testWebElementCommandsFailIfInitialDriverCreationFailed', function() {
@@ -1838,120 +1397,60 @@ describe('WebDriver', function() {
1838
1397
  });
1839
1398
 
1840
1399
  describe('actions()', function() {
1841
- it('failsIfInitialDriverCreationFailed', function() {
1842
- let session = Promise.reject(new StubError('no session for you'));
1843
- let driver = new FakeExecutor().createDriver(session);
1844
- driver.getSession().catch(function() {});
1845
- return driver.
1846
- actions().
1847
- mouseDown().
1848
- mouseUp().
1849
- perform().
1850
- catch(assertIsStubError);
1851
- });
1852
-
1853
- describe('mouseMove', function() {
1854
- it('noElement', function() {
1400
+ describe('move()', function() {
1401
+ it('no origin', function() {
1855
1402
  let executor = new FakeExecutor()
1856
- .expect(CName.MOVE_TO, {'xoffset': 0, 'yoffset': 125})
1403
+ .expect(CName.ACTIONS, {
1404
+ actions: [{
1405
+ type: 'pointer',
1406
+ id: 'default mouse',
1407
+ parameters: {
1408
+ pointerType: 'mouse'
1409
+ },
1410
+ actions: [{
1411
+ duration: 100,
1412
+ origin: 'viewport',
1413
+ type: 'pointerMove',
1414
+ x: 0,
1415
+ y: 125
1416
+ }]
1417
+ }]
1418
+ })
1857
1419
  .andReturnSuccess()
1858
1420
  .end();
1859
1421
 
1860
- return executor.createDriver().
1861
- actions().
1862
- mouseMove({x: 0, y: 125}).
1863
- perform();
1422
+ let driver = executor.createDriver();
1423
+ return driver.actions().move({x: 0, y: 125}).perform();
1864
1424
  });
1865
1425
 
1866
- it('element', function() {
1426
+ it('origin = element', function() {
1867
1427
  let executor = new FakeExecutor()
1868
1428
  .expect(CName.FIND_ELEMENT,
1869
1429
  {using: 'css selector', value: '*[id="foo"]'})
1870
1430
  .andReturnSuccess(WebElement.buildId('abc123'))
1871
- .expect(CName.MOVE_TO,
1872
- {'element': 'abc123', 'xoffset': 0, 'yoffset': 125})
1873
- .andReturnSuccess()
1431
+ .expect(CName.ACTIONS, {
1432
+ actions: [{
1433
+ type: 'pointer',
1434
+ id: 'default mouse',
1435
+ parameters: {
1436
+ pointerType: 'mouse'
1437
+ },
1438
+ actions: [{
1439
+ duration: 100,
1440
+ origin: WebElement.buildId('abc123'),
1441
+ type: 'pointerMove',
1442
+ x: 0,
1443
+ y: 125
1444
+ }]
1445
+ }]
1446
+ })
1874
1447
  .end();
1875
1448
 
1876
- var driver = executor.createDriver();
1877
- var element = driver.findElement(By.id('foo'));
1878
- return driver.actions()
1879
- .mouseMove(element, {x: 0, y: 125})
1880
- .perform();
1449
+ let driver = executor.createDriver();
1450
+ let element = driver.findElement(By.id('foo'));
1451
+ return driver.actions().move({x: 0, y: 125, origin: element}).perform();
1881
1452
  });
1882
1453
  });
1883
-
1884
- it('supportsMouseDown', function() {
1885
- let executor = new FakeExecutor()
1886
- .expect(CName.MOUSE_DOWN, {'button': Button.LEFT})
1887
- .andReturnSuccess()
1888
- .end();
1889
-
1890
- return executor.createDriver().
1891
- actions().
1892
- mouseDown().
1893
- perform();
1894
- });
1895
-
1896
- it('testActionSequence', function() {
1897
- let executor = new FakeExecutor()
1898
- .expect(CName.FIND_ELEMENT,
1899
- {using: 'css selector', value: '*[id="a"]'})
1900
- .andReturnSuccess(WebElement.buildId('id1'))
1901
- .expect(CName.FIND_ELEMENT,
1902
- {using: 'css selector', value: '*[id="b"]'})
1903
- .andReturnSuccess(WebElement.buildId('id2'))
1904
- .expect(CName.SEND_KEYS_TO_ACTIVE_ELEMENT,
1905
- {'value': [Key.SHIFT]})
1906
- .andReturnSuccess()
1907
- .expect(CName.MOVE_TO, {'element': 'id1'})
1908
- .andReturnSuccess()
1909
- .expect(CName.CLICK, {'button': Button.LEFT})
1910
- .andReturnSuccess()
1911
- .expect(CName.MOVE_TO, {'element': 'id2'})
1912
- .andReturnSuccess()
1913
- .expect(CName.CLICK, {'button': Button.LEFT})
1914
- .andReturnSuccess()
1915
- .end();
1916
-
1917
- var driver = executor.createDriver();
1918
- var element1 = driver.findElement(By.id('a'));
1919
- var element2 = driver.findElement(By.id('b'));
1920
-
1921
- return driver.actions()
1922
- .keyDown(Key.SHIFT)
1923
- .click(element1)
1924
- .click(element2)
1925
- .perform();
1926
- });
1927
- });
1928
-
1929
- describe('touchActions()', function() {
1930
- it('failsIfInitialDriverCreationFailed', function() {
1931
- let session = Promise.reject(new StubError);
1932
- let driver = new FakeExecutor().createDriver(session);
1933
- driver.getSession().catch(function() {});
1934
- return driver.
1935
- touchActions().
1936
- scroll({x: 3, y: 4}).
1937
- perform().
1938
- catch(assertIsStubError);
1939
- });
1940
-
1941
- it('testTouchActionSequence', function() {
1942
- let executor = new FakeExecutor()
1943
- .expect(CName.TOUCH_DOWN, {x: 1, y: 2}).andReturnSuccess()
1944
- .expect(CName.TOUCH_MOVE, {x: 3, y: 4}).andReturnSuccess()
1945
- .expect(CName.TOUCH_UP, {x: 5, y: 6}).andReturnSuccess()
1946
- .end();
1947
-
1948
- var driver = executor.createDriver();
1949
- return driver.touchActions()
1950
- .tapAndHold({x: 1, y: 2})
1951
- .move({x: 3, y: 4})
1952
- .release({x: 5, y: 6})
1953
- .perform();
1954
- });
1955
1454
  });
1956
1455
 
1957
1456
  describe('manage()', function() {
@@ -2024,101 +1523,7 @@ describe('WebDriver', function() {
2024
1523
  let driver = executor.createDriver();
2025
1524
  return driver.manage().setTimeouts({implicit: 3});
2026
1525
  });
2027
-
2028
- describe('deprecated API calls setTimeouts()', function() {
2029
- it('implicitlyWait()', function() {
2030
- let executor = new FakeExecutor()
2031
- .expect(CName.SET_TIMEOUT, {implicit: 3})
2032
- .andReturnSuccess()
2033
- .end();
2034
- let driver = executor.createDriver();
2035
- return driver.manage().timeouts().implicitlyWait(3);
2036
- });
2037
-
2038
- it('setScriptTimeout()', function() {
2039
- let executor = new FakeExecutor()
2040
- .expect(CName.SET_TIMEOUT, {script: 3})
2041
- .andReturnSuccess()
2042
- .end();
2043
- let driver = executor.createDriver();
2044
- return driver.manage().timeouts().setScriptTimeout(3);
2045
- });
2046
-
2047
- it('pageLoadTimeout()', function() {
2048
- let executor = new FakeExecutor()
2049
- .expect(CName.SET_TIMEOUT, {pageLoad: 3})
2050
- .andReturnSuccess()
2051
- .end();
2052
- let driver = executor.createDriver();
2053
- return driver.manage().timeouts().pageLoadTimeout(3);
2054
- });
2055
- });
2056
- });
2057
- });
2058
-
2059
- describe('generator support', function() {
2060
- var driver;
2061
-
2062
- beforeEach(function() {
2063
- driver = new WebDriver(
2064
- new Session('test-session', {}),
2065
- new ExplodingExecutor());
2066
- });
2067
-
2068
- it('canUseGeneratorsWithWebDriverCall', function() {
2069
- return driver.call(function* () {
2070
- var x = yield Promise.resolve(1);
2071
- var y = yield Promise.resolve(2);
2072
- return x + y;
2073
- }).then(function(value) {
2074
- assert.deepEqual(3, value);
2075
- });
2076
1526
  });
2077
-
2078
- it('canDefineScopeOnGeneratorCall', function() {
2079
- return driver.call(function* () {
2080
- var x = yield Promise.resolve(1);
2081
- return this.name + x;
2082
- }, {name: 'Bob'}).then(function(value) {
2083
- assert.deepEqual('Bob1', value);
2084
- });
2085
- });
2086
-
2087
- it('canSpecifyArgsOnGeneratorCall', function() {
2088
- return driver.call(function* (a, b) {
2089
- var x = yield Promise.resolve(1);
2090
- var y = yield Promise.resolve(2);
2091
- return [x + y, a, b];
2092
- }, null, 'abc', 123).then(function(value) {
2093
- assert.deepEqual([3, 'abc', 123], value);
2094
- });
2095
- });
2096
-
2097
- it('canUseGeneratorWithWebDriverWait', function() {
2098
- var values = [];
2099
- return driver.wait(function* () {
2100
- yield values.push(1);
2101
- values.push(yield promise.delayed(10).then(function() {
2102
- return 2;
2103
- }));
2104
- yield values.push(3);
2105
- return values.length === 6;
2106
- }, 250).then(function() {
2107
- assert.deepEqual([1, 2, 3, 1, 2, 3], values);
2108
- });
2109
- });
2110
-
2111
- /**
2112
- * @constructor
2113
- * @implements {CommandExecutor}
2114
- */
2115
- function ExplodingExecutor() {}
2116
-
2117
-
2118
- /** @override */
2119
- ExplodingExecutor.prototype.execute = function(command, cb) {
2120
- cb(Error('Unsupported operation'));
2121
- };
2122
1527
  });
2123
1528
 
2124
1529
  describe('wire format', function() {
@@ -2128,10 +1533,16 @@ describe('WebDriver', function() {
2128
1533
  function runSerializeTest(input, want) {
2129
1534
  let executor = new FakeExecutor().
2130
1535
  expect(CName.NEW_SESSION).
2131
- withParameters({'desiredCapabilities': want}).
1536
+ withParameters({
1537
+ 'desiredCapabilities': {'serialize-test': want},
1538
+ 'capabilities': {'alwaysMatch': {}},
1539
+ }).
2132
1540
  andReturnSuccess({'browserName': 'firefox'}).
2133
1541
  end();
2134
- return WebDriver.createSession(executor, input)
1542
+ // We stuff the value to be serialized inside of a capabilities object,
1543
+ // using a non-W3C key so that the value gets dropped from the W3C
1544
+ // capabilities object.
1545
+ return WebDriver.createSession(executor, {'serialize-test': input})
2135
1546
  .getSession();
2136
1547
  }
2137
1548
 
@@ -2224,8 +1635,7 @@ describe('WebDriver', function() {
2224
1635
 
2225
1636
  it('with sub-objects', function() {
2226
1637
  var expected = {sessionId: {value: 'foo'}};
2227
- return runSerializeTest(
2228
- {sessionId: {value: 'foo'}}, expected);
1638
+ return runSerializeTest({sessionId: {value: 'foo'}}, expected);
2229
1639
  });
2230
1640
 
2231
1641
  it('with values that have toJSON', function() {
@@ -2257,6 +1667,24 @@ describe('WebDriver', function() {
2257
1667
 
2258
1668
  return runSerializeTest(parameters, expected);
2259
1669
  });
1670
+
1671
+ it('nested promises', function() {
1672
+ const input = {
1673
+ 'struct': Promise.resolve({
1674
+ 'element': new WebElementPromise(
1675
+ FAKE_DRIVER,
1676
+ Promise.resolve(new WebElement(FAKE_DRIVER, 'fefifofum')))
1677
+ })
1678
+ };
1679
+
1680
+ const want = {
1681
+ 'struct': {
1682
+ 'element': WebElement.buildId('fefifofum')
1683
+ }
1684
+ };
1685
+
1686
+ return runSerializeTest(input, want);
1687
+ });
2260
1688
  });
2261
1689
  });
2262
1690