selenium-webdriver 3.3.0 → 4.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/CHANGES.md +273 -0
  2. package/NOTICE +1 -1
  3. package/README.md +28 -36
  4. package/chrome.js +221 -146
  5. package/edge.js +43 -118
  6. package/example/chrome_android.js +8 -9
  7. package/example/chrome_mobile_emulation.js +9 -10
  8. package/example/firefox_channels.js +23 -19
  9. package/example/google_search.js +3 -3
  10. package/example/google_search_test.js +39 -27
  11. package/example/headless.js +55 -0
  12. package/example/logging.js +40 -7
  13. package/firefox.js +769 -0
  14. package/http/index.js +41 -4
  15. package/http/util.js +11 -6
  16. package/ie.js +57 -98
  17. package/index.js +182 -115
  18. package/io/index.js +59 -0
  19. package/io/zip.js +214 -0
  20. package/jasmine.json +11 -0
  21. package/lib/actions.js +68 -63
  22. package/lib/atoms/get-attribute.js +9 -0
  23. package/lib/atoms/is-displayed.js +73 -78
  24. package/lib/by.js +9 -1
  25. package/lib/capabilities.js +303 -201
  26. package/lib/command.js +28 -50
  27. package/lib/error.js +113 -42
  28. package/lib/http.js +167 -135
  29. package/lib/input.js +1044 -8
  30. package/lib/promise.js +222 -3331
  31. package/lib/proxy.js +134 -39
  32. package/lib/test/bootstrap_jasmine.js +28 -0
  33. package/lib/test/data/actions/click.html +24 -0
  34. package/lib/test/data/actions/drag.html +77 -0
  35. package/lib/test/data/actions/record_click.html +21 -0
  36. package/lib/test/data/chrome/download.html +2 -0
  37. package/lib/test/data/click_tests/disabled_element.html +12 -0
  38. package/lib/test/data/content-editable.html +10 -0
  39. package/lib/test/data/firefox/webextension.xpi +0 -0
  40. package/lib/test/data/inputs.html +42 -0
  41. package/lib/test/data/key_logger.html +34 -0
  42. package/lib/test/data/nestedElements.html +10 -1
  43. package/lib/test/data/scrolling_tests/page_with_partially_hidden_element.html +14 -0
  44. package/lib/test/data/selectPage.html +12 -0
  45. package/lib/test/data/simpleTest.html +5 -0
  46. package/lib/test/data/single_text_input.html +12 -0
  47. package/lib/test/data/upload_invisible.html +45 -0
  48. package/lib/test/fileserver.js +23 -19
  49. package/lib/test/index.js +30 -244
  50. package/lib/test/resources.js +0 -1
  51. package/lib/webdriver.js +770 -939
  52. package/net/index.js +21 -25
  53. package/net/portprober.js +51 -68
  54. package/package.json +6 -4
  55. package/remote/index.js +18 -30
  56. package/safari.js +42 -129
  57. package/test/actions_test.js +173 -18
  58. package/test/builder_test.js +106 -0
  59. package/test/chrome/devtools_test.js +93 -0
  60. package/test/chrome/options_test.js +48 -154
  61. package/test/chrome/service_test.js +7 -7
  62. package/test/cookie_test.js +77 -63
  63. package/test/element_finding_test.js +206 -201
  64. package/test/execute_script_test.js +115 -114
  65. package/test/fingerprint_test.js +16 -15
  66. package/test/firefox_test.js +251 -0
  67. package/test/http/http_test.js +18 -1
  68. package/test/http/util_test.js +2 -2
  69. package/test/{io_test.js → io/io_test.js} +40 -1
  70. package/test/io/zip_test.js +127 -0
  71. package/test/lib/by_test.js +21 -0
  72. package/test/lib/error_test.js +55 -8
  73. package/test/lib/http_test.js +18 -130
  74. package/test/lib/input_test.js +1379 -0
  75. package/test/lib/promise_test.js +473 -908
  76. package/test/lib/webdriver_test.js +357 -825
  77. package/test/logging_test.js +37 -43
  78. package/test/page_loading_test.js +70 -86
  79. package/test/proxy_test.js +64 -72
  80. package/test/rect_test.js +14 -25
  81. package/test/remote_test.js +13 -32
  82. package/test/safari_test.js +7 -71
  83. package/test/stale_element_test.js +20 -23
  84. package/test/tag_name_test.js +10 -9
  85. package/test/upload_test.js +27 -35
  86. package/test/window_test.js +72 -85
  87. package/testing/index.js +386 -315
  88. package/.npmignore +0 -2
  89. package/example/async_await_test.js +0 -68
  90. package/example/google_search_generator.js +0 -50
  91. package/example/parallel_flows.js +0 -54
  92. package/firefox/binary.js +0 -344
  93. package/firefox/extension.js +0 -187
  94. package/firefox/index.js +0 -722
  95. package/firefox/profile.js +0 -430
  96. package/lib/atoms/getAttribute.js +0 -12
  97. package/lib/events.js +0 -210
  98. package/lib/firefox/webdriver.json +0 -70
  99. package/lib/firefox/webdriver.xpi +0 -0
  100. package/lib/test/data/firefox/jetpack-sample.xpi +0 -0
  101. package/lib/test/data/firefox/sample.xpi +0 -0
  102. package/lib/test/promise.js +0 -79
  103. package/opera.js +0 -405
  104. package/phantomjs.js +0 -282
  105. package/test/firefox/extension_test.js +0 -96
  106. package/test/firefox/firefox_test.js +0 -226
  107. package/test/firefox/profile_test.js +0 -185
  108. package/test/lib/events_test.js +0 -177
  109. package/test/lib/promise_aplus_test.js +0 -78
  110. package/test/lib/promise_error_test.js +0 -884
  111. package/test/lib/promise_flow_test.js +0 -2288
  112. package/test/lib/promise_generator_test.js +0 -310
  113. package/test/phantomjs/execute_phantomjs_test.js +0 -59
  114. package/test/session_test.js +0 -54
  115. package/test/testing/assert_test.js +0 -373
  116. package/test/testing/index_test.js +0 -224
  117. package/testing/assert.js +0 -378
