Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/javascript/selenium-webdriver/test/lib/promise_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 assert = require('node:assert')
21
22
const testutil = require('./testutil')
23
const promise = require('selenium-webdriver/lib/promise')
24
25
// Aliases for readability.
26
const NativePromise = Promise
27
const StubError = testutil.StubError
28
const assertIsStubError = testutil.assertIsStubError
29
const callbackPair = testutil.callbackPair
30
const throwStubError = testutil.throwStubError
31
const fail = () => assert.fail()
32
33
// Refer to promise_aplus_test for promise compliance with standard behavior.
34
describe('promise', function () {
35
let app, uncaughtExceptions
36
37
beforeEach(function setUp() {
38
if (promise.USE_PROMISE_MANAGER) {
39
promise.LONG_STACK_TRACES = false
40
uncaughtExceptions = []
41
42
app = promise.controlFlow()
43
app.on(promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION, (e) => uncaughtExceptions.push(e))
44
}
45
})
46
47
afterEach(function tearDown() {
48
if (promise.USE_PROMISE_MANAGER) {
49
app.reset()
50
promise.setDefaultFlow(new promise.ControlFlow())
51
assert.deepStrictEqual([], uncaughtExceptions, 'Did not expect any uncaught exceptions')
52
promise.LONG_STACK_TRACES = false
53
}
54
})
55
56
it('isPromise', () => {
57
const v = () => {}
58
const x = new Promise(v, v)
59
const p = createRejectedPromise('reject')
60
const q = Promise.resolve('resolved')
61
const t = {
62
then() {},
63
}
64
const f = () => {}
65
f.then = () => {}
66
assert.equal(true, promise.isPromise(x))
67
assert.equal(true, promise.isPromise(p))
68
assert.equal(true, promise.isPromise(q))
69
assert.equal(true, promise.isPromise(t))
70
assert.equal(true, promise.isPromise(f))
71
assert.equal(false, promise.isPromise(0))
72
assert.equal(false, promise.isPromise(false))
73
assert.equal(false, promise.isPromise(true))
74
assert.equal(false, promise.isPromise(null))
75
assert.equal(false, promise.isPromise(undefined))
76
assert.equal(false, promise.isPromise(''))
77
assert.equal(false, promise.isPromise('promise'))
78
assert.equal(false, promise.isPromise(v))
79
})
80
81
function defer() {
82
let d = {}
83
let promise = new Promise((resolve, reject) => {
84
Object.assign(d, { resolve, reject })
85
})
86
d.promise = promise
87
return d
88
}
89
90
function createRejectedPromise(reason) {
91
var p = Promise.reject(reason)
92
p.catch(function () {}) // Silence unhandled rejection handlers.
93
return p
94
}
95
96
describe('fullyResolved', function () {
97
it('primitives', function () {
98
function runTest(value) {
99
return promise.fullyResolved(value).then((resolved) => assert.strictEqual(value, resolved))
100
}
101
102
return runTest(true)
103
.then(() => runTest(function () {}))
104
.then(() => runTest(null))
105
.then(() => runTest(123))
106
.then(() => runTest('foo bar'))
107
.then(() => runTest(undefined))
108
})
109
110
it('arrayOfPrimitives', function () {
111
var fn = function () {}
112
const array = [true, fn, null, 123, '', undefined, 1]
113
return promise.fullyResolved(array).then(function (resolved) {
114
assert.strictEqual(array, resolved)
115
assert.deepStrictEqual([true, fn, null, 123, '', undefined, 1], resolved)
116
})
117
})
118
119
it('nestedArrayOfPrimitives', function () {
120
var fn = function () {}
121
const array = [true, [fn, null, 123], '', undefined]
122
return promise.fullyResolved(array).then(function (resolved) {
123
assert.strictEqual(array, resolved)
124
assert.deepStrictEqual([true, [fn, null, 123], '', undefined], resolved)
125
assert.deepStrictEqual([fn, null, 123], resolved[1])
126
})
127
})
128
129
it('arrayWithPromisedPrimitive', function () {
130
return promise.fullyResolved([Promise.resolve(123)]).then(function (resolved) {
131
assert.deepStrictEqual([123], resolved)
132
})
133
})
134
135
it('promiseResolvesToPrimitive', function () {
136
return promise.fullyResolved(Promise.resolve(123)).then((resolved) => assert.strictEqual(123, resolved))
137
})
138
139
it('promiseResolvesToArray', function () {
140
var fn = function () {}
141
const array = [true, [fn, null, 123], '', undefined]
142
const aPromise = Promise.resolve(array)
143
144
var result = promise.fullyResolved(aPromise)
145
return result.then(function (resolved) {
146
assert.strictEqual(array, resolved)
147
assert.deepStrictEqual([true, [fn, null, 123], '', undefined], resolved)
148
assert.deepStrictEqual([fn, null, 123], resolved[1])
149
})
150
})
151
152
it('promiseResolvesToArrayWithPromises', function () {
153
var nestedPromise = Promise.resolve(123)
154
const aPromise = Promise.resolve([true, nestedPromise])
155
return promise.fullyResolved(aPromise).then(function (resolved) {
156
assert.deepStrictEqual([true, 123], resolved)
157
})
158
})
159
160
it('rejectsIfArrayPromiseRejects', function () {
161
var nestedPromise = createRejectedPromise(new StubError())
162
const aPromise = Promise.resolve([true, nestedPromise])
163
164
return promise.fullyResolved(aPromise).then(assert.fail, assertIsStubError)
165
})
166
167
it('rejectsOnFirstArrayRejection', function () {
168
var e1 = new Error('foo')
169
var e2 = new Error('bar')
170
const aPromise = Promise.resolve([createRejectedPromise(e1), createRejectedPromise(e2)])
171
172
return promise.fullyResolved(aPromise).then(assert.fail, function (error) {
173
assert.strictEqual(e1, error)
174
})
175
})
176
177
it('rejectsIfNestedArrayPromiseRejects', function () {
178
const aPromise = Promise.resolve([Promise.resolve([createRejectedPromise(new StubError())])])
179
180
return promise.fullyResolved(aPromise).then(assert.fail, assertIsStubError)
181
})
182
183
it('simpleHash', function () {
184
var hash = { a: 123 }
185
return promise.fullyResolved(hash).then(function (resolved) {
186
assert.strictEqual(hash, resolved)
187
assert.deepStrictEqual(hash, { a: 123 })
188
})
189
})
190
191
it('nestedHash', function () {
192
var nestedHash = { foo: 'bar' }
193
var hash = { a: 123, b: nestedHash }
194
195
return promise.fullyResolved(hash).then(function (resolved) {
196
assert.strictEqual(hash, resolved)
197
assert.deepStrictEqual({ a: 123, b: { foo: 'bar' } }, resolved)
198
assert.strictEqual(nestedHash, resolved['b'])
199
})
200
})
201
202
it('promiseResolvesToSimpleHash', function () {
203
var hash = { a: 123 }
204
const aPromise = Promise.resolve(hash)
205
206
return promise.fullyResolved(aPromise).then((resolved) => assert.strictEqual(hash, resolved))
207
})
208
209
it('promiseResolvesToNestedHash', function () {
210
var nestedHash = { foo: 'bar' }
211
var hash = { a: 123, b: nestedHash }
212
const aPromise = Promise.resolve(hash)
213
214
return promise.fullyResolved(aPromise).then(function (resolved) {
215
assert.strictEqual(hash, resolved)
216
assert.strictEqual(nestedHash, resolved['b'])
217
assert.deepStrictEqual(hash, { a: 123, b: { foo: 'bar' } })
218
})
219
})
220
221
it('promiseResolvesToHashWithPromises', function () {
222
const aPromise = Promise.resolve({
223
a: Promise.resolve(123),
224
})
225
226
return promise.fullyResolved(aPromise).then(function (resolved) {
227
assert.deepStrictEqual({ a: 123 }, resolved)
228
})
229
})
230
231
it('rejectsIfHashPromiseRejects', function () {
232
const aPromise = Promise.resolve({
233
a: createRejectedPromise(new StubError()),
234
})
235
236
return promise.fullyResolved(aPromise).then(assert.fail, assertIsStubError)
237
})
238
239
it('rejectsIfNestedHashPromiseRejects', function () {
240
const aPromise = Promise.resolve({
241
a: { b: createRejectedPromise(new StubError()) },
242
})
243
244
return promise.fullyResolved(aPromise).then(assert.fail, assertIsStubError)
245
})
246
247
it('instantiatedObject', function () {
248
function Foo() {
249
this.bar = 'baz'
250
}
251
252
var foo = new Foo()
253
254
return promise.fullyResolved(foo).then(function (resolvedFoo) {
255
assert.strictEqual(foo, resolvedFoo)
256
assert.ok(resolvedFoo instanceof Foo)
257
assert.deepStrictEqual(new Foo(), resolvedFoo)
258
})
259
})
260
261
it('withEmptyArray', function () {
262
return promise.fullyResolved([]).then(function (resolved) {
263
assert.deepStrictEqual([], resolved)
264
})
265
})
266
267
it('withEmptyHash', function () {
268
return promise.fullyResolved({}).then(function (resolved) {
269
assert.deepStrictEqual({}, resolved)
270
})
271
})
272
273
it('arrayWithPromisedHash', function () {
274
var obj = { foo: 'bar' }
275
const array = [Promise.resolve(obj)]
276
277
return promise.fullyResolved(array).then(function (resolved) {
278
assert.deepStrictEqual(resolved, [obj])
279
})
280
})
281
})
282
283
describe('finally', function () {
284
it('successful callback does not suppress original error', async () => {
285
let p = Promise.reject(new StubError())
286
let called = false
287
288
try {
289
await promise.finally(p, function () {
290
called = true
291
})
292
fail('should have thrown')
293
} catch (e) {
294
assertIsStubError(e)
295
assert.ok(called)
296
}
297
})
298
299
it('failing callback suppresses original error', async () => {
300
let p = Promise.reject(Error('original'))
301
302
try {
303
await promise.finally(p, throwStubError)
304
fail('should have thrown')
305
} catch (e) {
306
assertIsStubError(e)
307
}
308
})
309
310
it('callback throws after fulfilled promise', async () => {
311
try {
312
await promise.finally(Promise.resolve(), throwStubError)
313
fail('should have thrown')
314
} catch (e) {
315
assertIsStubError(e)
316
}
317
})
318
319
it('callback returns rejected promise', async () => {
320
try {
321
await promise.finally(Promise.resolve(), () => Promise.reject(new StubError()))
322
fail('should have thrown')
323
} catch (e) {
324
assertIsStubError(e)
325
}
326
})
327
328
it('returned promise resolves with callback result', async () => {
329
let value = await promise.finally(Promise.resolve(1), () => 2)
330
assert.strictEqual(value, 2)
331
})
332
})
333
334
describe('checkedNodeCall', function () {
335
it('functionThrows', function () {
336
return promise.checkedNodeCall(throwStubError).then(assert.fail, assertIsStubError)
337
})
338
339
it('functionReturnsAnError', function () {
340
return promise
341
.checkedNodeCall(function (callback) {
342
callback(new StubError())
343
})
344
.then(assert.fail, assertIsStubError)
345
})
346
347
it('functionReturnsSuccess', function () {
348
var success = 'success!'
349
return promise
350
.checkedNodeCall(function (callback) {
351
callback(null, success)
352
})
353
.then((value) => assert.strictEqual(success, value))
354
})
355
356
it('functionReturnsAndThrows', function () {
357
var error = new Error('boom')
358
var error2 = new Error('boom again')
359
return promise
360
.checkedNodeCall(function (callback) {
361
callback(error)
362
throw error2
363
})
364
.then(assert.fail, (e) => assert.strictEqual(error, e))
365
})
366
367
it('functionThrowsAndReturns', function () {
368
var error = new Error('boom')
369
var error2 = new Error('boom again')
370
return promise
371
.checkedNodeCall(function (callback) {
372
setTimeout(() => callback(error), 10)
373
throw error2
374
})
375
.then(assert.fail, (e) => assert.strictEqual(error2, e))
376
})
377
})
378
379
describe('map', function () {
380
it('(base case)', function () {
381
const a = [1, 2, 3]
382
return promise
383
.map(a, function (value, index, a2) {
384
assert.strictEqual(a, a2)
385
assert.strictEqual('number', typeof index, 'not a number')
386
return value + 1
387
})
388
.then(function (value) {
389
assert.deepStrictEqual([2, 3, 4], value)
390
})
391
})
392
393
it('omitsDeleted', function () {
394
const a = [0, 1, 2, 3, 4, 5, 6]
395
delete a[1]
396
delete a[3]
397
delete a[4]
398
delete a[6]
399
400
const expected = [0, NaN, 4, NaN, NaN, 25, NaN]
401
402
return promise
403
.map(a, function (value) {
404
return value * value
405
})
406
.then(function (value) {
407
assert.deepStrictEqual(expected, value)
408
})
409
})
410
411
it('emptyArray', function () {
412
return promise
413
.map([], function (value) {
414
return value + 1
415
})
416
.then(function (value) {
417
assert.deepStrictEqual([], value)
418
})
419
})
420
421
it('inputIsPromise', function () {
422
var input = defer()
423
var result = promise.map(input.promise, function (value) {
424
return value + 1
425
})
426
427
var pair = callbackPair(function (value) {
428
assert.deepStrictEqual([2, 3, 4], value)
429
})
430
result = result.then(pair.callback, pair.errback)
431
432
setTimeout(function () {
433
pair.assertNeither()
434
input.resolve([1, 2, 3])
435
}, 10)
436
437
return result
438
})
439
440
it('waitsForFunctionResultToResolve', function () {
441
var innerResults = [defer(), defer()]
442
443
var result = promise.map([1, 2], function (_value, index) {
444
return innerResults[index].promise
445
})
446
447
var pair = callbackPair(function (value) {
448
assert.deepStrictEqual(['a', 'b'], value)
449
})
450
result = result.then(pair.callback, pair.errback)
451
452
return NativePromise.resolve()
453
.then(function () {
454
pair.assertNeither()
455
innerResults[0].resolve('a')
456
})
457
.then(function () {
458
pair.assertNeither()
459
innerResults[1].resolve('b')
460
return result
461
})
462
.then(pair.assertCallback)
463
})
464
465
it('rejectsPromiseIfFunctionThrows', function () {
466
return promise.map([1], throwStubError).then(assert.fail, assertIsStubError)
467
})
468
469
it('rejectsPromiseIfFunctionReturnsRejectedPromise', function () {
470
return promise
471
.map([1], function () {
472
return createRejectedPromise(new StubError())
473
})
474
.then(assert.fail, assertIsStubError)
475
})
476
477
it('stopsCallingFunctionIfPreviousIterationFailed', function () {
478
var count = 0
479
return promise
480
.map([1, 2, 3, 4], function () {
481
count++
482
if (count === 3) {
483
throw new StubError()
484
}
485
})
486
.then(assert.fail, function (e) {
487
assertIsStubError(e)
488
assert.strictEqual(3, count)
489
})
490
})
491
492
it('rejectsWithFirstRejectedPromise', function () {
493
var innerResult = [
494
Promise.resolve(),
495
createRejectedPromise(new StubError()),
496
createRejectedPromise(Error('should be ignored')),
497
]
498
var count = 0
499
return promise
500
.map([1, 2, 3, 4], function (_value, index) {
501
count += 1
502
return innerResult[index]
503
})
504
.then(assert.fail, function (e) {
505
assertIsStubError(e)
506
assert.strictEqual(2, count)
507
})
508
})
509
510
it('preservesOrderWhenMapReturnsPromise', function () {
511
var deferreds = [defer(), defer(), defer(), defer()]
512
var result = promise.map(deferreds, function (value) {
513
return value.promise
514
})
515
516
var pair = callbackPair(function (value) {
517
assert.deepStrictEqual([0, 1, 2, 3], value)
518
})
519
result = result.then(pair.callback, pair.errback)
520
521
return Promise.resolve()
522
.then(function () {
523
pair.assertNeither()
524
for (let i = deferreds.length; i > 0; i -= 1) {
525
deferreds[i - 1].resolve(i - 1)
526
}
527
return result
528
})
529
.then(pair.assertCallback)
530
})
531
})
532
533
describe('filter', function () {
534
it('basicFiltering', function () {
535
const a = [0, 1, 2, 3]
536
return promise
537
.filter(a, function (val, index, a2) {
538
assert.strictEqual(a, a2)
539
assert.strictEqual('number', typeof index, 'not a number')
540
return val > 1
541
})
542
.then(function (val) {
543
assert.deepStrictEqual([2, 3], val)
544
})
545
})
546
547
it('omitsDeleted', function () {
548
const a = [0, 1, 2, 3, 4, 5, 6]
549
delete a[3]
550
delete a[4]
551
552
return promise
553
.filter(a, function (value) {
554
return value > 1 && value < 6
555
})
556
.then(function (val) {
557
assert.deepStrictEqual([2, 5], val)
558
})
559
})
560
561
it('preservesInputs', function () {
562
const a = [0, 1, 2, 3]
563
564
return promise
565
.filter(a, function (_value, i, a2) {
566
assert.strictEqual(a, a2)
567
// Even if a function modifies the input array, the original value
568
// should be inserted into the new array.
569
a2[i] = a2[i] - 1
570
return a2[i] >= 1
571
})
572
.then(function (val) {
573
assert.deepStrictEqual([2, 3], val)
574
})
575
})
576
577
it('inputIsPromise', function () {
578
const input = defer()
579
let result = promise.filter(input.promise, function (value) {
580
return value > 1 && value < 3
581
})
582
583
const pair = callbackPair(function (value) {
584
assert.deepStrictEqual([2], value)
585
})
586
result = result.then(pair.callback, pair.errback)
587
return NativePromise.resolve()
588
.then(function () {
589
pair.assertNeither()
590
input.resolve([1, 2, 3])
591
return result
592
})
593
.then(pair.assertCallback)
594
})
595
596
it('waitsForFunctionResultToResolve', function () {
597
const innerResults = [defer(), defer()]
598
599
let result = promise.filter([1, 2], function (_value, index) {
600
return innerResults[index].promise
601
})
602
603
const pair = callbackPair(function (value) {
604
assert.deepStrictEqual([2], value)
605
})
606
result = result.then(pair.callback, pair.errback)
607
return NativePromise.resolve()
608
.then(function () {
609
pair.assertNeither()
610
innerResults[0].resolve(false)
611
})
612
.then(function () {
613
pair.assertNeither()
614
innerResults[1].resolve(true)
615
return result
616
})
617
.then(pair.assertCallback)
618
})
619
620
it('rejectsPromiseIfFunctionReturnsRejectedPromise', function () {
621
return promise
622
.filter([1], function () {
623
return createRejectedPromise(new StubError())
624
})
625
.then(assert.fail, assertIsStubError)
626
})
627
628
it('stopsCallingFunctionIfPreviousIterationFailed', function () {
629
var count = 0
630
return promise
631
.filter([1, 2, 3, 4], function () {
632
count++
633
if (count === 3) {
634
throw new StubError()
635
}
636
})
637
.then(assert.fail, function (e) {
638
assertIsStubError(e)
639
assert.strictEqual(3, count)
640
})
641
})
642
643
it('rejectsWithFirstRejectedPromise', function () {
644
var innerResult = [
645
Promise.resolve(),
646
createRejectedPromise(new StubError()),
647
createRejectedPromise(Error('should be ignored')),
648
]
649
650
return promise
651
.filter([1, 2, 3, 4], function (_value, index) {
652
assert.ok(index < innerResult.length)
653
return innerResult[index]
654
})
655
.then(assert.fail, assertIsStubError)
656
})
657
658
it('preservesOrderWhenFilterReturnsPromise', function () {
659
const deferreds = [defer(), defer(), defer(), defer()]
660
let result = promise.filter([0, 1, 2, 3], function (_value, index) {
661
return deferreds[index].promise
662
})
663
664
const pair = callbackPair(function (value) {
665
assert.deepStrictEqual([1, 2], value)
666
})
667
result = result.then(pair.callback, pair.errback)
668
669
return NativePromise.resolve()
670
.then(function () {
671
pair.assertNeither()
672
for (let i = deferreds.length - 1; i >= 0; i -= 1) {
673
deferreds[i].resolve(i > 0 && i < 3)
674
}
675
return result
676
})
677
.then(pair.assertCallback)
678
})
679
})
680
})
681
682