Skip to content

Commit e484bb3

Browse files
committed
Promise tests
1 parent 6d03787 commit e484bb3

14 files changed

+820
-139
lines changed

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

Lines changed: 103 additions & 1 deletion
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);
@@ -6,7 +8,7 @@ QUnit.test('Promise.allSettled', assert => {
68
assert.true(Promise.allSettled([1, 2, 3]) instanceof Promise, 'returns a promise');
79
});
810

9-
QUnit.test('Promise.allSettled, resolved', assert => {
11+
QUnit.test('Promise.allSettled, resolved with rejection', assert => {
1012
return Promise.allSettled([
1113
Promise.resolve(1),
1214
Promise.reject(2),
@@ -28,3 +30,103 @@ QUnit.test('Promise.allSettled, rejected', assert => {
2830
assert.required('rejected as expected');
2931
});
3032
});
33+
34+
QUnit.test('Promise.allSettled, resolved', assert => {
35+
return Promise.allSettled([
36+
Promise.resolve(1),
37+
Promise.resolve(2),
38+
Promise.resolve(3),
39+
]).then(it => {
40+
assert.deepEqual(it, [
41+
{ value: 1, status: 'fulfilled' },
42+
{ value: 2, status: 'fulfilled' },
43+
{ value: 3, status: 'fulfilled' },
44+
], 'resolved with a correct value');
45+
});
46+
});
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, without constructor context', assert => {
63+
const { allSettled } = Promise;
64+
assert.throws(() => allSettled([]), TypeError, 'Throws if called without a constructor context');
65+
assert.throws(() => allSettled.call(null, []), TypeError, 'Throws if called with null as this');
66+
});
67+
68+
QUnit.test('Promise.allSettled, fake promises', assert => {
69+
const { all: allSettled, resolve } = Promise;
70+
let FakePromise1 = function (executor) {
71+
executor(() => { /* empty */ }, () => { /* empty */ });
72+
};
73+
let FakePromise2 = FakePromise1[Symbol.species] = function (executor) {
74+
executor(() => { /* empty */ }, () => { /* empty */ });
75+
};
76+
FakePromise1.resolve = FakePromise2.resolve = resolve.bind(Promise);
77+
assert.true(allSettled.call(FakePromise1, [1, 2, 3]) instanceof FakePromise1, 'subclassing, `this` pattern');
78+
FakePromise1 = function () { /* empty */ };
79+
FakePromise2 = function (executor) {
80+
executor(null, () => { /* empty */ });
81+
};
82+
const FakePromise3 = function (executor) {
83+
executor(() => { /* empty */ }, null);
84+
};
85+
FakePromise1.resolve = FakePromise2.resolve = FakePromise3.resolve = resolve.bind(Promise);
86+
assert.throws(() => {
87+
allSettled.call(FakePromise1, [1, 2, 3]);
88+
}, 'NewPromiseCapability validations, #1');
89+
assert.throws(() => {
90+
allSettled.call(FakePromise2, [1, 2, 3]);
91+
}, 'NewPromiseCapability validations, #2');
92+
assert.throws(() => {
93+
allSettled.call(FakePromise3, [1, 2, 3]);
94+
}, 'NewPromiseCapability validations, #3');
95+
});
96+
97+
QUnit.test('Promise.allSettled, iterables', assert => {
98+
const iterable = createIterable([1, 2, 3]);
99+
Promise.allSettled(iterable).catch(() => { /* empty */ });
100+
assert.true(iterable.received, 'works with iterables: iterator received');
101+
assert.true(iterable.called, 'works with iterables: next called');
102+
});
103+
104+
QUnit.test('Promise.allSettled, iterables 2', assert => {
105+
const array = [];
106+
let done = false;
107+
// eslint-disable-next-line es/no-nonstandard-array-prototype-properties -- legacy FF case
108+
array['@@iterator'] = undefined;
109+
array[Symbol.iterator] = function () {
110+
done = true;
111+
return [][Symbol.iterator].call(this);
112+
};
113+
Promise.allSettled(array);
114+
assert.true(done);
115+
});
116+
117+
QUnit.test('Promise.allSettled, iterables closing', assert => {
118+
const { resolve } = Promise;
119+
let done = false;
120+
try {
121+
Promise.resolve = function () {
122+
throw new Error();
123+
};
124+
Promise.allSettled(createIterable([1, 2, 3], {
125+
return() {
126+
done = true;
127+
},
128+
})).catch(() => { /* empty */ });
129+
} catch { /* empty */ }
130+
Promise.resolve = resolve;
131+
assert.true(done, 'iteration closing');
132+
});
Lines changed: 86 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,90 @@
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, fake promises', assert => {
52+
const { all, resolve } = Promise;
53+
let FakePromise1 = function (executor) {
54+
executor(() => { /* empty */ }, () => { /* empty */ });
55+
};
56+
let FakePromise2 = FakePromise1[Symbol.species] = function (executor) {
57+
executor(() => { /* empty */ }, () => { /* empty */ });
58+
};
59+
FakePromise1.resolve = FakePromise2.resolve = resolve.bind(Promise);
60+
assert.true(all.call(FakePromise1, [1, 2, 3]) instanceof FakePromise1, 'subclassing, `this` pattern');
61+
FakePromise1 = function () { /* empty */ };
62+
FakePromise2 = function (executor) {
63+
executor(null, () => { /* empty */ });
64+
};
65+
const FakePromise3 = function (executor) {
66+
executor(() => { /* empty */ }, null);
67+
};
68+
FakePromise1.resolve = FakePromise2.resolve = FakePromise3.resolve = resolve.bind(Promise);
69+
assert.throws(() => {
70+
all.call(FakePromise1, [1, 2, 3]);
71+
}, 'NewPromiseCapability validations, #1');
72+
assert.throws(() => {
73+
all.call(FakePromise2, [1, 2, 3]);
74+
}, 'NewPromiseCapability validations, #2');
75+
assert.throws(() => {
76+
all.call(FakePromise3, [1, 2, 3]);
77+
}, 'NewPromiseCapability validations, #3');
78+
});
79+
80+
QUnit.test('Promise.all, iterables', assert => {
1181
const iterable = createIterable([1, 2, 3]);
1282
Promise.all(iterable).catch(() => { /* empty */ });
1383
assert.true(iterable.received, 'works with iterables: iterator received');
1484
assert.true(iterable.called, 'works with iterables: next called');
85+
});
86+
87+
QUnit.test('Promise.all, iterables 2', assert => {
1588
const array = [];
1689
let done = false;
1790
// eslint-disable-next-line es/no-nonstandard-array-prototype-properties -- legacy FF case
@@ -22,10 +95,11 @@ QUnit.test('Promise.all', assert => {
2295
};
2396
Promise.all(array);
2497
assert.true(done);
25-
assert.throws(() => {
26-
all.call(null, []).catch(() => { /* empty */ });
27-
}, TypeError, 'throws without context');
28-
done = false;
98+
});
99+
100+
QUnit.test('Promise.all, iterables closing', assert => {
101+
const { resolve } = Promise;
102+
let done = false;
29103
try {
30104
Promise.resolve = function () {
31105
throw new Error();
@@ -38,29 +112,10 @@ QUnit.test('Promise.all', assert => {
38112
} catch { /* empty */ }
39113
Promise.resolve = resolve;
40114
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');
115+
});
116+
117+
QUnit.test('Promise.all, without constructor context', assert => {
118+
const { all } = Promise;
119+
assert.throws(() => all([]), TypeError, 'Throws if called without a constructor context');
120+
assert.throws(() => all.call(null, []), TypeError, 'Throws if called with null as this');
66121
});

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

Lines changed: 87 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,88 @@ 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, without constructor context', assert => {
62+
const { any } = Promise;
63+
assert.throws(() => any([]), TypeError, 'Throws if called without a constructor context');
64+
assert.throws(() => any.call(null, []), TypeError, 'Throws if called with null as this');
65+
});
66+
67+
QUnit.test('Promise.any, fake promises', assert => {
68+
const { any, resolve } = Promise;
69+
let FakePromise1 = function (executor) {
70+
executor(() => { /* empty */ }, () => { /* empty */ });
71+
};
72+
let FakePromise2 = FakePromise1[Symbol.species] = function (executor) {
73+
executor(() => { /* empty */ }, () => { /* empty */ });
74+
};
75+
FakePromise1.resolve = FakePromise2.resolve = resolve.bind(Promise);
76+
assert.true(any.call(FakePromise1, [1, 2, 3]) instanceof FakePromise1, 'subclassing, `this` pattern');
77+
FakePromise1 = function () { /* empty */ };
78+
FakePromise2 = function (executor) {
79+
executor(null, () => { /* empty */ });
80+
};
81+
const FakePromise3 = function (executor) {
82+
executor(() => { /* empty */ }, null);
83+
};
84+
FakePromise1.resolve = FakePromise2.resolve = FakePromise3.resolve = resolve.bind(Promise);
85+
assert.throws(() => {
86+
any.call(FakePromise1, [1, 2, 3]);
87+
}, 'NewPromiseCapability validations, #1');
88+
assert.throws(() => {
89+
any.call(FakePromise2, [1, 2, 3]);
90+
}, 'NewPromiseCapability validations, #2');
91+
assert.throws(() => {
92+
any.call(FakePromise3, [1, 2, 3]);
93+
}, 'NewPromiseCapability validations, #3');
94+
});
95+
96+
QUnit.test('Promise.any, iterables', assert => {
97+
const iterable = createIterable([1, 2, 3]);
98+
Promise.any(iterable).catch(() => { /* empty */ });
99+
assert.true(iterable.received, 'works with iterables: iterator received');
100+
assert.true(iterable.called, 'works with iterables: next called');
101+
});
102+
103+
QUnit.test('Promise.any, empty iterables', assert => {
104+
const array = [];
105+
let done = false;
106+
// eslint-disable-next-line es/no-nonstandard-array-prototype-properties -- legacy FF case
107+
array['@@iterator'] = undefined;
108+
array[Symbol.iterator] = function () {
109+
done = true;
110+
return [][Symbol.iterator].call(this);
111+
};
112+
return Promise.any(array).then(() => {
113+
assert.avoid();
114+
}, error => {
115+
assert.true(error instanceof AggregateError, 'instanceof AggregateError');
116+
assert.true(done, 'iterator called');
117+
});
118+
});
119+
120+
QUnit.test('Promise.any, iterables closing', assert => {
121+
const { resolve } = Promise;
122+
let done = false;
123+
try {
124+
Promise.resolve = function () {
125+
throw new Error();
126+
};
127+
Promise.any(createIterable([1, 2, 3], {
128+
return() {
129+
done = true;
130+
},
131+
})).catch(() => { /* empty */ });
132+
} catch { /* empty */ }
133+
Promise.resolve = resolve;
134+
assert.true(done, 'iteration closing');
135+
});

0 commit comments

Comments
 (0)