Skip to content

Commit 44aba52

Browse files
committed
Promise tests
1 parent 6d03787 commit 44aba52

14 files changed

+1026
-186
lines changed

tests/unit-global/es.promise.all-settled.js

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { createIterable } from '../helpers/helpers.js';
2+
13
QUnit.test('Promise.allSettled', assert => {
24
assert.isFunction(Promise.allSettled);
35
assert.arity(Promise.allSettled, 1);
@@ -7,6 +9,20 @@ QUnit.test('Promise.allSettled', assert => {
79
});
810

911
QUnit.test('Promise.allSettled, resolved', assert => {
12+
return Promise.allSettled([
13+
Promise.resolve(1),
14+
Promise.resolve(2),
15+
Promise.resolve(3),
16+
]).then(it => {
17+
assert.deepEqual(it, [
18+
{ value: 1, status: 'fulfilled' },
19+
{ value: 2, status: 'fulfilled' },
20+
{ value: 3, status: 'fulfilled' },
21+
], 'resolved with a correct value');
22+
});
23+
});
24+
25+
QUnit.test('Promise.allSettled, resolved with rejection', assert => {
1026
return Promise.allSettled([
1127
Promise.resolve(1),
1228
Promise.reject(2),
@@ -28,3 +44,87 @@ QUnit.test('Promise.allSettled, rejected', assert => {
2844
assert.required('rejected as expected');
2945
});
3046
});
47+
48+
QUnit.test('Promise.allSettled, resolved with timeouts', assert => {
49+
return Promise.allSettled([
50+
Promise.resolve(1),
51+
new Promise(resolve => setTimeout(() => resolve(2), 10)),
52+
Promise.resolve(3),
53+
]).then(it => {
54+
assert.deepEqual(it, [
55+
{ value: 1, status: 'fulfilled' },
56+
{ value: 2, status: 'fulfilled' },
57+
{ value: 3, status: 'fulfilled' },
58+
], 'keeps correct mapping, even with delays');
59+
});
60+
});
61+
62+
QUnit.test('Promise.allSettled, subclassing', assert => {
63+
const { allSettled, resolve } = Promise;
64+
function SubPromise(executor) {
65+
executor(() => { /* empty */ }, () => { /* empty */ });
66+
}
67+
SubPromise.resolve = resolve.bind(Promise);
68+
assert.true(allSettled.call(SubPromise, [1, 2, 3]) instanceof SubPromise, 'subclassing, `this` pattern');
69+
70+
function FakePromise1() { /* empty */ }
71+
function FakePromise2(executor) {
72+
executor(null, () => { /* empty */ });
73+
}
74+
function FakePromise3(executor) {
75+
executor(() => { /* empty */ }, null);
76+
}
77+
FakePromise1.resolve = FakePromise2.resolve = FakePromise3.resolve = resolve.bind(Promise);
78+
assert.throws(() => {
79+
allSettled.call(FakePromise1, [1, 2, 3]);
80+
}, 'NewPromiseCapability validations, #1');
81+
assert.throws(() => {
82+
allSettled.call(FakePromise2, [1, 2, 3]);
83+
}, 'NewPromiseCapability validations, #2');
84+
assert.throws(() => {
85+
allSettled.call(FakePromise3, [1, 2, 3]);
86+
}, 'NewPromiseCapability validations, #3');
87+
});
88+
89+
QUnit.test('Promise.allSettled, iterables', assert => {
90+
const iterable = createIterable([1, 2, 3]);
91+
Promise.allSettled(iterable).catch(() => { /* empty */ });
92+
assert.true(iterable.received, 'works with iterables: iterator received');
93+
assert.true(iterable.called, 'works with iterables: next called');
94+
});
95+
96+
QUnit.test('Promise.allSettled, iterables 2', assert => {
97+
const array = [];
98+
let done = false;
99+
// eslint-disable-next-line es/no-nonstandard-array-prototype-properties -- legacy FF case
100+
array['@@iterator'] = undefined;
101+
array[Symbol.iterator] = function () {
102+
done = true;
103+
return [][Symbol.iterator].call(this);
104+
};
105+
Promise.allSettled(array);
106+
assert.true(done);
107+
});
108+
109+
QUnit.test('Promise.allSettled, iterator closing', assert => {
110+
const { resolve } = Promise;
111+
let done = false;
112+
try {
113+
Promise.resolve = function () {
114+
throw new Error();
115+
};
116+
Promise.allSettled(createIterable([1, 2, 3], {
117+
return() {
118+
done = true;
119+
},
120+
})).catch(() => { /* empty */ });
121+
} catch { /* empty */ }
122+
Promise.resolve = resolve;
123+
assert.true(done, 'iteration closing');
124+
});
125+
126+
QUnit.test('Promise.allSettled, without constructor context', assert => {
127+
const { allSettled } = Promise;
128+
assert.throws(() => allSettled([]), TypeError, 'Throws if called without a constructor context');
129+
assert.throws(() => allSettled.call(null, []), TypeError, 'Throws if called with null as this');
130+
});
Lines changed: 84 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,88 @@
11
import { createIterable } from '../helpers/helpers.js';
22

33
QUnit.test('Promise.all', assert => {
4-
let FakePromise1, FakePromise2;
5-
const { all, resolve } = Promise;
4+
const { all } = Promise;
65
assert.isFunction(all);
76
assert.arity(all, 1);
87
assert.name(all, 'all');
98
assert.looksNative(all);
109
assert.nonEnumerable(Promise, 'all');
10+
assert.true(Promise.all([]) instanceof Promise, 'returns a promise');
11+
});
12+
13+
QUnit.test('Promise.all, resolved', assert => {
14+
return Promise.all([
15+
Promise.resolve(1),
16+
Promise.resolve(2),
17+
Promise.resolve(3),
18+
]).then(it => {
19+
assert.deepEqual(it, [1, 2, 3], 'resolved with a correct value');
20+
});
21+
});
22+
23+
QUnit.test('Promise.all, resolved with rejection', assert => {
24+
return Promise.all([
25+
Promise.resolve(1),
26+
Promise.reject(2),
27+
Promise.resolve(3),
28+
]).then(() => {
29+
assert.avoid();
30+
}, error => {
31+
assert.same(error, 2, 'rejected with a correct value');
32+
});
33+
});
34+
35+
QUnit.test('Promise.all, resolved with empty array', assert => {
36+
return Promise.all([]).then(it => {
37+
assert.deepEqual(it, [], 'resolved with a correct value');
38+
});
39+
});
40+
41+
QUnit.test('Promise.all, resolved with timeouts', assert => {
42+
return Promise.all([
43+
Promise.resolve(1),
44+
new Promise(resolve => setTimeout(() => resolve(2), 10)),
45+
Promise.resolve(3),
46+
]).then(it => {
47+
assert.deepEqual(it, [1, 2, 3], 'keeps correct mapping, even with delays');
48+
});
49+
});
50+
51+
QUnit.test('Promise.all, subclassing', assert => {
52+
const { all, resolve } = Promise;
53+
function SubPromise(executor) {
54+
executor(() => { /* empty */ }, () => { /* empty */ });
55+
}
56+
SubPromise.resolve = resolve.bind(Promise);
57+
assert.true(all.call(SubPromise, [1, 2, 3]) instanceof SubPromise, 'subclassing, `this` pattern');
58+
59+
function FakePromise1() { /* empty */ }
60+
function FakePromise2(executor) {
61+
executor(null, () => { /* empty */ });
62+
}
63+
function FakePromise3(executor) {
64+
executor(() => { /* empty */ }, null);
65+
}
66+
FakePromise1.resolve = FakePromise2.resolve = FakePromise3.resolve = resolve.bind(Promise);
67+
assert.throws(() => {
68+
all.call(FakePromise1, [1, 2, 3]);
69+
}, 'NewPromiseCapability validations, #1');
70+
assert.throws(() => {
71+
all.call(FakePromise2, [1, 2, 3]);
72+
}, 'NewPromiseCapability validations, #2');
73+
assert.throws(() => {
74+
all.call(FakePromise3, [1, 2, 3]);
75+
}, 'NewPromiseCapability validations, #3');
76+
});
77+
78+
QUnit.test('Promise.all, iterables', assert => {
1179
const iterable = createIterable([1, 2, 3]);
1280
Promise.all(iterable).catch(() => { /* empty */ });
1381
assert.true(iterable.received, 'works with iterables: iterator received');
1482
assert.true(iterable.called, 'works with iterables: next called');
83+
});
84+
85+
QUnit.test('Promise.all, iterables 2', assert => {
1586
const array = [];
1687
let done = false;
1788
// eslint-disable-next-line es/no-nonstandard-array-prototype-properties -- legacy FF case
@@ -22,10 +93,11 @@ QUnit.test('Promise.all', assert => {
2293
};
2394
Promise.all(array);
2495
assert.true(done);
25-
assert.throws(() => {
26-
all.call(null, []).catch(() => { /* empty */ });
27-
}, TypeError, 'throws without context');
28-
done = false;
96+
});
97+
98+
QUnit.test('Promise.all, iterator closing', assert => {
99+
const { resolve } = Promise;
100+
let done = false;
29101
try {
30102
Promise.resolve = function () {
31103
throw new Error();
@@ -38,29 +110,10 @@ QUnit.test('Promise.all', assert => {
38110
} catch { /* empty */ }
39111
Promise.resolve = resolve;
40112
assert.true(done, 'iteration closing');
41-
FakePromise1 = function (executor) {
42-
executor(() => { /* empty */ }, () => { /* empty */ });
43-
};
44-
FakePromise2 = FakePromise1[Symbol.species] = function (executor) {
45-
executor(() => { /* empty */ }, () => { /* empty */ });
46-
};
47-
FakePromise1.resolve = FakePromise2.resolve = resolve.bind(Promise);
48-
assert.true(all.call(FakePromise1, [1, 2, 3]) instanceof FakePromise1, 'subclassing, `this` pattern');
49-
FakePromise1 = function () { /* empty */ };
50-
FakePromise2 = function (executor) {
51-
executor(null, () => { /* empty */ });
52-
};
53-
const FakePromise3 = function (executor) {
54-
executor(() => { /* empty */ }, null);
55-
};
56-
FakePromise1.resolve = FakePromise2.resolve = FakePromise3.resolve = resolve.bind(Promise);
57-
assert.throws(() => {
58-
all.call(FakePromise1, [1, 2, 3]);
59-
}, 'NewPromiseCapability validations, #1');
60-
assert.throws(() => {
61-
all.call(FakePromise2, [1, 2, 3]);
62-
}, 'NewPromiseCapability validations, #2');
63-
assert.throws(() => {
64-
all.call(FakePromise3, [1, 2, 3]);
65-
}, 'NewPromiseCapability validations, #3');
113+
});
114+
115+
QUnit.test('Promise.all, without constructor context', assert => {
116+
const { all } = Promise;
117+
assert.throws(() => all([]), TypeError, 'Throws if called without a constructor context');
118+
assert.throws(() => all.call(null, []), TypeError, 'Throws if called with null as this');
66119
});

tests/unit-global/es.promise.any.js

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { createIterable } from '../helpers/helpers.js';
2+
13
QUnit.test('Promise.any', assert => {
24
assert.isFunction(Promise.any);
35
assert.arity(Promise.any, 1);
@@ -46,3 +48,86 @@ QUnit.test('Promise.any, rejected #3', assert => {
4648
assert.deepEqual(error.errors, [], 'rejected with a correct value');
4749
});
4850
});
51+
52+
QUnit.test('Promise.any, resolved with timeout', assert => {
53+
return Promise.any([
54+
new Promise(resolve => setTimeout(() => resolve(1), 50)),
55+
Promise.resolve(2),
56+
]).then(it => {
57+
assert.same(it, 2, 'resolved with a correct value');
58+
});
59+
});
60+
61+
QUnit.test('Promise.any, subclassing', assert => {
62+
const { any, resolve } = Promise;
63+
function SubPromise(executor) {
64+
executor(() => { /* empty */ }, () => { /* empty */ });
65+
}
66+
SubPromise.resolve = resolve.bind(Promise);
67+
assert.true(any.call(SubPromise, [1, 2, 3]) instanceof SubPromise, 'subclassing, `this` pattern');
68+
69+
function FakePromise1() { /* empty */ }
70+
function FakePromise2(executor) {
71+
executor(null, () => { /* empty */ });
72+
}
73+
function FakePromise3(executor) {
74+
executor(() => { /* empty */ }, null);
75+
}
76+
FakePromise1.resolve = FakePromise2.resolve = FakePromise3.resolve = resolve.bind(Promise);
77+
assert.throws(() => {
78+
any.call(FakePromise1, [1, 2, 3]);
79+
}, 'NewPromiseCapability validations, #1');
80+
assert.throws(() => {
81+
any.call(FakePromise2, [1, 2, 3]);
82+
}, 'NewPromiseCapability validations, #2');
83+
assert.throws(() => {
84+
any.call(FakePromise3, [1, 2, 3]);
85+
}, 'NewPromiseCapability validations, #3');
86+
});
87+
88+
QUnit.test('Promise.any, iterables', assert => {
89+
const iterable = createIterable([1, 2, 3]);
90+
Promise.any(iterable).catch(() => { /* empty */ });
91+
assert.true(iterable.received, 'works with iterables: iterator received');
92+
assert.true(iterable.called, 'works with iterables: next called');
93+
});
94+
95+
QUnit.test('Promise.any, empty iterables', assert => {
96+
const array = [];
97+
let done = false;
98+
// eslint-disable-next-line es/no-nonstandard-array-prototype-properties -- legacy FF case
99+
array['@@iterator'] = undefined;
100+
array[Symbol.iterator] = function () {
101+
done = true;
102+
return [][Symbol.iterator].call(this);
103+
};
104+
return Promise.any(array).then(() => {
105+
assert.avoid();
106+
}, error => {
107+
assert.true(error instanceof AggregateError, 'instanceof AggregateError');
108+
assert.true(done, 'iterator called');
109+
});
110+
});
111+
112+
QUnit.test('Promise.any, iterator closing', assert => {
113+
const { resolve } = Promise;
114+
let done = false;
115+
try {
116+
Promise.resolve = function () {
117+
throw new Error();
118+
};
119+
Promise.any(createIterable([1, 2, 3], {
120+
return() {
121+
done = true;
122+
},
123+
})).catch(() => { /* empty */ });
124+
} catch { /* empty */ }
125+
Promise.resolve = resolve;
126+
assert.true(done, 'iteration closing');
127+
});
128+
129+
QUnit.test('Promise.any, without constructor context', assert => {
130+
const { any } = Promise;
131+
assert.throws(() => any([]), TypeError, 'Throws if called without a constructor context');
132+
assert.throws(() => any.call(null, []), TypeError, 'Throws if called with null as this');
133+
});

0 commit comments

Comments
 (0)