@@ -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,79 +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, 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, null,
468
- () => {throw e});
469
- return waitForAbort().then(err => assert.strictEqual(err, e));
470
- });
471
- });
472
- });
473
279
  });
474
280
 
475
281
  it('testDoesNotExecuteCommandIfSessionDoesNotResolve', function() {
@@ -507,26 +313,6 @@ describe('WebDriver', function() {
507
313
  v => assert.strictEqual(v, e));
508
314
  });
509
315
 
510
- it('testCanSuppressCommandFailures', function() {
511
- let e = new error.NoSuchWindowError('window not found');
512
- let executor = new FakeExecutor().
513
- expect(CName.SWITCH_TO_WINDOW).
514
- withParameters({
515
- 'name': 'foo',
516
- 'handle': 'foo'
517
- }).
518
- andReturnError(e).
519
- expect(CName.GET_TITLE).
520
- andReturnSuccess('Google Search').
521
- end();
522
-
523
- var driver = executor.createDriver();
524
- driver.switchTo().window('foo')
525
- .catch(v => assert.strictEqual(v, e));
526
- driver.getTitle();
527
- return waitForIdle();
528
- });
529
-
530
316
  it('testErrorsPropagateUpToTheRunningApplication', function() {
531
317
  let e = new error.NoSuchWindowError('window not found');
532
318
  let executor = new FakeExecutor().
@@ -590,53 +376,6 @@ describe('WebDriver', function() {
590
376
  .then(assert.fail, verifyError);
591
377
  });
592
378
 
593
- it('testCallbackCommandsExecuteBeforeNextCommand', function() {
594
- let executor = new FakeExecutor().
595
- expect(CName.GET_CURRENT_URL).
596
- expect(CName.GET, {'url': 'http://www.google.com'}).
597
- expect(CName.CLOSE).
598
- expect(CName.GET_TITLE).
599
- end();
600
-
601
- var driver = executor.createDriver();
602
- driver.getCurrentUrl().then(function() {
603
- driver.get('http://www.google.com').then(function() {
604
- driver.close();
605
- });
606
- });
607
- driver.getTitle();
608
-
609
- return waitForIdle();
610
- });
611
-
612
- enablePromiseManager(() => {
613
- it('testEachCallbackFrameRunsToCompletionBeforeTheNext', function() {
614
- let executor = new FakeExecutor().
615
- expect(CName.GET_TITLE).
616
- expect(CName.GET_CURRENT_URL).
617
- expect(CName.GET_CURRENT_WINDOW_HANDLE).
618
- expect(CName.CLOSE).
619
- expect(CName.QUIT).
620
- end();
621
-
622
- var driver = executor.createDriver();
623
- driver.getTitle().
624
- // Everything in this callback...
625
- then(function() {
626
- driver.getCurrentUrl();
627
- driver.getWindowHandle();
628
- }).
629
- // ...should execute before everything in this callback.
630
- then(function() {
631
- driver.close();
632
- });
633
- // This should execute after everything above
634
- driver.quit();
635
-
636
- return waitForIdle();
637
- });
638
- });
639
-
640
379
  describe('returningAPromise', function() {
641
380
  it('fromACallback', function() {
642
381
  let executor = new FakeExecutor().
@@ -676,274 +415,6 @@ describe('WebDriver', function() {
676
415
  });
677
416
  });
678
417
 
679
- describe('customFunctions', function() {
680
- it('returnsANonPromiseValue', function() {
681
- var driver = new FakeExecutor().createDriver();
682
- return driver.call(() => 'abc123').then(function(value) {
683
- assert.equal('abc123', value);
684
- });
685
- });
686
-
687
- enablePromiseManager(() => {
688
- it('executionOrderWithCustomFunctions', function() {
689
- var msg = [];
690
- let executor = new FakeExecutor().
691
- expect(CName.GET_TITLE).andReturnSuccess('cheese ').
692
- expect(CName.GET_CURRENT_URL).andReturnSuccess('tasty').
693
- end();
694
-
695
- var driver = executor.createDriver();
696
-
697
- var pushMsg = msg.push.bind(msg);
698
- driver.getTitle().then(pushMsg);
699
- driver.call(() => 'is ').then(pushMsg);
700
- driver.getCurrentUrl().then(pushMsg);
701
- driver.call(() => '!').then(pushMsg);
702
-
703
- return waitForIdle().then(function() {
704
- assert.equal('cheese is tasty!', msg.join(''));
705
- });
706
- });
707
- });
708
-
709
- it('passingArgumentsToACustomFunction', function() {
710
- var add = function(a, b) {
711
- return a + b;
712
- };
713
- var driver = new FakeExecutor().createDriver();
714
- return driver.call(add, null, 1, 2).then(function(value) {
715
- assert.equal(3, value);
716
- });
717
- });
718
-
719
- it('passingPromisedArgumentsToACustomFunction', function() {
720
- var promisedArg = Promise.resolve(2);
721
- var add = function(a, b) {
722
- return a + b;
723
- };
724
- var driver = new FakeExecutor().createDriver();
725
- return driver.call(add, null, 1, promisedArg).then(function(value) {
726
- assert.equal(3, value);
727
- });
728
- });
729
-
730
- it('passingArgumentsAndScopeToACustomFunction', function() {
731
- function Foo(name) {
732
- this.name = name;
733
- }
734
- Foo.prototype.getName = function() {
735
- return this.name;
736
- };
737
- var foo = new Foo('foo');
738
-
739
- var driver = new FakeExecutor().createDriver();
740
- return driver.call(foo.getName, foo).then(function(value) {
741
- assert.equal('foo', value);
742
- });
743
- });
744
-
745
- it('customFunctionThrowsAnError', function() {
746
- var driver = new FakeExecutor().createDriver();
747
- return driver.call(throwStubError).then(fail, assertIsStubError);
748
- });
749
-
750
- it('customFunctionSchedulesCommands', function() {
751
- let executor = new FakeExecutor().
752
- expect(CName.GET_TITLE).
753
- expect(CName.CLOSE).
754
- expect(CName.QUIT).
755
- end();
756
-
757
- var driver = executor.createDriver();
758
- driver.call(function() {
759
- driver.getTitle();
760
- driver.close();
761
- });
762
- driver.quit();
763
- return waitForIdle();
764
- });
765
-
766
- it('returnsATaskResultAfterSchedulingAnother', function() {
767
- let executor = new FakeExecutor().
768
- expect(CName.GET_TITLE).
769
- andReturnSuccess('Google Search').
770
- expect(CName.CLOSE).
771
- end();
772
-
773
- var driver = executor.createDriver();
774
- return driver.call(function() {
775
- var title = driver.getTitle();
776
- driver.close();
777
- return title;
778
- }).then(function(title) {
779
- assert.equal('Google Search', title);
780
- });
781
- });
782
-
783
- it('hasANestedCommandThatFails', function() {
784
- let executor = new FakeExecutor().
785
- expect(CName.SWITCH_TO_WINDOW, {
786
- 'name': 'foo',
787
- 'handle': 'foo'
788
- }).
789
- andReturnError(new StubError()).
790
- end();
791
-
792
- var driver = executor.createDriver();
793
- return driver.call(function() {
794
- return driver.switchTo().window('foo');
795
- }).then(fail, assertIsStubError);
796
- });
797
-
798
- enablePromiseManager(() => {
799
- it('doesNotCompleteUntilReturnedPromiseIsResolved', function() {
800
- var order = [];
801
- var driver = new FakeExecutor().createDriver();
802
-
803
- var d = promise.defer();
804
- d.promise.then(function() {
805
- order.push('b');
806
- });
807
-
808
- driver.call(function() {
809
- order.push('a');
810
- return d.promise;
811
- });
812
- driver.call(function() {
813
- order.push('c');
814
- });
815
-
816
- // timeout to ensure the first function starts its execution before we
817
- // trigger d's callbacks.
818
- return new Promise(f => setTimeout(f, 0)).then(function() {
819
- assert.deepEqual(['a'], order);
820
- d.fulfill();
821
- return waitForIdle().then(function() {
822
- assert.deepEqual(['a', 'b', 'c'], order);
823
- });
824
- });
825
- });
826
- });
827
-
828
- it('returnsADeferredAction', function() {
829
- let executor = new FakeExecutor().
830
- expect(CName.GET_TITLE).andReturnSuccess('Google').
831
- end();
832
-
833
- var driver = executor.createDriver();
834
- driver.call(function() {
835
- return driver.getTitle();
836
- }).then(function(title) {
837
- assert.equal('Google', title);
838
- });
839
- return waitForIdle();
840
- });
841
- });
842
-
843
- describe('nestedCommands', function() {
844
- enablePromiseManager(() => {
845
- it('commandExecutionOrder', function() {
846
- var msg = [];
847
- var driver = new FakeExecutor().createDriver();
848
- driver.call(msg.push, msg, 'a');
849
- driver.call(function() {
850
- driver.call(msg.push, msg, 'c');
851
- driver.call(function() {
852
- driver.call(msg.push, msg, 'e');
853
- driver.call(msg.push, msg, 'f');
854
- });
855
- driver.call(msg.push, msg, 'd');
856
- });
857
- driver.call(msg.push, msg, 'b');
858
- return waitForIdle().then(function() {
859
- assert.equal('acefdb', msg.join(''));
860
- });
861
- });
862
-
863
- it('basicUsage', function() {
864
- var msg = [];
865
- var driver = new FakeExecutor().createDriver();
866
- var pushMsg = msg.push.bind(msg);
867
- driver.call(() => 'cheese ').then(pushMsg);
868
- driver.call(function() {
869
- driver.call(() => 'is ').then(pushMsg);
870
- driver.call(() => 'tasty').then(pushMsg);
871
- });
872
- driver.call(() => '!').then(pushMsg);
873
- return waitForIdle().then(function() {
874
- assert.equal('cheese is tasty!', msg.join(''));
875
- });
876
- });
877
-
878
- it('normalCommandAfterNestedCommandThatReturnsAnAction', function() {
879
- var msg = [];
880
- let executor = new FakeExecutor().
881
- expect(CName.CLOSE).
882
- end();
883
- var driver = executor.createDriver();
884
- driver.call(function() {
885
- return driver.call(function() {
886
- msg.push('a');
887
- return driver.call(() => 'foobar');
888
- });
889
- });
890
- driver.close().then(function() {
891
- msg.push('b');
892
- });
893
- return waitForIdle().then(function() {
894
- assert.equal('ab', msg.join(''));
895
- });
896
- });
897
- });
898
-
899
- it('canReturnValueFromNestedFunction', function() {
900
- var driver = new FakeExecutor().createDriver();
901
- return driver.call(function() {
902
- return driver.call(function() {
903
- return driver.call(() => 'foobar');
904
- });
905
- }).then(function(value) {
906
- assert.equal('foobar', value);
907
- });
908
- });
909
-
910
- it('errorsBubbleUp_caught', function() {
911
- var driver = new FakeExecutor().createDriver();
912
- var result = driver.call(function() {
913
- return driver.call(function() {
914
- return driver.call(throwStubError);
915
- });
916
- }).then(fail, assertIsStubError);
917
- return Promise.all([waitForIdle(), result]);
918
- });
919
-
920
- it('errorsBubbleUp_uncaught', function() {
921
- var driver = new FakeExecutor().createDriver();
922
- return driver.call(function() {
923
- return driver.call(function() {
924
- return driver.call(throwStubError);
925
- });
926
- })
927
- .then(_ => assert.fail('should have failed'), assertIsStubError);
928
- });
929
-
930
- it('canScheduleCommands', function() {
931
- let executor = new FakeExecutor().
932
- expect(CName.GET_TITLE).
933
- expect(CName.CLOSE).
934
- end();
935
-
936
- var driver = executor.createDriver();
937
- driver.call(function() {
938
- driver.call(function() {
939
- driver.getTitle();
940
- });
941
- driver.close();
942
- });
943
- return waitForIdle();
944
- });
945
- });
946
-
947
418
  describe('WebElementPromise', function() {
948
419
  let driver = new FakeExecutor().createDriver();
949
420
 
@@ -1228,8 +699,7 @@ describe('WebDriver', function() {
1228
699
 
1229
700
  var driver = executor.createDriver();
1230
701
  var element = driver.findElement(By.id('foo'));
1231
- element.click();
1232
- return waitForIdle();
702
+ return element.click();
1233
703
  });
1234
704
 
1235
705
  it('canUseElementInCallback', function() {
@@ -1242,10 +712,7 @@ describe('WebDriver', function() {
1242
712
  end();
1243
713
 
1244
714
  var driver = executor.createDriver();
1245
- driver.findElement(By.id('foo')).then(function(element) {
1246
- element.click();
1247
- });
1248
- return waitForIdle();
715
+ return driver.findElement(By.id('foo')).then(e => e.click());
1249
716
  });
1250
717
 
1251
718
  it('byJs', function() {
@@ -1259,9 +726,8 @@ describe('WebDriver', function() {
1259
726
  end();
1260
727
 
1261
728
  var driver = executor.createDriver();
1262
- var element = driver.findElement(By.js('return document.body'));
1263
- element.click(); // just to make sure
1264
- return waitForIdle();
729
+ return driver.findElement(By.js('return document.body'))
730
+ .then(e => e.click());
1265
731
  });
1266
732
 
1267
733
  it('byJs_returnsNonWebElementValue', function() {
@@ -1289,8 +755,7 @@ describe('WebDriver', function() {
1289
755
  andReturnSuccess(WebElement.buildId('one')).
1290
756
  end();
1291
757
  var driver = executor.createDriver();
1292
- driver.findElement(By.js(script, 'div'));
1293
- return waitForIdle();
758
+ return driver.findElement(By.js(script, 'div'));
1294
759
  });
1295
760
 
1296
761
  it('customLocator', function() {
@@ -1333,7 +798,7 @@ describe('WebDriver', function() {
1333
798
  var driver = executor.createDriver();
1334
799
  return driver.findElements(By.tagName('a'))
1335
800
  .then(function(elements) {
1336
- return promise.all(elements.map(function(e) {
801
+ return Promise.all(elements.map(function(e) {
1337
802
  assert.ok(e instanceof WebElement);
1338
803
  return e.getId();
1339
804
  }));
@@ -1356,7 +821,7 @@ describe('WebDriver', function() {
1356
821
  return driver.
1357
822
  findElements(By.js('return document.getElementsByTagName("div");')).
1358
823
  then(function(elements) {
1359
- return promise.all(elements.map(function(e) {
824
+ return Promise.all(elements.map(function(e) {
1360
825
  assert.ok(e instanceof WebElement);
1361
826
  return e.getId();
1362
827
  }));
@@ -1384,15 +849,14 @@ describe('WebDriver', function() {
1384
849
  end();
1385
850
 
1386
851
  var driver = executor.createDriver();
1387
- driver.findElements(By.js('return document.getElementsByTagName("div");')).
852
+ return driver.findElements(By.js('return document.getElementsByTagName("div");')).
1388
853
  then(function(elements) {
1389
- return promise.all(elements.map(function(e) {
854
+ return Promise.all(elements.map(function(e) {
1390
855
  assert.ok(e instanceof WebElement);
1391
856
  return e.getId();
1392
857
  }));
1393
858
  }).
1394
859
  then((actual) => assert.deepEqual(ids, actual));
1395
- return waitForIdle();
1396
860
  });
1397
861
 
1398
862
  it('byJs_convertsSingleWebElementResponseToArray', function() {
@@ -1408,7 +872,7 @@ describe('WebDriver', function() {
1408
872
  return driver.
1409
873
  findElements(By.js('return document.getElementsByTagName("div");')).
1410
874
  then(function(elements) {
1411
- return promise.all(elements.map(function(e) {
875
+ return Promise.all(elements.map(function(e) {
1412
876
  assert.ok(e instanceof WebElement);
1413
877
  return e.getId();
1414
878
  }));
@@ -1432,7 +896,7 @@ describe('WebDriver', function() {
1432
896
  var driver = executor.createDriver();
1433
897
  return driver.findElements(By.js(script, 'div'))
1434
898
  then(function(elements) {
1435
- return promise.all(elements.map(function(e) {
899
+ return Promise.all(elements.map(function(e) {
1436
900
  assert.ok(e instanceof WebElement);
1437
901
  return e.getId();
1438
902
  }));
@@ -1446,14 +910,14 @@ describe('WebDriver', function() {
1446
910
  let executor = new FakeExecutor().
1447
911
  expect(CName.SEND_KEYS_TO_ELEMENT,
1448
912
  {'id': WebElement.buildId('one'),
913
+ 'text': '12abc3',
1449
914
  'value':'12abc3'.split('')}).
1450
915
  andReturnSuccess().
1451
916
  end();
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() {
@@ -1463,6 +927,7 @@ describe('WebDriver', function() {
1463
927
  andReturnSuccess(WebElement.buildId('one')).
1464
928
  expect(CName.SEND_KEYS_TO_ELEMENT,
1465
929
  {'id':WebElement.buildId('one'),
930
+ 'text': 'abc123def',
1466
931
  'value':'abc123def'.split('')}).
1467
932
  andReturnSuccess().
1468
933
  end();
@@ -1482,6 +947,7 @@ describe('WebDriver', function() {
1482
947
  andReturnSuccess(WebElement.buildId('one')).
1483
948
  expect(CName.SEND_KEYS_TO_ELEMENT,
1484
949
  {'id': WebElement.buildId('one'),
950
+ 'text': 'modified/path',
1485
951
  'value':'modified/path'.split('')}).
1486
952
  andReturnSuccess().
1487
953
  end();
@@ -1510,8 +976,7 @@ describe('WebDriver', function() {
1510
976
  andReturnSuccess().
1511
977
  end();
1512
978
 
1513
- executor.createDriver().switchTo().window('foo');
1514
- return waitForIdle();
979
+ return executor.createDriver().switchTo().window('foo');
1515
980
  });
1516
981
 
1517
982
  it('should propagate exceptions', function() {
@@ -1550,6 +1015,174 @@ describe('WebDriver', function() {
1550
1015
  });
1551
1016
 
1552
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
+
1553
1186
  describe('supports custom wait functions', function() {
1554
1187
  it('waitSucceeds', function() {
1555
1188
  let executor = new FakeExecutor().
@@ -1563,10 +1196,9 @@ describe('WebDriver', function() {
1563
1196
  end();
1564
1197
 
1565
1198
  var driver = executor.createDriver();
1566
- driver.wait(function() {
1199
+ return driver.wait(function() {
1567
1200
  return driver.findElements(By.id('foo')).then(els => els.length > 0);
1568
1201
  }, 200);
1569
- return waitForIdle();
1570
1202
  });
1571
1203
 
1572
1204
  it('waitTimesout_timeoutCaught', function() {
@@ -1585,26 +1217,6 @@ describe('WebDriver', function() {
1585
1217
  e.message.substring(0, 'Wait timed out after '.length));
1586
1218
  });
1587
1219
  });
1588
-
1589
- enablePromiseManager(() => {
1590
- it('waitTimesout_timeoutNotCaught', function() {
1591
- let executor = new FakeExecutor().
1592
- expect(CName.FIND_ELEMENTS,
1593
- {using: 'css selector', value: '*[id="foo"]'}).
1594
- andReturnSuccess([]).
1595
- anyTimes().
1596
- end();
1597
-
1598
- var driver = executor.createDriver();
1599
- driver.wait(function() {
1600
- return driver.findElements(By.id('foo')).then(els => els.length > 0);
1601
- }, 25);
1602
- return waitForAbort().then(function(e) {
1603
- assert.equal('Wait timed out after ',
1604
- e.message.substring(0, 'Wait timed out after '.length));
1605
- });
1606
- });
1607
- });
1608
1220
  });
1609
1221
 
1610
1222
  describe('supports condition objects', function() {
@@ -1692,30 +1304,6 @@ describe('WebDriver', function() {
1692
1304
  .then(assert.fail, v => assert.strictEqual(v, e));
1693
1305
  });
1694
1306
 
1695
- enablePromiseManager(() => {
1696
- it('alertsBelongToSameFlowAsParentDriver', function() {
1697
- let executor = new FakeExecutor()
1698
- .expect(CName.GET_ALERT_TEXT).andReturnSuccess('hello')
1699
- .end();
1700
-
1701
- var driver = executor.createDriver();
1702
- var otherFlow = new promise.ControlFlow();
1703
- otherFlow.execute(function() {
1704
- driver.switchTo().alert().then(function() {
1705
- assert.strictEqual(
1706
- driver.controlFlow(), promise.controlFlow(),
1707
- 'Alert should belong to the same flow as its parent driver');
1708
- });
1709
- });
1710
-
1711
- assert.notEqual(otherFlow, driver.controlFlow);
1712
- return Promise.all([
1713
- waitForIdle(otherFlow),
1714
- waitForIdle(driver.controlFlow())
1715
- ]);
1716
- });
1717
- });
1718
-
1719
1307
  it('commandsFailIfAlertNotPresent', function() {
1720
1308
  let e = new error.NoSuchAlertError;
1721
1309
  let executor = new FakeExecutor()
@@ -1739,30 +1327,6 @@ describe('WebDriver', function() {
1739
1327
  });
1740
1328
  });
1741
1329
 
1742
- enablePromiseManager(() => {
1743
- it('testWebElementsBelongToSameFlowAsParentDriver', function() {
1744
- let executor = new FakeExecutor()
1745
- .expect(CName.FIND_ELEMENT,
1746
- {using: 'css selector', value: '*[id="foo"]'})
1747
- .andReturnSuccess(WebElement.buildId('abc123'))
1748
- .end();
1749
-
1750
- var driver = executor.createDriver();
1751
- var otherFlow = new promise.ControlFlow();
1752
- otherFlow.execute(function() {
1753
- driver.findElement({id: 'foo'}).then(function() {
1754
- assert.equal(driver.controlFlow(), promise.controlFlow());
1755
- });
1756
- });
1757
-
1758
- assert.notEqual(otherFlow, driver.controlFlow);
1759
- return Promise.all([
1760
- waitForIdle(otherFlow),
1761
- waitForIdle(driver.controlFlow())
1762
- ]);
1763
- });
1764
- });
1765
-
1766
1330
  it('testFetchingLogs', function() {
1767
1331
  let executor = new FakeExecutor().
1768
1332
  expect(CName.GET_LOG, {'type': 'browser'}).
@@ -1794,10 +1358,7 @@ describe('WebDriver', function() {
1794
1358
  var driver = new FakeExecutor().createDriver(session);
1795
1359
  var navigateResult = driver.get('some-url').then(fail, assertIsStubError);
1796
1360
  var quitResult = driver.quit().then(fail, assertIsStubError);
1797
-
1798
- return waitForIdle().then(function() {
1799
- return promise.all(navigateResult, quitResult);
1800
- });
1361
+ return Promise.all([navigateResult, quitResult]);
1801
1362
  });
1802
1363
 
1803
1364
  it('testWebElementCommandsFailIfInitialDriverCreationFailed', function() {
@@ -1836,185 +1397,133 @@ describe('WebDriver', function() {
1836
1397
  });
1837
1398
 
1838
1399
  describe('actions()', function() {
1839
- it('failsIfInitialDriverCreationFailed', function() {
1840
- let session = Promise.reject(new StubError('no session for you'));
1841
- let driver = new FakeExecutor().createDriver(session);
1842
- driver.getSession().catch(function() {});
1843
- return driver.
1844
- actions().
1845
- mouseDown().
1846
- mouseUp().
1847
- perform().
1848
- catch(assertIsStubError);
1849
- });
1850
-
1851
- describe('mouseMove', function() {
1852
- it('noElement', function() {
1400
+ describe('move()', function() {
1401
+ it('no origin', function() {
1853
1402
  let executor = new FakeExecutor()
1854
- .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
+ })
1855
1419
  .andReturnSuccess()
1856
1420
  .end();
1857
1421
 
1858
- return executor.createDriver().
1859
- actions().
1860
- mouseMove({x: 0, y: 125}).
1861
- perform();
1422
+ let driver = executor.createDriver();
1423
+ return driver.actions().move({x: 0, y: 125}).perform();
1862
1424
  });
1863
1425
 
1864
- it('element', function() {
1426
+ it('origin = element', function() {
1865
1427
  let executor = new FakeExecutor()
1866
1428
  .expect(CName.FIND_ELEMENT,
1867
1429
  {using: 'css selector', value: '*[id="foo"]'})
1868
1430
  .andReturnSuccess(WebElement.buildId('abc123'))
1869
- .expect(CName.MOVE_TO,
1870
- {'element': 'abc123', 'xoffset': 0, 'yoffset': 125})
1871
- .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
+ })
1872
1447
  .end();
1873
1448
 
1874
- var driver = executor.createDriver();
1875
- var element = driver.findElement(By.id('foo'));
1876
- return driver.actions()
1877
- .mouseMove(element, {x: 0, y: 125})
1878
- .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();
1879
1452
  });
1880
1453
  });
1454
+ });
1881
1455
 
1882
- it('supportsMouseDown', function() {
1883
- let executor = new FakeExecutor()
1884
- .expect(CName.MOUSE_DOWN, {'button': Button.LEFT})
1885
- .andReturnSuccess()
1886
- .end();
1887
-
1888
- return executor.createDriver().
1889
- actions().
1890
- mouseDown().
1891
- perform();
1892
- });
1893
-
1894
- it('testActionSequence', function() {
1895
- let executor = new FakeExecutor()
1896
- .expect(CName.FIND_ELEMENT,
1897
- {using: 'css selector', value: '*[id="a"]'})
1898
- .andReturnSuccess(WebElement.buildId('id1'))
1899
- .expect(CName.FIND_ELEMENT,
1900
- {using: 'css selector', value: '*[id="b"]'})
1901
- .andReturnSuccess(WebElement.buildId('id2'))
1902
- .expect(CName.SEND_KEYS_TO_ACTIVE_ELEMENT,
1903
- {'value': [Key.SHIFT]})
1904
- .andReturnSuccess()
1905
- .expect(CName.MOVE_TO, {'element': 'id1'})
1906
- .andReturnSuccess()
1907
- .expect(CName.CLICK, {'button': Button.LEFT})
1908
- .andReturnSuccess()
1909
- .expect(CName.MOVE_TO, {'element': 'id2'})
1910
- .andReturnSuccess()
1911
- .expect(CName.CLICK, {'button': Button.LEFT})
1912
- .andReturnSuccess()
1913
- .end();
1456
+ describe('manage()', function() {
1457
+ describe('setTimeouts()', function() {
1458
+ describe('throws if no timeouts are specified', function() {
1459
+ let driver;
1460
+ before(() => driver = new FakeExecutor().createDriver());
1914
1461
 
1915
- var driver = executor.createDriver();
1916
- var element1 = driver.findElement(By.id('a'));
1917
- var element2 = driver.findElement(By.id('b'));
1462
+ it('; no arguments', function() {
1463
+ assert.throws(() => driver.manage().setTimeouts(), TypeError);
1464
+ });
1918
1465
 
1919
- return driver.actions()
1920
- .keyDown(Key.SHIFT)
1921
- .click(element1)
1922
- .click(element2)
1923
- .perform();
1924
- });
1925
- });
1466
+ it('; ignores unrecognized timeout keys', function() {
1467
+ assert.throws(
1468
+ () => driver.manage().setTimeouts({foo: 123}), TypeError);
1469
+ });
1926
1470
 
1927
- describe('touchActions()', function() {
1928
- it('failsIfInitialDriverCreationFailed', function() {
1929
- let session = Promise.reject(new StubError);
1930
- let driver = new FakeExecutor().createDriver(session);
1931
- driver.getSession().catch(function() {});
1932
- return driver.
1933
- touchActions().
1934
- scroll({x: 3, y: 4}).
1935
- perform().
1936
- catch(assertIsStubError);
1937
- });
1471
+ it('; ignores positional arguments', function() {
1472
+ assert.throws(
1473
+ () => driver.manage().setTimeouts(1234, 56), TypeError);
1474
+ });
1475
+ });
1938
1476
 
1939
- it('testTouchActionSequence', function() {
1940
- let executor = new FakeExecutor()
1941
- .expect(CName.TOUCH_DOWN, {x: 1, y: 2}).andReturnSuccess()
1942
- .expect(CName.TOUCH_MOVE, {x: 3, y: 4}).andReturnSuccess()
1943
- .expect(CName.TOUCH_UP, {x: 5, y: 6}).andReturnSuccess()
1944
- .end();
1477
+ describe('throws timeout is not a number, null, or undefined', () => {
1478
+ let driver;
1479
+ before(() => driver = new FakeExecutor().createDriver());
1945
1480
 
1946
- var driver = executor.createDriver();
1947
- return driver.touchActions()
1948
- .tapAndHold({x: 1, y: 2})
1949
- .move({x: 3, y: 4})
1950
- .release({x: 5, y: 6})
1951
- .perform();
1952
- });
1953
- });
1481
+ function checkError(e) {
1482
+ return e instanceof TypeError
1483
+ && /expected "(script|pageLoad|implicit)" to be a number/.test(
1484
+ e.message);
1485
+ }
1954
1486
 
1955
- describe('generator support', function() {
1956
- var driver;
1487
+ it('script', function() {
1488
+ assert.throws(
1489
+ () => driver.manage().setTimeouts({script: 'abc'}),
1490
+ checkError);
1491
+ });
1957
1492
 
1958
- beforeEach(function() {
1959
- driver = new WebDriver(
1960
- new Session('test-session', {}),
1961
- new ExplodingExecutor());
1962
- });
1493
+ it('pageLoad', function() {
1494
+ assert.throws(
1495
+ () => driver.manage().setTimeouts({pageLoad: 'abc'}),
1496
+ checkError);
1497
+ });
1963
1498
 
1964
- it('canUseGeneratorsWithWebDriverCall', function() {
1965
- return driver.call(function* () {
1966
- var x = yield Promise.resolve(1);
1967
- var y = yield Promise.resolve(2);
1968
- return x + y;
1969
- }).then(function(value) {
1970
- assert.deepEqual(3, value);
1499
+ it('implicit', function() {
1500
+ assert.throws(
1501
+ () => driver.manage().setTimeouts({implicit: 'abc'}),
1502
+ checkError);
1503
+ });
1971
1504
  });
1972
- });
1973
1505
 
1974
- it('canDefineScopeOnGeneratorCall', function() {
1975
- return driver.call(function* () {
1976
- var x = yield Promise.resolve(1);
1977
- return this.name + x;
1978
- }, {name: 'Bob'}).then(function(value) {
1979
- assert.deepEqual('Bob1', value);
1980
- });
1981
- });
1982
-
1983
- it('canSpecifyArgsOnGeneratorCall', function() {
1984
- return driver.call(function* (a, b) {
1985
- var x = yield Promise.resolve(1);
1986
- var y = yield Promise.resolve(2);
1987
- return [x + y, a, b];
1988
- }, null, 'abc', 123).then(function(value) {
1989
- assert.deepEqual([3, 'abc', 123], value);
1506
+ it('can set multiple timeouts', function() {
1507
+ let executor = new FakeExecutor()
1508
+ .expect(CName.SET_TIMEOUT, {script:1, pageLoad: 2, implicit: 3})
1509
+ .andReturnSuccess()
1510
+ .end();
1511
+ let driver = executor.createDriver();
1512
+ return driver.manage()
1513
+ .setTimeouts({script: 1, pageLoad: 2, implicit: 3});
1990
1514
  });
1991
- });
1992
1515
 
1993
- it('canUseGeneratorWithWebDriverWait', function() {
1994
- var values = [];
1995
- return driver.wait(function* () {
1996
- yield values.push(1);
1997
- values.push(yield promise.delayed(10).then(function() {
1998
- return 2;
1999
- }));
2000
- yield values.push(3);
2001
- return values.length === 6;
2002
- }, 250).then(function() {
2003
- assert.deepEqual([1, 2, 3, 1, 2, 3], values);
1516
+ it('falls back to legacy wire format if W3C version fails', () => {
1517
+ let executor = new FakeExecutor()
1518
+ .expect(CName.SET_TIMEOUT, {implicit: 3})
1519
+ .andReturnError(Error('oops'))
1520
+ .expect(CName.SET_TIMEOUT, {type: 'implicit', ms: 3})
1521
+ .andReturnSuccess()
1522
+ .end();
1523
+ let driver = executor.createDriver();
1524
+ return driver.manage().setTimeouts({implicit: 3});
2004
1525
  });
2005
1526
  });
2006
-
2007
- /**
2008
- * @constructor
2009
- * @implements {CommandExecutor}
2010
- */
2011
- function ExplodingExecutor() {}
2012
-
2013
-
2014
- /** @override */
2015
- ExplodingExecutor.prototype.execute = function(command, cb) {
2016
- cb(Error('Unsupported operation'));
2017
- };
2018
1527
  });
2019
1528
 
2020
1529
  describe('wire format', function() {
@@ -2024,10 +1533,16 @@ describe('WebDriver', function() {
2024
1533
  function runSerializeTest(input, want) {
2025
1534
  let executor = new FakeExecutor().
2026
1535
  expect(CName.NEW_SESSION).
2027
- withParameters({'desiredCapabilities': want}).
1536
+ withParameters({
1537
+ 'desiredCapabilities': {'serialize-test': want},
1538
+ 'capabilities': {'alwaysMatch': {}},
1539
+ }).
2028
1540
  andReturnSuccess({'browserName': 'firefox'}).
2029
1541
  end();
2030
- 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})
2031
1546
  .getSession();
2032
1547
  }
2033
1548
 
@@ -2120,8 +1635,7 @@ describe('WebDriver', function() {
2120
1635
 
2121
1636
  it('with sub-objects', function() {
2122
1637
  var expected = {sessionId: {value: 'foo'}};
2123
- return runSerializeTest(
2124
- {sessionId: {value: 'foo'}}, expected);
1638
+ return runSerializeTest({sessionId: {value: 'foo'}}, expected);
2125
1639
  });
2126
1640
 
2127
1641
  it('with values that have toJSON', function() {
@@ -2153,6 +1667,24 @@ describe('WebDriver', function() {
2153
1667
 
2154
1668
  return runSerializeTest(parameters, expected);
2155
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
+ });
2156
1688
  });
2157
1689
  });
2158
1690