Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/javascript/selenium-webdriver/test/lib/webdriver_test.js
2885 views
1
// Licensed to the Software Freedom Conservancy (SFC) under one
2
// or more contributor license agreements. See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership. The SFC licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License. You may obtain a copy of the License at
8
//
9
// http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied. See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
'use strict'
19
20
const { StubError, assertIsInstance, assertIsStubError, throwStubError } = require('./testutil')
21
22
const error = require('selenium-webdriver/lib/error')
23
const logging = require('selenium-webdriver/lib/logging')
24
const promise = require('selenium-webdriver/lib/promise')
25
const until = require('selenium-webdriver/lib/until')
26
const { Alert, AlertPromise, WebDriver, WebElement, WebElementPromise } = require('selenium-webdriver/lib/webdriver')
27
const { By } = require('selenium-webdriver/lib/by')
28
const { Capabilities } = require('selenium-webdriver/lib/capabilities')
29
const { Name } = require('selenium-webdriver/lib/command')
30
const { Session } = require('selenium-webdriver/lib/session')
31
const assert = require('node:assert')
32
33
const CName = Name
34
const SESSION_ID = 'test_session_id'
35
const fail = (msg) => assert.fail(msg)
36
37
describe('WebDriver', function () {
38
const LOG = logging.getLogger('webdriver.test')
39
40
function defer() {
41
let d = {}
42
let promise = new Promise((resolve, reject) => {
43
Object.assign(d, { resolve, reject })
44
})
45
d.promise = promise
46
return d
47
}
48
49
function expectedError(ctor, message) {
50
return function (e) {
51
assertIsInstance(ctor, e)
52
assert.strictEqual(message, e.message)
53
}
54
}
55
56
class Expectation {
57
constructor(executor, name, opt_parameters) {
58
this.executor_ = executor
59
this.name_ = name
60
this.times_ = 1
61
this.sessionId_ = SESSION_ID
62
this.check_ = null
63
this.toDo_ = null
64
this.withParameters(opt_parameters || {})
65
}
66
67
anyTimes() {
68
this.times_ = Infinity
69
return this
70
}
71
72
times(n) {
73
this.times_ = n
74
return this
75
}
76
77
withParameters(parameters) {
78
this.parameters_ = parameters
79
if (this.name_ !== CName.NEW_SESSION) {
80
this.parameters_['sessionId'] = this.sessionId_
81
}
82
return this
83
}
84
85
andReturn(code, opt_value) {
86
this.toDo_ = function (command) {
87
LOG.info('executing ' + command.getName() + '; returning ' + code)
88
return Promise.resolve(opt_value !== void 0 ? opt_value : null)
89
}
90
return this
91
}
92
93
andReturnSuccess(opt_value) {
94
this.toDo_ = function (command) {
95
LOG.info('executing ' + command.getName() + '; returning success')
96
return Promise.resolve(opt_value !== void 0 ? opt_value : null)
97
}
98
return this
99
}
100
101
andReturnError(error) {
102
if (typeof error === 'number') {
103
throw Error('need error type')
104
}
105
this.toDo_ = function (command) {
106
LOG.info('executing ' + command.getName() + '; returning failure')
107
return Promise.reject(error)
108
}
109
return this
110
}
111
112
expect(name, opt_parameters) {
113
this.end()
114
return this.executor_.expect(name, opt_parameters)
115
}
116
117
end() {
118
if (!this.toDo_) {
119
this.andReturnSuccess(null)
120
}
121
return this.executor_
122
}
123
124
execute(command) {
125
assert.deepStrictEqual(command.getParameters(), this.parameters_)
126
return this.toDo_(command)
127
}
128
}
129
130
class FakeExecutor {
131
constructor() {
132
this.commands_ = new Map()
133
}
134
135
execute(command) {
136
let expectations = this.commands_.get(command.getName())
137
if (!expectations || !expectations.length) {
138
assert.fail('unexpected command: ' + command.getName())
139
return
140
}
141
142
let next = expectations[0]
143
let result = next.execute(command)
144
if (next.times_ !== Infinity) {
145
next.times_ -= 1
146
if (!next.times_) {
147
expectations.shift()
148
}
149
}
150
return result
151
}
152
153
expect(commandName, opt_parameters) {
154
if (!this.commands_.has(commandName)) {
155
this.commands_.set(commandName, [])
156
}
157
let e = new Expectation(this, commandName, opt_parameters)
158
this.commands_.get(commandName).push(e)
159
return e
160
}
161
162
createDriver(opt_session) {
163
let session = opt_session || new Session(SESSION_ID, {})
164
return new WebDriver(session, this)
165
}
166
}
167
168
/////////////////////////////////////////////////////////////////////////////
169
//
170
// Tests
171
//
172
/////////////////////////////////////////////////////////////////////////////
173
174
describe('testCreateSession', function () {
175
it('happyPathWithCapabilitiesHashObject', function () {
176
let aSession = new Session(SESSION_ID, { browserName: 'firefox' })
177
let executor = new FakeExecutor()
178
.expect(CName.NEW_SESSION)
179
.withParameters({
180
capabilities: {
181
alwaysMatch: { browserName: 'firefox' },
182
firstMatch: [{}],
183
},
184
})
185
.andReturnSuccess(aSession)
186
.end()
187
188
const driver = WebDriver.createSession(executor, {
189
browserName: 'firefox',
190
})
191
return driver.getSession().then((v) => assert.strictEqual(v, aSession))
192
})
193
194
it('happy Path With Capabilities Instance', function () {
195
let aSession = new Session(SESSION_ID, { browserName: 'firefox' })
196
let executor = new FakeExecutor()
197
.expect(CName.NEW_SESSION)
198
.withParameters({
199
capabilities: {
200
alwaysMatch: {
201
'moz:debuggerAddress': true,
202
browserName: 'firefox',
203
},
204
firstMatch: [{}],
205
},
206
})
207
.andReturnSuccess(aSession)
208
.end()
209
210
const driver = WebDriver.createSession(executor, Capabilities.firefox())
211
return driver.getSession().then((v) => assert.strictEqual(v, aSession))
212
})
213
214
it('drops non-W3C capability names from W3C capabilities', function () {
215
let aSession = new Session(SESSION_ID, { browserName: 'firefox' })
216
let executor = new FakeExecutor()
217
.expect(CName.NEW_SESSION)
218
.withParameters({
219
capabilities: {
220
alwaysMatch: { browserName: 'firefox' },
221
firstMatch: [{}],
222
},
223
})
224
.andReturnSuccess(aSession)
225
.end()
226
227
const driver = WebDriver.createSession(executor, {
228
browserName: 'firefox',
229
foo: 'bar',
230
})
231
return driver.getSession().then((v) => assert.strictEqual(v, aSession))
232
})
233
234
it('failsToCreateSession', function () {
235
let executor = new FakeExecutor()
236
.expect(CName.NEW_SESSION)
237
.withParameters({
238
capabilities: {
239
alwaysMatch: { browserName: 'firefox' },
240
firstMatch: [{}],
241
},
242
})
243
.andReturnError(new StubError())
244
.end()
245
246
const driver = WebDriver.createSession(executor, {
247
browserName: 'firefox',
248
})
249
return driver.getSession().then(fail, assertIsStubError)
250
})
251
252
it('invokes quit callback if it fails to create a session', function () {
253
let called = false
254
let executor = new FakeExecutor()
255
.expect(CName.NEW_SESSION)
256
.withParameters({
257
capabilities: {
258
alwaysMatch: { browserName: 'firefox' },
259
firstMatch: [{}],
260
},
261
})
262
.andReturnError(new StubError())
263
.end()
264
265
let driver = WebDriver.createSession(executor, { browserName: 'firefox' }, () => (called = true))
266
return driver.getSession().then(fail, (err) => {
267
assert.ok(called)
268
assertIsStubError(err)
269
})
270
})
271
})
272
273
it('testDoesNotExecuteCommandIfSessionDoesNotResolve', function () {
274
const session = Promise.reject(new StubError())
275
return new FakeExecutor()
276
.createDriver(session)
277
.getTitle()
278
.then((_) => assert.fail('should have failed'), assertIsStubError)
279
})
280
281
it('testCommandReturnValuesArePassedToFirstCallback', function () {
282
let executor = new FakeExecutor().expect(CName.GET_TITLE).andReturnSuccess('Google Search').end()
283
284
const driver = executor.createDriver()
285
return driver.getTitle().then((title) => assert.strictEqual('Google Search', title))
286
})
287
288
it('testStopsCommandExecutionWhenAnErrorOccurs', function () {
289
let e = new error.NoSuchWindowError('window not found')
290
let executor = new FakeExecutor()
291
.expect(CName.SWITCH_TO_WINDOW)
292
.withParameters({
293
name: 'foo',
294
handle: 'foo',
295
})
296
.andReturnError(e)
297
.end()
298
299
let driver = executor.createDriver()
300
return driver
301
.switchTo()
302
.window('foo')
303
.then(
304
(_) => driver.getTitle(), // mock should blow if this gets executed
305
(v) => assert.strictEqual(v, e),
306
)
307
})
308
309
it('testReportsErrorWhenExecutingCommandsAfterExecutingAQuit', function () {
310
let executor = new FakeExecutor().expect(CName.QUIT).end()
311
312
let verifyError = expectedError(
313
error.NoSuchSessionError,
314
'This driver instance does not have a valid session ID ' +
315
'(did you call WebDriver.quit()?) and may no longer be used.',
316
)
317
318
let driver = executor.createDriver()
319
return driver
320
.quit()
321
.then((_) => driver.get('http://www.google.com'))
322
.then(assert.fail, verifyError)
323
})
324
325
describe('returningAPromise', function () {
326
it('fromACallback', function () {
327
let executor = new FakeExecutor()
328
.expect(CName.GET_TITLE)
329
.expect(CName.GET_CURRENT_URL)
330
.andReturnSuccess('http://www.google.com')
331
.end()
332
333
const driver = executor.createDriver()
334
return driver
335
.getTitle()
336
.then(function () {
337
return driver.getCurrentUrl()
338
})
339
.then(function (value) {
340
assert.strictEqual('http://www.google.com', value)
341
})
342
})
343
344
it('fromAnErrbackSuppressesTheError', function () {
345
let executor = new FakeExecutor()
346
.expect(CName.SWITCH_TO_WINDOW, {
347
name: 'foo',
348
handle: 'foo',
349
})
350
.andReturnError(new StubError())
351
.expect(CName.GET_CURRENT_URL)
352
.andReturnSuccess('http://www.google.com')
353
.end()
354
355
const driver = executor.createDriver()
356
return driver
357
.switchTo()
358
.window('foo')
359
.catch(function (e) {
360
assertIsStubError(e)
361
return driver.getCurrentUrl()
362
})
363
.then((url) => assert.strictEqual('http://www.google.com', url))
364
})
365
})
366
367
describe('WebElementPromise', function () {
368
let driver = new FakeExecutor().createDriver()
369
370
it('resolvesWhenUnderlyingElementDoes', function () {
371
let el = new WebElement(driver, { ELEMENT: 'foo' })
372
return new WebElementPromise(driver, Promise.resolve(el)).then((e) => assert.strictEqual(e, el))
373
})
374
375
it('resolvesBeforeCallbacksOnWireValueTrigger', function () {
376
const el = defer()
377
378
const element = new WebElementPromise(driver, el.promise)
379
const messages = []
380
381
let steps = [
382
element.then((_) => messages.push('element resolved')),
383
element.getId().then((_) => messages.push('wire value resolved')),
384
]
385
386
el.resolve(new WebElement(driver, { ELEMENT: 'foo' }))
387
return Promise.all(steps).then(function () {
388
assert.deepStrictEqual(['element resolved', 'wire value resolved'], messages)
389
})
390
})
391
392
it('isRejectedIfUnderlyingIdIsRejected', function () {
393
let element = new WebElementPromise(driver, Promise.reject(new StubError()))
394
return element.then(fail, assertIsStubError)
395
})
396
})
397
398
describe('executeScript', function () {
399
it('nullReturnValue', function () {
400
let executor = new FakeExecutor()
401
.expect(CName.EXECUTE_SCRIPT)
402
.withParameters({
403
script: 'return document.body;',
404
args: [],
405
})
406
.andReturnSuccess(null)
407
.end()
408
409
const driver = executor.createDriver()
410
return driver.executeScript('return document.body;').then((result) => assert.strictEqual(null, result))
411
})
412
413
it('primitiveReturnValue', function () {
414
let executor = new FakeExecutor()
415
.expect(CName.EXECUTE_SCRIPT)
416
.withParameters({
417
script: 'return document.body;',
418
args: [],
419
})
420
.andReturnSuccess(123)
421
.end()
422
423
const driver = executor.createDriver()
424
return driver.executeScript('return document.body;').then((result) => assert.strictEqual(123, result))
425
})
426
427
it('webElementReturnValue', function () {
428
const json = WebElement.buildId('foo')
429
430
let executor = new FakeExecutor()
431
.expect(CName.EXECUTE_SCRIPT)
432
.withParameters({
433
script: 'return document.body;',
434
args: [],
435
})
436
.andReturnSuccess(json)
437
.end()
438
439
const driver = executor.createDriver()
440
return driver
441
.executeScript('return document.body;')
442
.then((element) => element.getId())
443
.then((id) => assert.strictEqual(id, 'foo'))
444
})
445
446
it('arrayReturnValue', function () {
447
const json = [WebElement.buildId('foo')]
448
449
let executor = new FakeExecutor()
450
.expect(CName.EXECUTE_SCRIPT)
451
.withParameters({
452
script: 'return document.body;',
453
args: [],
454
})
455
.andReturnSuccess(json)
456
.end()
457
458
const driver = executor.createDriver()
459
return driver
460
.executeScript('return document.body;')
461
.then(function (array) {
462
assert.strictEqual(1, array.length)
463
return array[0].getId()
464
})
465
.then((id) => assert.strictEqual('foo', id))
466
})
467
468
it('objectReturnValue', function () {
469
const json = { foo: WebElement.buildId('foo') }
470
471
let executor = new FakeExecutor()
472
.expect(CName.EXECUTE_SCRIPT)
473
.withParameters({
474
script: 'return document.body;',
475
args: [],
476
})
477
.andReturnSuccess(json)
478
.end()
479
480
const driver = executor.createDriver()
481
return driver
482
.executeScript('return document.body;')
483
.then((obj) => obj['foo'].getId())
484
.then((id) => assert.strictEqual(id, 'foo'))
485
})
486
487
it('scriptAsFunction', function () {
488
let executor = new FakeExecutor()
489
.expect(CName.EXECUTE_SCRIPT)
490
.withParameters({
491
script: 'return (' + function () {} + ').apply(null, arguments);',
492
args: [],
493
})
494
.andReturnSuccess(null)
495
.end()
496
497
const driver = executor.createDriver()
498
return driver.executeScript(function () {})
499
})
500
501
it('simpleArgumentConversion', function () {
502
let executor = new FakeExecutor()
503
.expect(CName.EXECUTE_SCRIPT)
504
.withParameters({
505
script: 'return 1;',
506
args: ['abc', 123, true, [123, { foo: 'bar' }]],
507
})
508
.andReturnSuccess(null)
509
.end()
510
511
const driver = executor.createDriver()
512
return driver.executeScript('return 1;', 'abc', 123, true, [123, { foo: 'bar' }])
513
})
514
515
it('webElementArgumentConversion', function () {
516
const elementJson = WebElement.buildId('fefifofum')
517
518
let executor = new FakeExecutor()
519
.expect(CName.EXECUTE_SCRIPT)
520
.withParameters({
521
script: 'return 1;',
522
args: [elementJson],
523
})
524
.andReturnSuccess(null)
525
.end()
526
527
const driver = executor.createDriver()
528
return driver.executeScript('return 1;', new WebElement(driver, 'fefifofum'))
529
})
530
531
it('webElementPromiseArgumentConversion', function () {
532
const elementJson = WebElement.buildId('bar')
533
534
let executor = new FakeExecutor()
535
.expect(CName.FIND_ELEMENT, {
536
using: 'css selector',
537
value: '*[id="foo"]',
538
})
539
.andReturnSuccess(elementJson)
540
.expect(CName.EXECUTE_SCRIPT)
541
.withParameters({
542
script: 'return 1;',
543
args: [elementJson],
544
})
545
.andReturnSuccess(null)
546
.end()
547
548
const driver = executor.createDriver()
549
const element = driver.findElement(By.id('foo'))
550
return driver.executeScript('return 1;', element)
551
})
552
553
it('argumentConversion', function () {
554
const elementJson = WebElement.buildId('fefifofum')
555
556
let executor = new FakeExecutor()
557
.expect(CName.EXECUTE_SCRIPT)
558
.withParameters({
559
script: 'return 1;',
560
args: ['abc', 123, true, elementJson, [123, { foo: 'bar' }]],
561
})
562
.andReturnSuccess(null)
563
.end()
564
565
const driver = executor.createDriver()
566
const element = new WebElement(driver, 'fefifofum')
567
return driver.executeScript('return 1;', 'abc', 123, true, element, [123, { foo: 'bar' }])
568
})
569
570
it('scriptReturnsAnError', function () {
571
let executor = new FakeExecutor()
572
.expect(CName.EXECUTE_SCRIPT)
573
.withParameters({
574
script: 'throw Error(arguments[0]);',
575
args: ['bam'],
576
})
577
.andReturnError(new StubError())
578
.end()
579
const driver = executor.createDriver()
580
return driver.executeScript('throw Error(arguments[0]);', 'bam').then(fail, assertIsStubError)
581
})
582
583
it('failsIfArgumentIsARejectedPromise', function () {
584
let executor = new FakeExecutor()
585
586
const arg = Promise.reject(new StubError())
587
arg.catch(function () {}) // Suppress default handler.
588
589
const driver = executor.createDriver()
590
return driver.executeScript(function () {}, arg).then(fail, assertIsStubError)
591
})
592
})
593
594
describe('executeAsyncScript', function () {
595
it('failsIfArgumentIsARejectedPromise', function () {
596
const arg = Promise.reject(new StubError())
597
arg.catch(function () {}) // Suppress default handler.
598
599
const driver = new FakeExecutor().createDriver()
600
return driver.executeAsyncScript(function () {}, arg).then(fail, assertIsStubError)
601
})
602
})
603
604
describe('findElement', function () {
605
it('elementNotFound', function () {
606
let executor = new FakeExecutor()
607
.expect(CName.FIND_ELEMENT, {
608
using: 'css selector',
609
value: '*[id="foo"]',
610
})
611
.andReturnError(new StubError())
612
.end()
613
614
const driver = executor.createDriver()
615
return driver.findElement(By.id('foo')).then(assert.fail, assertIsStubError)
616
})
617
618
it('elementNotFoundInACallback', function () {
619
let executor = new FakeExecutor()
620
.expect(CName.FIND_ELEMENT, {
621
using: 'css selector',
622
value: '*[id="foo"]',
623
})
624
.andReturnError(new StubError())
625
.end()
626
627
const driver = executor.createDriver()
628
return Promise.resolve()
629
.then((_) => driver.findElement(By.id('foo')))
630
.then(assert.fail, assertIsStubError)
631
})
632
633
it('elementFound', function () {
634
let executor = new FakeExecutor()
635
.expect(CName.FIND_ELEMENT, {
636
using: 'css selector',
637
value: '*[id="foo"]',
638
})
639
.andReturnSuccess(WebElement.buildId('bar'))
640
.expect(CName.CLICK_ELEMENT, { id: WebElement.buildId('bar') })
641
.andReturnSuccess()
642
.end()
643
644
const driver = executor.createDriver()
645
const element = driver.findElement(By.id('foo'))
646
return element.click()
647
})
648
649
it('canUseElementInCallback', function () {
650
let executor = new FakeExecutor()
651
.expect(CName.FIND_ELEMENT, {
652
using: 'css selector',
653
value: '*[id="foo"]',
654
})
655
.andReturnSuccess(WebElement.buildId('bar'))
656
.expect(CName.CLICK_ELEMENT, { id: WebElement.buildId('bar') })
657
.andReturnSuccess()
658
.end()
659
660
const driver = executor.createDriver()
661
return driver.findElement(By.id('foo')).then((e) => e.click())
662
})
663
664
it('byJs', function () {
665
let executor = new FakeExecutor()
666
.expect(CName.EXECUTE_SCRIPT, {
667
script: 'return document.body',
668
args: [],
669
})
670
.andReturnSuccess(WebElement.buildId('bar'))
671
.expect(CName.CLICK_ELEMENT, { id: WebElement.buildId('bar') })
672
.end()
673
674
const driver = executor.createDriver()
675
return driver.findElement(By.js('return document.body')).then((e) => e.click())
676
})
677
678
it('byJs_returnsNonWebElementValue', function () {
679
let executor = new FakeExecutor()
680
.expect(CName.EXECUTE_SCRIPT, { script: 'return 123', args: [] })
681
.andReturnSuccess(123)
682
.end()
683
684
const driver = executor.createDriver()
685
return driver.findElement(By.js('return 123')).then(assert.fail, function (e) {
686
assertIsInstance(TypeError, e)
687
assert.strictEqual('Custom locator did not return a WebElement', e.message)
688
})
689
})
690
691
it('byJs_canPassArguments', function () {
692
const script = 'return document.getElementsByTagName(arguments[0]);'
693
let executor = new FakeExecutor()
694
.expect(CName.EXECUTE_SCRIPT, {
695
script: script,
696
args: ['div'],
697
})
698
.andReturnSuccess(WebElement.buildId('one'))
699
.end()
700
const driver = executor.createDriver()
701
return driver.findElement(By.js(script, 'div'))
702
})
703
704
it('customLocator', function () {
705
let executor = new FakeExecutor()
706
.expect(CName.FIND_ELEMENTS, { using: 'css selector', value: '.a' })
707
.andReturnSuccess([WebElement.buildId('foo'), WebElement.buildId('bar')])
708
.expect(CName.CLICK_ELEMENT, { id: WebElement.buildId('foo') })
709
.andReturnSuccess()
710
.end()
711
712
const driver = executor.createDriver()
713
const element = driver.findElement(function (d) {
714
assert.strictEqual(driver, d)
715
return d.findElements(By.className('a'))
716
})
717
return element.click()
718
})
719
720
it('customLocatorThrowsIfresultIsNotAWebElement', function () {
721
const driver = new FakeExecutor().createDriver()
722
return driver
723
.findElement((_) => 1)
724
.then(assert.fail, function (e) {
725
assertIsInstance(TypeError, e)
726
assert.strictEqual('Custom locator did not return a WebElement', e.message)
727
})
728
})
729
})
730
731
describe('findElements', function () {
732
it('returnsMultipleElements', function () {
733
const ids = ['foo', 'bar', 'baz']
734
let executor = new FakeExecutor()
735
.expect(CName.FIND_ELEMENTS, { using: 'css selector', value: '.a' })
736
.andReturnSuccess(ids.map(WebElement.buildId))
737
.end()
738
739
const driver = executor.createDriver()
740
return driver
741
.findElements(By.className('a'))
742
.then(function (elements) {
743
return Promise.all(
744
elements.map(function (e) {
745
assert.ok(e instanceof WebElement)
746
return e.getId()
747
}),
748
)
749
})
750
.then((actual) => assert.deepStrictEqual(ids, actual))
751
})
752
753
it('byJs', function () {
754
const ids = ['foo', 'bar', 'baz']
755
let executor = new FakeExecutor()
756
.expect(CName.EXECUTE_SCRIPT, {
757
script: 'return document.getElementsByTagName("div");',
758
args: [],
759
})
760
.andReturnSuccess(ids.map(WebElement.buildId))
761
.end()
762
763
const driver = executor.createDriver()
764
765
return driver
766
.findElements(By.js('return document.getElementsByTagName("div");'))
767
.then(function (elements) {
768
return Promise.all(
769
elements.map(function (e) {
770
assert.ok(e instanceof WebElement)
771
return e.getId()
772
}),
773
)
774
})
775
.then((actual) => assert.deepStrictEqual(ids, actual))
776
})
777
778
it('byJs_filtersOutNonWebElementResponses', function () {
779
const ids = ['foo', 'bar', 'baz']
780
const json = [
781
WebElement.buildId(ids[0]),
782
123,
783
'a',
784
false,
785
WebElement.buildId(ids[1]),
786
{ 'not a web element': 1 },
787
WebElement.buildId(ids[2]),
788
]
789
let executor = new FakeExecutor()
790
.expect(CName.EXECUTE_SCRIPT, {
791
script: 'return document.getElementsByTagName("div");',
792
args: [],
793
})
794
.andReturnSuccess(json)
795
.end()
796
797
const driver = executor.createDriver()
798
return driver
799
.findElements(By.js('return document.getElementsByTagName("div");'))
800
.then(function (elements) {
801
return Promise.all(
802
elements.map(function (e) {
803
assert.ok(e instanceof WebElement)
804
return e.getId()
805
}),
806
)
807
})
808
.then((actual) => assert.deepStrictEqual(ids, actual))
809
})
810
811
it('byJs_convertsSingleWebElementResponseToArray', function () {
812
let executor = new FakeExecutor()
813
.expect(CName.EXECUTE_SCRIPT, {
814
script: 'return document.getElementsByTagName("div");',
815
args: [],
816
})
817
.andReturnSuccess(WebElement.buildId('foo'))
818
.end()
819
820
const driver = executor.createDriver()
821
return driver
822
.findElements(By.js('return document.getElementsByTagName("div");'))
823
.then(function (elements) {
824
return Promise.all(
825
elements.map(function (e) {
826
assert.ok(e instanceof WebElement)
827
return e.getId()
828
}),
829
)
830
})
831
.then((actual) => assert.deepStrictEqual(['foo'], actual))
832
})
833
834
it('byJs_canPassScriptArguments', function () {
835
const script = 'return document.getElementsByTagName(arguments[0]);'
836
let executor = new FakeExecutor()
837
.expect(CName.EXECUTE_SCRIPT, {
838
script: script,
839
args: ['div'],
840
})
841
.andReturnSuccess([WebElement.buildId('one'), WebElement.buildId('two')])
842
.end()
843
844
const driver = executor.createDriver()
845
return driver
846
.findElements(By.js(script, 'div'))
847
.then(function (elements) {
848
return Promise.all(
849
elements.map(function (e) {
850
assert.ok(e instanceof WebElement)
851
return e.getId()
852
}),
853
)
854
})
855
.then((actual) => assert.deepStrictEqual(['one', 'two'], actual))
856
})
857
})
858
859
describe('sendKeys', function () {
860
it('convertsVarArgsIntoStrings_simpleArgs', function () {
861
let executor = new FakeExecutor()
862
.expect(CName.SEND_KEYS_TO_ELEMENT, {
863
id: WebElement.buildId('one'),
864
text: '12abc3',
865
value: '12abc3'.split(''),
866
})
867
.andReturnSuccess()
868
.end()
869
870
const driver = executor.createDriver()
871
const element = new WebElement(driver, 'one')
872
return element.sendKeys(1, 2, 'abc', 3)
873
})
874
875
it('sendKeysWithEmojiRepresentedByPairOfCodePoints', function () {
876
let executor = new FakeExecutor()
877
.expect(CName.SEND_KEYS_TO_ELEMENT, {
878
id: WebElement.buildId('one'),
879
text: '\uD83D\uDE00',
880
value: ['\uD83D\uDE00'],
881
})
882
.andReturnSuccess()
883
.end()
884
885
const driver = executor.createDriver()
886
const element = new WebElement(driver, 'one')
887
return element.sendKeys('\uD83D\uDE00')
888
})
889
890
it('convertsVarArgsIntoStrings_promisedArgs', function () {
891
let executor = new FakeExecutor()
892
.expect(CName.FIND_ELEMENT, {
893
using: 'css selector',
894
value: '*[id="foo"]',
895
})
896
.andReturnSuccess(WebElement.buildId('one'))
897
.expect(CName.SEND_KEYS_TO_ELEMENT, {
898
id: WebElement.buildId('one'),
899
text: 'abc123def',
900
value: 'abc123def'.split(''),
901
})
902
.andReturnSuccess()
903
.end()
904
905
const driver = executor.createDriver()
906
const element = driver.findElement(By.id('foo'))
907
return element.sendKeys(Promise.resolve('abc'), 123, Promise.resolve('def'))
908
})
909
910
it('sendKeysWithAFileDetector', function () {
911
let executor = new FakeExecutor()
912
.expect(CName.FIND_ELEMENT, {
913
using: 'css selector',
914
value: '*[id="foo"]',
915
})
916
.andReturnSuccess(WebElement.buildId('one'))
917
.expect(CName.SEND_KEYS_TO_ELEMENT, {
918
id: WebElement.buildId('one'),
919
text: 'modified/path',
920
value: 'modified/path'.split(''),
921
})
922
.andReturnSuccess()
923
.end()
924
925
let driver = executor.createDriver()
926
let handleFile = function (d, path) {
927
assert.strictEqual(driver, d)
928
assert.strictEqual(path, 'original/path')
929
return Promise.resolve('modified/path')
930
}
931
driver.setFileDetector({ handleFile })
932
933
return driver.findElement(By.id('foo')).sendKeys('original/', 'path')
934
})
935
936
it('sendKeysWithAFileDetector_handlerError', function () {
937
let executor = new FakeExecutor()
938
.expect(CName.FIND_ELEMENT, {
939
using: 'css selector',
940
value: '*[id="foo"]',
941
})
942
.andReturnSuccess(WebElement.buildId('one'))
943
.expect(CName.SEND_KEYS_TO_ELEMENT, {
944
id: WebElement.buildId('one'),
945
text: 'original/path',
946
value: 'original/path'.split(''),
947
})
948
.andReturnSuccess()
949
.end()
950
951
let driver = executor.createDriver()
952
let handleFile = function (d, path) {
953
assert.strictEqual(driver, d)
954
assert.strictEqual(path, 'original/path')
955
return Promise.reject('unhandled file error')
956
}
957
driver.setFileDetector({ handleFile })
958
959
return driver.findElement(By.id('foo')).sendKeys('original/', 'path')
960
})
961
})
962
963
describe('switchTo()', function () {
964
describe('window', function () {
965
it('should return a resolved promise when the window is found', function () {
966
let executor = new FakeExecutor()
967
.expect(CName.SWITCH_TO_WINDOW)
968
.withParameters({
969
name: 'foo',
970
handle: 'foo',
971
})
972
.andReturnSuccess()
973
.end()
974
975
return executor.createDriver().switchTo().window('foo')
976
})
977
978
it('should propagate exceptions', function () {
979
let e = new error.NoSuchWindowError('window not found')
980
let executor = new FakeExecutor()
981
.expect(CName.SWITCH_TO_WINDOW)
982
.withParameters({
983
name: 'foo',
984
handle: 'foo',
985
})
986
.andReturnError(e)
987
.end()
988
989
return executor
990
.createDriver()
991
.switchTo()
992
.window('foo')
993
.then(assert.fail, (v) => assert.strictEqual(v, e))
994
})
995
})
996
})
997
998
describe('elementEquality', function () {
999
it('isReflexive', function () {
1000
const a = new WebElement(new FakeExecutor().createDriver(), 'foo')
1001
return WebElement.equals(a, a).then(assert.ok)
1002
})
1003
1004
it('failsIfAnInputElementCouldNotBeFound', function () {
1005
let id = Promise.reject(new StubError())
1006
1007
const driver = new FakeExecutor().createDriver()
1008
const a = new WebElement(driver, 'foo')
1009
const b = new WebElementPromise(driver, id)
1010
1011
return WebElement.equals(a, b).then(fail, assertIsStubError)
1012
})
1013
})
1014
1015
describe('waiting', function () {
1016
it('on a condition that always returns true', function () {
1017
let executor = new FakeExecutor()
1018
let driver = executor.createDriver()
1019
let count = 0
1020
1021
function condition() {
1022
count++
1023
return true
1024
}
1025
1026
return driver.wait(condition, 1).then(() => assert.strictEqual(1, count))
1027
})
1028
1029
it('on a simple counting condition', function () {
1030
let executor = new FakeExecutor()
1031
let driver = executor.createDriver()
1032
let count = 0
1033
1034
function condition() {
1035
return ++count === 3
1036
}
1037
1038
return driver.wait(condition, 250).then(() => assert.strictEqual(3, count))
1039
})
1040
1041
it('on a condition that returns a promise that resolves to true after a short timeout', function () {
1042
let executor = new FakeExecutor()
1043
let driver = executor.createDriver()
1044
1045
let count = 0
1046
1047
function condition() {
1048
count += 1
1049
return new Promise((resolve) => {
1050
setTimeout(() => resolve(true), 50)
1051
})
1052
}
1053
1054
return driver.wait(condition, 75).then(() => assert.strictEqual(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
1063
function condition() {
1064
count += 1
1065
return new Promise((resolve) => {
1066
setTimeout(() => resolve(count === 3), 25)
1067
})
1068
}
1069
1070
return driver.wait(condition, 100, null, 25).then(() => assert.strictEqual(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').then(fail, assertIsStubError)
1077
})
1078
1079
it('fails if condition returns a rejected promise', function () {
1080
let executor = new FakeExecutor()
1081
let driver = executor.createDriver()
1082
1083
function condition() {
1084
return new Promise((_, reject) => reject(new StubError()))
1085
}
1086
1087
return driver.wait(condition, 0, 'goes boom').then(fail, assertIsStubError)
1088
})
1089
1090
it('supports message function if condition exceeds timeout', function () {
1091
let executor = new FakeExecutor()
1092
let driver = executor.createDriver()
1093
let message = () => 'goes boom'
1094
return driver
1095
.wait(() => false, 0.001, message)
1096
.then(fail, (e) => {
1097
assert.ok(/^goes boom\nWait timed out after \d+ms$/.test(e.message))
1098
})
1099
})
1100
1101
it('handles if the message function throws an error after a condition exceeds timeout', function () {
1102
let executor = new FakeExecutor()
1103
let driver = executor.createDriver()
1104
let message = () => {
1105
throw new Error('message function error')
1106
}
1107
return driver
1108
.wait(() => false, 0.001, message)
1109
.then(fail, (e) => {
1110
assert.ok(/^message function error\nWait timed out after \d+ms$/.test(e.message))
1111
})
1112
})
1113
1114
it('supports message function if condition returns a rejected promise', function () {
1115
let executor = new FakeExecutor()
1116
let driver = executor.createDriver()
1117
let condition = new Promise((res) => setTimeout(res, 100))
1118
let message = () => 'goes boom'
1119
return driver.wait(condition, 1, message).then(fail, (e) => {
1120
assert.ok(/^goes boom\nTimed out waiting for promise to resolve after \d+ms$/.test(e.message))
1121
})
1122
})
1123
1124
it('handles if the message function returns an error after a rejected promise', function () {
1125
let executor = new FakeExecutor()
1126
let driver = executor.createDriver()
1127
let condition = new Promise((res) => setTimeout(res, 100))
1128
let message = () => {
1129
throw new Error('message function error')
1130
}
1131
return driver.wait(condition, 1, message).then(fail, (e) => {
1132
assert.ok(/^message function error\nTimed out waiting for promise to resolve after \d+ms$/.test(e.message))
1133
})
1134
})
1135
1136
it('waits forever on a zero timeout', function () {
1137
let done = false
1138
setTimeout(() => (done = true), 150)
1139
1140
let executor = new FakeExecutor()
1141
let driver = executor.createDriver()
1142
let waitResult = driver.wait(() => done, 0)
1143
1144
return driver
1145
.sleep(75)
1146
.then(function () {
1147
assert.ok(!done)
1148
return driver.sleep(100)
1149
})
1150
.then(function () {
1151
assert.ok(done)
1152
return waitResult
1153
})
1154
})
1155
1156
it('waits forever if timeout omitted', function () {
1157
let done = false
1158
setTimeout(() => (done = true), 150)
1159
1160
let executor = new FakeExecutor()
1161
let driver = executor.createDriver()
1162
let waitResult = driver.wait(() => done)
1163
1164
return driver
1165
.sleep(75)
1166
.then(function () {
1167
assert.ok(!done)
1168
return driver.sleep(100)
1169
})
1170
.then(function () {
1171
assert.ok(done)
1172
return waitResult
1173
})
1174
})
1175
1176
it('times out when timer expires', function () {
1177
let executor = new FakeExecutor()
1178
let driver = executor.createDriver()
1179
1180
let count = 0
1181
let wait = driver.wait(
1182
function () {
1183
count += 1
1184
let ms = count === 2 ? 65 : 5
1185
return promise.delayed(ms).then(function () {
1186
return false
1187
})
1188
},
1189
60,
1190
'counting to 3',
1191
)
1192
1193
return wait.then(fail, function (e) {
1194
assert.strictEqual(2, count)
1195
assert.ok(e instanceof error.TimeoutError, 'Unexpected error: ' + e)
1196
assert.ok(/^counting to 3\nWait timed out after \d+ms$/.test(e.message))
1197
})
1198
})
1199
1200
it('requires condition to be a promise or function', function () {
1201
let executor = new FakeExecutor()
1202
let driver = executor.createDriver()
1203
assert.throws(() => driver.wait(1234, 0))
1204
})
1205
1206
it('promise that does not resolve before timeout', function () {
1207
let d = defer()
1208
1209
let executor = new FakeExecutor()
1210
let driver = executor.createDriver()
1211
return driver.wait(d.promise, 5).then(fail, (e) => {
1212
assert.ok(e instanceof error.TimeoutError, 'Unexpected error: ' + e)
1213
assert.ok(
1214
/Timed out waiting for promise to resolve after \d+ms/.test(e.message),
1215
'unexpected error message: ' + e.message,
1216
)
1217
})
1218
})
1219
1220
it('unbounded wait on promise resolution', function () {
1221
let messages = []
1222
let d = defer()
1223
1224
let executor = new FakeExecutor()
1225
let driver = executor.createDriver()
1226
let waitResult = driver.wait(d.promise).then(function (value) {
1227
messages.push('b')
1228
assert.strictEqual(1234, value)
1229
})
1230
1231
setTimeout(() => messages.push('a'), 5)
1232
return driver
1233
.sleep(10)
1234
.then(function () {
1235
assert.deepStrictEqual(['a'], messages)
1236
d.resolve(1234)
1237
return waitResult
1238
})
1239
.then(function () {
1240
assert.deepStrictEqual(['a', 'b'], messages)
1241
})
1242
})
1243
1244
describe('supports custom wait functions', function () {
1245
it('waitSucceeds', function () {
1246
let executor = new FakeExecutor()
1247
.expect(CName.FIND_ELEMENTS, {
1248
using: 'css selector',
1249
value: '*[id="foo"]',
1250
})
1251
.andReturnSuccess([])
1252
.times(2)
1253
.expect(CName.FIND_ELEMENTS, {
1254
using: 'css selector',
1255
value: '*[id="foo"]',
1256
})
1257
.andReturnSuccess([WebElement.buildId('bar')])
1258
.end()
1259
1260
const driver = executor.createDriver()
1261
return driver.wait(
1262
function () {
1263
return driver.findElements(By.id('foo')).then((els) => els.length > 0)
1264
},
1265
200,
1266
null,
1267
25,
1268
)
1269
})
1270
1271
it('waitTimesout_timeoutCaught', function () {
1272
let executor = new FakeExecutor()
1273
.expect(CName.FIND_ELEMENTS, {
1274
using: 'css selector',
1275
value: '*[id="foo"]',
1276
})
1277
.andReturnSuccess([])
1278
.anyTimes()
1279
.end()
1280
1281
const driver = executor.createDriver()
1282
return driver
1283
.wait(function () {
1284
return driver.findElements(By.id('foo')).then((els) => els.length > 0)
1285
}, 25)
1286
.then(fail, function (e) {
1287
assert.strictEqual('Wait timed out after ', e.message.substring(0, 'Wait timed out after '.length))
1288
})
1289
})
1290
})
1291
1292
describe('supports condition objects', function () {
1293
it('wait succeeds', function () {
1294
let executor = new FakeExecutor()
1295
.expect(CName.FIND_ELEMENTS, {
1296
using: 'css selector',
1297
value: '*[id="foo"]',
1298
})
1299
.andReturnSuccess([])
1300
.times(2)
1301
.expect(CName.FIND_ELEMENTS, {
1302
using: 'css selector',
1303
value: '*[id="foo"]',
1304
})
1305
.andReturnSuccess([WebElement.buildId('bar')])
1306
.end()
1307
1308
let driver = executor.createDriver()
1309
return driver.wait(until.elementLocated(By.id('foo')), 200, null, 25)
1310
})
1311
1312
it('wait times out', function () {
1313
let executor = new FakeExecutor()
1314
.expect(CName.FIND_ELEMENTS, {
1315
using: 'css selector',
1316
value: '*[id="foo"]',
1317
})
1318
.andReturnSuccess([])
1319
.anyTimes()
1320
.end()
1321
1322
let driver = executor.createDriver()
1323
return driver
1324
.wait(until.elementLocated(By.id('foo')), 5)
1325
.then(fail, (err) => assert.ok(err instanceof error.TimeoutError))
1326
})
1327
})
1328
1329
describe('supports promise objects', function () {
1330
it('wait succeeds', function () {
1331
let promise = new Promise((resolve) => {
1332
setTimeout(() => resolve(1), 10)
1333
})
1334
1335
let driver = new FakeExecutor().createDriver()
1336
return driver.wait(promise, 200).then((v) => assert.strictEqual(v, 1))
1337
})
1338
1339
it('wait times out', function () {
1340
let promise = new Promise(() => {
1341
/* never resolves */
1342
})
1343
1344
let driver = new FakeExecutor().createDriver()
1345
return driver.wait(promise, 5).then(fail, (err) => assert.ok(err instanceof error.TimeoutError))
1346
})
1347
1348
it('wait fails if promise is rejected', function () {
1349
let err = Error('boom')
1350
let driver = new FakeExecutor().createDriver()
1351
return driver.wait(Promise.reject(err), 5).then(fail, (e) => assert.strictEqual(e, err))
1352
})
1353
})
1354
1355
it('fails if not supported condition type provided', function () {
1356
let driver = new FakeExecutor().createDriver()
1357
assert.throws(() => driver.wait({}, 5), TypeError)
1358
})
1359
})
1360
1361
describe('alert handling', function () {
1362
it('alertResolvesWhenPromisedTextResolves', function () {
1363
let driver = new FakeExecutor().createDriver()
1364
let deferredText = defer()
1365
1366
let alert = new AlertPromise(driver, deferredText.promise)
1367
1368
deferredText.resolve(new Alert(driver, 'foo'))
1369
return alert.getText().then((text) => assert.strictEqual(text, 'foo'))
1370
})
1371
1372
it('cannotSwitchToAlertThatIsNotPresent', function () {
1373
let e = new error.NoSuchAlertError()
1374
let executor = new FakeExecutor().expect(CName.GET_ALERT_TEXT).andReturnError(e).end()
1375
1376
return executor
1377
.createDriver()
1378
.switchTo()
1379
.alert()
1380
.then(assert.fail, (v) => assert.strictEqual(v, e))
1381
})
1382
1383
it('commandsFailIfAlertNotPresent', function () {
1384
let e = new error.NoSuchAlertError()
1385
let executor = new FakeExecutor().expect(CName.GET_ALERT_TEXT).andReturnError(e).end()
1386
1387
const driver = executor.createDriver()
1388
const alert = driver.switchTo().alert()
1389
1390
const expectError = (v) => assert.strictEqual(v, e)
1391
1392
return alert
1393
.getText()
1394
.then(fail, expectedError)
1395
.then(() => alert.accept())
1396
.then(fail, expectedError)
1397
.then(() => alert.dismiss())
1398
.then(fail, expectError)
1399
.then(() => alert.sendKeys('hi'))
1400
.then(fail, expectError)
1401
})
1402
})
1403
1404
it('testFetchingLogs', function () {
1405
let executor = new FakeExecutor()
1406
.expect(CName.GET_LOG, { type: 'browser' })
1407
.andReturnSuccess([
1408
{ level: 'INFO', message: 'hello', timestamp: 1234 },
1409
{ level: 'DEBUG', message: 'abc123', timestamp: 5678 },
1410
])
1411
.end()
1412
1413
const driver = executor.createDriver()
1414
return driver
1415
.manage()
1416
.logs()
1417
.get('browser')
1418
.then(function (entries) {
1419
assert.strictEqual(2, entries.length)
1420
1421
assert.ok(entries[0] instanceof logging.Entry)
1422
assert.strictEqual(logging.Level.INFO.value, entries[0].level.value)
1423
assert.strictEqual('hello', entries[0].message)
1424
assert.strictEqual(1234, entries[0].timestamp)
1425
1426
assert.ok(entries[1] instanceof logging.Entry)
1427
assert.strictEqual(logging.Level.DEBUG.value, entries[1].level.value)
1428
assert.strictEqual('abc123', entries[1].message)
1429
assert.strictEqual(5678, entries[1].timestamp)
1430
})
1431
})
1432
1433
it('testCommandsFailIfInitialSessionCreationFailed', function () {
1434
const session = Promise.reject(new StubError())
1435
1436
const driver = new FakeExecutor().createDriver(session)
1437
const navigateResult = driver.get('some-url').then(fail, assertIsStubError)
1438
const quitResult = driver.quit().then(fail, assertIsStubError)
1439
return Promise.all([navigateResult, quitResult])
1440
})
1441
1442
it('testWebElementCommandsFailIfInitialDriverCreationFailed', function () {
1443
const session = Promise.reject(new StubError())
1444
const driver = new FakeExecutor().createDriver(session)
1445
return driver.findElement(By.id('foo')).click().then(fail, assertIsStubError)
1446
})
1447
1448
it('testWebElementCommansFailIfElementCouldNotBeFound', function () {
1449
let e = new error.NoSuchElementError('Unable to find element')
1450
let executor = new FakeExecutor()
1451
.expect(CName.FIND_ELEMENT, {
1452
using: 'css selector',
1453
value: '*[id="foo"]',
1454
})
1455
.andReturnError(e)
1456
.end()
1457
1458
const driver = executor.createDriver()
1459
return driver
1460
.findElement(By.id('foo'))
1461
.click()
1462
.then(fail, (v) => assert.strictEqual(v, e))
1463
})
1464
1465
it('testCannotFindChildElementsIfParentCouldNotBeFound', function () {
1466
let e = new error.NoSuchElementError('Unable to find element')
1467
let executor = new FakeExecutor()
1468
.expect(CName.FIND_ELEMENT, {
1469
using: 'css selector',
1470
value: '*[id="foo"]',
1471
})
1472
.andReturnError(e)
1473
.end()
1474
1475
const driver = executor.createDriver()
1476
return driver
1477
.findElement(By.id('foo'))
1478
.findElement(By.id('bar'))
1479
.findElement(By.id('baz'))
1480
.then(fail, (v) => assert.strictEqual(v, e))
1481
})
1482
1483
describe('actions()', function () {
1484
describe('move()', function () {
1485
it('no origin', function () {
1486
let executor = new FakeExecutor()
1487
.expect(CName.ACTIONS, {
1488
actions: [
1489
{
1490
type: 'pointer',
1491
id: 'default mouse',
1492
parameters: {
1493
pointerType: 'mouse',
1494
},
1495
actions: [
1496
{
1497
duration: 100,
1498
origin: 'viewport',
1499
type: 'pointerMove',
1500
x: 0,
1501
y: 125,
1502
altitudeAngle: 0,
1503
azimuthAngle: 0,
1504
width: 0,
1505
height: 0,
1506
pressure: 0,
1507
tangentialPressure: 0,
1508
tiltX: 0,
1509
tiltY: 0,
1510
twist: 0,
1511
},
1512
],
1513
},
1514
],
1515
})
1516
.andReturnSuccess()
1517
.end()
1518
1519
let driver = executor.createDriver()
1520
return driver.actions().move({ x: 0, y: 125 }).perform()
1521
})
1522
1523
it('origin = element', function () {
1524
let executor = new FakeExecutor()
1525
.expect(CName.FIND_ELEMENT, {
1526
using: 'css selector',
1527
value: '*[id="foo"]',
1528
})
1529
.andReturnSuccess(WebElement.buildId('abc123'))
1530
.expect(CName.ACTIONS, {
1531
actions: [
1532
{
1533
type: 'pointer',
1534
id: 'default mouse',
1535
parameters: {
1536
pointerType: 'mouse',
1537
},
1538
actions: [
1539
{
1540
duration: 100,
1541
origin: WebElement.buildId('abc123'),
1542
type: 'pointerMove',
1543
x: 0,
1544
y: 125,
1545
altitudeAngle: 0,
1546
azimuthAngle: 0,
1547
width: 0,
1548
height: 0,
1549
pressure: 0,
1550
tangentialPressure: 0,
1551
tiltX: 0,
1552
tiltY: 0,
1553
twist: 0,
1554
},
1555
],
1556
},
1557
],
1558
})
1559
.end()
1560
1561
let driver = executor.createDriver()
1562
let element = driver.findElement(By.id('foo'))
1563
return driver.actions().move({ x: 0, y: 125, origin: element }).perform()
1564
})
1565
})
1566
})
1567
1568
describe('manage()', function () {
1569
describe('setTimeouts()', function () {
1570
describe('throws if no timeouts are specified', function () {
1571
let driver
1572
before(() => (driver = new FakeExecutor().createDriver()))
1573
1574
it('; no arguments', function () {
1575
assert.throws(() => driver.manage().setTimeouts(), TypeError)
1576
})
1577
1578
it('; ignores unrecognized timeout keys', function () {
1579
assert.throws(() => driver.manage().setTimeouts({ foo: 123 }), TypeError)
1580
})
1581
1582
it('; ignores positional arguments', function () {
1583
assert.throws(() => driver.manage().setTimeouts(1234, 56), TypeError)
1584
})
1585
})
1586
1587
describe('throws timeout is not a number, null, or undefined', () => {
1588
let driver
1589
before(() => (driver = new FakeExecutor().createDriver()))
1590
1591
function checkError(e) {
1592
return e instanceof TypeError && /expected "(script|pageLoad|implicit)" to be a number/.test(e.message)
1593
}
1594
1595
it('script', function () {
1596
assert.throws(() => driver.manage().setTimeouts({ script: 'abc' }), checkError)
1597
})
1598
1599
it('pageLoad', function () {
1600
assert.throws(() => driver.manage().setTimeouts({ pageLoad: 'abc' }), checkError)
1601
})
1602
1603
it('implicit', function () {
1604
assert.throws(() => driver.manage().setTimeouts({ implicit: 'abc' }), checkError)
1605
})
1606
})
1607
1608
it('can set multiple timeouts', function () {
1609
let executor = new FakeExecutor()
1610
.expect(CName.SET_TIMEOUT, { script: 1, pageLoad: 2, implicit: 3 })
1611
.andReturnSuccess()
1612
.end()
1613
let driver = executor.createDriver()
1614
return driver.manage().setTimeouts({ script: 1, pageLoad: 2, implicit: 3 })
1615
})
1616
1617
it('falls back to legacy wire format if W3C version fails', () => {
1618
let executor = new FakeExecutor()
1619
.expect(CName.SET_TIMEOUT, { implicit: 3 })
1620
.andReturnError(Error('oops'))
1621
.expect(CName.SET_TIMEOUT, { type: 'implicit', ms: 3 })
1622
.andReturnSuccess()
1623
.end()
1624
let driver = executor.createDriver()
1625
return driver.manage().setTimeouts({ implicit: 3 })
1626
})
1627
})
1628
})
1629
})
1630
1631