selenium-webdriver 3.0.0-beta-1 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES.md +109 -0
- package/LICENSE +1 -1
- package/README.md +7 -6
- package/chrome.js +31 -128
- package/edge.js +13 -91
- package/example/chrome_android.js +18 -13
- package/example/chrome_mobile_emulation.js +19 -15
- package/example/google_search.js +11 -11
- package/example/google_search_generator.js +23 -18
- package/example/google_search_test.js +31 -17
- package/example/logging.js +9 -17
- package/example/parallel_flows.js +3 -0
- package/firefox/binary.js +17 -0
- package/firefox/index.js +198 -101
- package/firefox/profile.js +24 -3
- package/http/util.js +95 -59
- package/ie.js +6 -10
- package/index.js +636 -2
- package/lib/actions.js +18 -10
- package/lib/atoms/getAttribute.js +11 -0
- package/lib/atoms/isDisplayed.js +106 -0
- package/lib/firefox/amd64/libnoblur64.so +0 -0
- package/lib/firefox/i386/libnoblur.so +0 -0
- package/lib/firefox/webdriver.xpi +0 -0
- package/lib/http.js +159 -46
- package/lib/logging.js +7 -1
- package/lib/promise.js +602 -358
- package/lib/proxy.js +28 -0
- package/lib/session.js +1 -1
- package/lib/test/build.js +26 -28
- package/lib/test/data/formPage.html +1 -0
- package/lib/test/fileserver.js +12 -10
- package/lib/test/httpserver.js +4 -6
- package/lib/test/index.js +18 -11
- package/lib/test/promise.js +79 -0
- package/lib/webdriver.js +587 -479
- package/opera.js +12 -88
- package/package.json +13 -14
- package/phantomjs.js +7 -14
- package/remote/index.js +201 -30
- package/safari.js +62 -416
- package/test/actions_test.js +9 -11
- package/test/chrome/options_test.js +8 -8
- package/test/chrome/service_test.js +2 -2
- package/test/cookie_test.js +57 -57
- package/test/element_finding_test.js +201 -185
- package/test/execute_script_test.js +108 -111
- package/test/fingerprint_test.js +16 -11
- package/test/firefox/firefox_test.js +75 -49
- package/test/firefox/profile_test.js +1 -3
- package/test/http/util_test.js +21 -27
- package/test/io_test.js +2 -5
- package/test/lib/http_test.js +8 -6
- package/test/lib/promise_aplus_test.js +48 -44
- package/test/lib/promise_error_test.js +687 -611
- package/test/lib/promise_flow_test.js +1810 -1806
- package/test/lib/promise_generator_test.js +227 -225
- package/test/lib/promise_test.js +864 -835
- package/test/lib/until_test.js +1 -1
- package/test/lib/webdriver_test.js +520 -424
- package/test/logging_test.js +43 -45
- package/test/net/portprober_test.js +23 -24
- package/test/page_loading_test.js +84 -78
- package/test/phantomjs/execute_phantomjs_test.js +11 -25
- package/test/proxy_test.js +23 -23
- package/test/remote_test.js +22 -22
- package/test/safari_test.js +108 -0
- package/test/session_test.js +11 -10
- package/test/stale_element_test.js +18 -16
- package/test/tag_name_test.js +7 -5
- package/test/testing/assert_test.js +2 -3
- package/test/testing/index_test.js +163 -117
- package/test/upload_test.js +13 -13
- package/test/window_test.js +94 -70
- package/testing/index.js +176 -37
- package/builder.js +0 -553
- package/lib/safari/client.js +0 -56
|
@@ -27,6 +27,7 @@ const testutil = require('./testutil');
|
|
|
27
27
|
|
|
28
28
|
const assert = require('assert');
|
|
29
29
|
const promise = require('../../lib/promise');
|
|
30
|
+
const {enablePromiseManager} = require('../../lib/test/promise');
|
|
30
31
|
|
|
31
32
|
const NativePromise = Promise;
|
|
32
33
|
const StubError = testutil.StubError;
|
|
@@ -34,244 +35,178 @@ const throwStubError = testutil.throwStubError;
|
|
|
34
35
|
const assertIsStubError = testutil.assertIsStubError;
|
|
35
36
|
|
|
36
37
|
describe('promise error handling', function() {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
afterEach(function tearDown() {
|
|
46
|
-
return waitForIdle(flow).then(function() {
|
|
47
|
-
assert.deepEqual(
|
|
48
|
-
[], uncaughtExceptions, 'There were uncaught exceptions');
|
|
49
|
-
flow.reset();
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
function onUncaughtException(e) {
|
|
54
|
-
uncaughtExceptions.push(e);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function waitForAbort(opt_flow, opt_n) {
|
|
58
|
-
var n = opt_n || 1;
|
|
59
|
-
var theFlow = opt_flow || flow;
|
|
60
|
-
theFlow.removeAllListeners(
|
|
61
|
-
promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION);
|
|
62
|
-
return new NativePromise(function(fulfill, reject) {
|
|
63
|
-
theFlow.once('idle', function() {
|
|
64
|
-
reject(Error('expected flow to report an unhandled error'));
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
var errors = [];
|
|
68
|
-
theFlow.on('uncaughtException', onError);
|
|
69
|
-
function onError(e) {
|
|
70
|
-
errors.push(e);
|
|
71
|
-
if (errors.length === n) {
|
|
72
|
-
theFlow.removeListener('uncaughtException', onError);
|
|
73
|
-
fulfill(n === 1 ? errors[0] : errors);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function waitForIdle(opt_flow) {
|
|
80
|
-
var theFlow = opt_flow || flow;
|
|
81
|
-
return new NativePromise(function(fulfill, reject) {
|
|
82
|
-
if (theFlow.isIdle()) {
|
|
83
|
-
fulfill();
|
|
84
|
-
return;
|
|
38
|
+
enablePromiseManager(() => {
|
|
39
|
+
var flow, uncaughtExceptions;
|
|
40
|
+
|
|
41
|
+
beforeEach(function setUp() {
|
|
42
|
+
if (promise.USE_PROMISE_MANAGER) {
|
|
43
|
+
flow = promise.controlFlow();
|
|
44
|
+
uncaughtExceptions = [];
|
|
45
|
+
flow.on('uncaughtException', onUncaughtException);
|
|
85
46
|
}
|
|
86
|
-
theFlow.once('idle', fulfill);
|
|
87
|
-
theFlow.once('uncaughtException', reject);
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
it('testRejectedPromiseTriggersErrorCallback', function() {
|
|
92
|
-
return promise.rejected(new StubError).
|
|
93
|
-
then(assert.fail, assertIsStubError);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
describe('callback throws trigger subsequent error callback', function() {
|
|
97
|
-
it('fulfilled promise', function() {
|
|
98
|
-
return promise.fulfilled().
|
|
99
|
-
then(throwStubError).
|
|
100
|
-
then(assert.fail, assertIsStubError);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it('rejected promise', function() {
|
|
104
|
-
var e = Error('not the droids you are looking for');
|
|
105
|
-
return promise.rejected(e).
|
|
106
|
-
then(assert.fail, throwStubError).
|
|
107
|
-
then(assert.fail, assertIsStubError);
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
describe('callback returns rejected promise triggers subsequent errback', function() {
|
|
112
|
-
it('from fulfilled callback', function() {
|
|
113
|
-
return promise.fulfilled().then(function() {
|
|
114
|
-
return promise.rejected(new StubError);
|
|
115
|
-
}).then(assert.fail, assertIsStubError);
|
|
116
47
|
});
|
|
117
48
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
49
|
+
afterEach(function tearDown() {
|
|
50
|
+
if (promise.USE_PROMISE_MANAGER) {
|
|
51
|
+
return waitForIdle(flow).then(function() {
|
|
52
|
+
assert.deepEqual(
|
|
53
|
+
[], uncaughtExceptions, 'There were uncaught exceptions');
|
|
54
|
+
flow.reset();
|
|
55
|
+
});
|
|
56
|
+
}
|
|
125
57
|
});
|
|
126
|
-
});
|
|
127
58
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
describe('multiple unhandled rejections outside a task', function() {
|
|
134
|
-
it('are reported in order they occurred', function() {
|
|
135
|
-
var e1 = Error('error 1');
|
|
136
|
-
var e2 = Error('error 2');
|
|
59
|
+
function onUncaughtException(e) {
|
|
60
|
+
uncaughtExceptions.push(e);
|
|
61
|
+
}
|
|
137
62
|
|
|
138
|
-
|
|
139
|
-
|
|
63
|
+
function waitForAbort(opt_flow, opt_n) {
|
|
64
|
+
var n = opt_n || 1;
|
|
65
|
+
var theFlow = opt_flow || flow;
|
|
66
|
+
theFlow.removeAllListeners(
|
|
67
|
+
promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION);
|
|
68
|
+
return new NativePromise(function(fulfill, reject) {
|
|
69
|
+
theFlow.once('idle', function() {
|
|
70
|
+
reject(Error('expected flow to report an unhandled error'));
|
|
71
|
+
});
|
|
140
72
|
|
|
141
|
-
return waitForAbort(flow).then(function(error) {
|
|
142
|
-
assert.ok(
|
|
143
|
-
error instanceof promise.MultipleUnhandledRejectionError);
|
|
144
|
-
// TODO: switch to Array.from when we drop node 0.12.x
|
|
145
73
|
var errors = [];
|
|
146
|
-
|
|
74
|
+
theFlow.on('uncaughtException', onError);
|
|
75
|
+
function onError(e) {
|
|
147
76
|
errors.push(e);
|
|
77
|
+
if (errors.length === n) {
|
|
78
|
+
theFlow.removeListener('uncaughtException', onError);
|
|
79
|
+
fulfill(n === 1 ? errors[0] : errors);
|
|
80
|
+
}
|
|
148
81
|
}
|
|
149
|
-
assert.deepEqual([e1, e2], errors);
|
|
150
82
|
});
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
describe('does not report unhandled rejection when', function() {
|
|
155
|
-
it('handler added before next tick', function() {
|
|
156
|
-
promise.rejected(new StubError).then(assert.fail, assertIsStubError);
|
|
157
|
-
return waitForIdle();
|
|
158
|
-
});
|
|
83
|
+
}
|
|
159
84
|
|
|
160
|
-
|
|
161
|
-
var
|
|
85
|
+
function waitForIdle(opt_flow) {
|
|
86
|
+
var theFlow = opt_flow || flow;
|
|
162
87
|
return new NativePromise(function(fulfill, reject) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
88
|
+
if (theFlow.isIdle()) {
|
|
89
|
+
fulfill();
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
theFlow.once('idle', fulfill);
|
|
93
|
+
theFlow.once('uncaughtException', reject);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
it('testRejectedPromiseTriggersErrorCallback', function() {
|
|
98
|
+
return promise.rejected(new StubError).
|
|
99
|
+
then(assert.fail, assertIsStubError);
|
|
175
100
|
});
|
|
176
|
-
});
|
|
177
101
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
102
|
+
describe('callback throws trigger subsequent error callback', function() {
|
|
103
|
+
it('fulfilled promise', function() {
|
|
104
|
+
return promise.fulfilled().
|
|
105
|
+
then(throwStubError).
|
|
106
|
+
then(assert.fail, assertIsStubError);
|
|
107
|
+
});
|
|
181
108
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
109
|
+
it('rejected promise', function() {
|
|
110
|
+
var e = Error('not the droids you are looking for');
|
|
111
|
+
return promise.rejected(e).
|
|
112
|
+
then(assert.fail, throwStubError).
|
|
113
|
+
then(assert.fail, assertIsStubError);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
187
116
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
117
|
+
describe('callback returns rejected promise triggers subsequent errback', function() {
|
|
118
|
+
it('from fulfilled callback', function() {
|
|
119
|
+
return promise.fulfilled().then(function() {
|
|
120
|
+
return promise.rejected(new StubError);
|
|
121
|
+
}).then(assert.fail, assertIsStubError);
|
|
122
|
+
});
|
|
193
123
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
124
|
+
it('from rejected callback', function() {
|
|
125
|
+
var e = Error('not the droids you are looking for');
|
|
126
|
+
return promise.rejected(e).
|
|
127
|
+
then(assert.fail, function() {
|
|
128
|
+
return promise.rejected(new StubError);
|
|
129
|
+
}).
|
|
130
|
+
then(assert.fail, assertIsStubError);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
198
133
|
|
|
199
|
-
|
|
200
|
-
var seen = [];
|
|
201
|
-
flow.execute(function() {
|
|
134
|
+
it('testReportsUnhandledRejectionsThroughTheControlFlow', function() {
|
|
202
135
|
promise.rejected(new StubError);
|
|
203
|
-
|
|
204
|
-
flow.execute(() => seen.push('a'))
|
|
205
|
-
.then(() => seen.push('b'), (e) => seen.push(e));
|
|
206
|
-
flow.execute(() => seen.push('c'))
|
|
207
|
-
.then(() => seen.push('b'), (e) => seen.push(e));
|
|
136
|
+
return waitForAbort().then(assertIsStubError);
|
|
208
137
|
});
|
|
209
138
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
139
|
+
describe('multiple unhandled rejections outside a task', function() {
|
|
140
|
+
it('are reported in order they occurred', function() {
|
|
141
|
+
var e1 = Error('error 1');
|
|
142
|
+
var e2 = Error('error 2');
|
|
214
143
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
return flow.execute(function() {
|
|
218
|
-
return flow.execute(function() {
|
|
219
|
-
return flow.execute(throwStubError);
|
|
220
|
-
});
|
|
221
|
-
}).then(assert.fail, assertIsStubError);
|
|
222
|
-
});
|
|
144
|
+
promise.rejected(e1);
|
|
145
|
+
promise.rejected(e2);
|
|
223
146
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
147
|
+
return waitForAbort(flow).then(function(error) {
|
|
148
|
+
assert.ok(
|
|
149
|
+
error instanceof promise.MultipleUnhandledRejectionError);
|
|
150
|
+
// TODO: switch to Array.from when we drop node 0.12.x
|
|
151
|
+
var errors = [];
|
|
152
|
+
for (var e of error.errors) {
|
|
153
|
+
errors.push(e);
|
|
154
|
+
}
|
|
155
|
+
assert.deepEqual([e1, e2], errors);
|
|
228
156
|
});
|
|
229
157
|
});
|
|
230
|
-
return waitForAbort().then(assertIsStubError);
|
|
231
158
|
});
|
|
232
159
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}).then(assert.fail, assertIsStubError);
|
|
239
|
-
return waitForIdle();
|
|
240
|
-
});
|
|
160
|
+
describe('does not report unhandled rejection when', function() {
|
|
161
|
+
it('handler added before next tick', function() {
|
|
162
|
+
promise.rejected(new StubError).then(assert.fail, assertIsStubError);
|
|
163
|
+
return waitForIdle();
|
|
164
|
+
});
|
|
241
165
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
166
|
+
it('added async but before next tick', function() {
|
|
167
|
+
var called = false;
|
|
168
|
+
return new NativePromise(function(fulfill, reject) {
|
|
169
|
+
var aPromise;
|
|
170
|
+
NativePromise.resolve().then(function() {
|
|
171
|
+
aPromise.then(assert.fail, function(e) {
|
|
172
|
+
called = true;
|
|
173
|
+
assertIsStubError(e);
|
|
174
|
+
});
|
|
175
|
+
waitForIdle().then(fulfill, reject);
|
|
247
176
|
});
|
|
248
|
-
|
|
177
|
+
aPromise = promise.rejected(new StubError);
|
|
178
|
+
}).then(function() {
|
|
179
|
+
assert.ok(called);
|
|
180
|
+
})
|
|
249
181
|
});
|
|
250
|
-
return waitForAbort().then(assertIsStubError);
|
|
251
182
|
});
|
|
252
183
|
|
|
253
|
-
it('
|
|
254
|
-
flow.execute(
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
184
|
+
it('testTaskThrows', function() {
|
|
185
|
+
return flow.execute(throwStubError).then(assert.fail, assertIsStubError);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('testTaskReturnsRejectedPromise', function() {
|
|
189
|
+
return flow.execute(function() {
|
|
190
|
+
return promise.rejected(new StubError)
|
|
258
191
|
}).then(assert.fail, assertIsStubError);
|
|
259
|
-
return waitForIdle();
|
|
260
192
|
});
|
|
261
193
|
|
|
262
|
-
it('
|
|
263
|
-
flow.execute(function() {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
194
|
+
it('testTaskHasUnhandledRejection', function() {
|
|
195
|
+
return flow.execute(function() {
|
|
196
|
+
promise.rejected(new StubError)
|
|
197
|
+
}).then(assert.fail, assertIsStubError);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('testTaskfails_returnedPromiseIsUnhandled', function() {
|
|
201
|
+
flow.execute(throwStubError);
|
|
268
202
|
return waitForAbort().then(assertIsStubError);
|
|
269
203
|
});
|
|
270
204
|
|
|
271
|
-
it('
|
|
205
|
+
it('testTaskHasUnhandledRejection_cancelsRemainingSubTasks', function() {
|
|
272
206
|
var seen = [];
|
|
273
207
|
flow.execute(function() {
|
|
274
|
-
|
|
208
|
+
promise.rejected(new StubError);
|
|
209
|
+
|
|
275
210
|
flow.execute(() => seen.push('a'))
|
|
276
211
|
.then(() => seen.push('b'), (e) => seen.push(e));
|
|
277
212
|
flow.execute(() => seen.push('c'))
|
|
@@ -282,526 +217,667 @@ describe('promise error handling', function() {
|
|
|
282
217
|
.then(assertIsStubError)
|
|
283
218
|
.then(() => assert.deepEqual([], seen));
|
|
284
219
|
});
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
it('testTaskReturnsPromiseLikeObjectThatInvokesErrback', function() {
|
|
288
|
-
return flow.execute(function() {
|
|
289
|
-
return {
|
|
290
|
-
'then': function(_, errback) {
|
|
291
|
-
errback('abc123');
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
|
-
}).then(assert.fail, function(value) {
|
|
295
|
-
assert.equal('abc123', value);
|
|
296
|
-
});
|
|
297
|
-
});
|
|
298
220
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
flow.wait(throwStubError, 50);
|
|
307
|
-
return waitForAbort().then(assertIsStubError);
|
|
308
|
-
});
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
describe('condition returns promise', function() {
|
|
312
|
-
it('failure is caught', function() {
|
|
313
|
-
return flow.wait(function() {
|
|
314
|
-
return promise.rejected(new StubError);
|
|
315
|
-
}, 50).then(assert.fail, assertIsStubError);
|
|
221
|
+
describe('nested task failures', function() {
|
|
222
|
+
it('returns up to paren', function() {
|
|
223
|
+
return flow.execute(function() {
|
|
224
|
+
return flow.execute(function() {
|
|
225
|
+
return flow.execute(throwStubError);
|
|
226
|
+
});
|
|
227
|
+
}).then(assert.fail, assertIsStubError);
|
|
316
228
|
});
|
|
317
229
|
|
|
318
|
-
it('
|
|
319
|
-
flow.
|
|
320
|
-
|
|
321
|
-
|
|
230
|
+
it('task throws; uncaught error bubbles up', function() {
|
|
231
|
+
flow.execute(function() {
|
|
232
|
+
flow.execute(function() {
|
|
233
|
+
flow.execute(throwStubError);
|
|
234
|
+
});
|
|
235
|
+
});
|
|
322
236
|
return waitForAbort().then(assertIsStubError);
|
|
323
237
|
});
|
|
324
|
-
});
|
|
325
238
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
239
|
+
it('task throws; uncaught error bubbles up; is caught at root', function() {
|
|
240
|
+
flow.execute(function() {
|
|
241
|
+
flow.execute(function() {
|
|
242
|
+
flow.execute(throwStubError);
|
|
243
|
+
});
|
|
244
|
+
}).then(assert.fail, assertIsStubError);
|
|
245
|
+
return waitForIdle();
|
|
331
246
|
});
|
|
332
247
|
|
|
333
|
-
it('
|
|
334
|
-
flow.
|
|
335
|
-
|
|
336
|
-
|
|
248
|
+
it('unhandled rejection bubbles up', function() {
|
|
249
|
+
flow.execute(function() {
|
|
250
|
+
flow.execute(function() {
|
|
251
|
+
flow.execute(function() {
|
|
252
|
+
promise.rejected(new StubError);
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
});
|
|
337
256
|
return waitForAbort().then(assertIsStubError);
|
|
338
257
|
});
|
|
339
|
-
});
|
|
340
258
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
return flow.wait(function() {
|
|
259
|
+
it('unhandled rejection bubbles up; caught at root', function() {
|
|
260
|
+
flow.execute(function() {
|
|
344
261
|
flow.execute(function() {
|
|
345
|
-
|
|
262
|
+
promise.rejected(new StubError);
|
|
346
263
|
});
|
|
347
|
-
}
|
|
264
|
+
}).then(assert.fail, assertIsStubError);
|
|
265
|
+
return waitForIdle();
|
|
348
266
|
});
|
|
349
267
|
|
|
350
|
-
it('
|
|
351
|
-
flow.
|
|
352
|
-
flow.execute(function() {
|
|
268
|
+
it('mixtureof hanging and free subtasks', function() {
|
|
269
|
+
flow.execute(function() {
|
|
270
|
+
return flow.execute(function() {
|
|
353
271
|
flow.execute(throwStubError);
|
|
354
272
|
});
|
|
355
|
-
}
|
|
273
|
+
});
|
|
356
274
|
return waitForAbort().then(assertIsStubError);
|
|
357
275
|
});
|
|
358
|
-
});
|
|
359
|
-
});
|
|
360
276
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
277
|
+
it('cancels remaining tasks', function() {
|
|
278
|
+
var seen = [];
|
|
279
|
+
flow.execute(function() {
|
|
280
|
+
flow.execute(() => promise.rejected(new StubError));
|
|
281
|
+
flow.execute(() => seen.push('a'))
|
|
282
|
+
.then(() => seen.push('b'), (e) => seen.push(e));
|
|
283
|
+
flow.execute(() => seen.push('c'))
|
|
284
|
+
.then(() => seen.push('b'), (e) => seen.push(e));
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
return waitForAbort()
|
|
288
|
+
.then(assertIsStubError)
|
|
289
|
+
.then(() => assert.deepEqual([], seen));
|
|
290
|
+
});
|
|
370
291
|
});
|
|
371
292
|
|
|
372
|
-
it('
|
|
373
|
-
var error = Error('an error');
|
|
293
|
+
it('testTaskReturnsPromiseLikeObjectThatInvokesErrback', function() {
|
|
374
294
|
return flow.execute(function() {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
}).
|
|
381
|
-
|
|
295
|
+
return {
|
|
296
|
+
'then': function(_, errback) {
|
|
297
|
+
errback('abc123');
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
}).then(assert.fail, function(value) {
|
|
301
|
+
assert.equal('abc123', value);
|
|
302
|
+
});
|
|
382
303
|
});
|
|
383
304
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
throw new StubError;
|
|
390
|
-
});
|
|
391
|
-
return waitForAbort().then(assertIsStubError);
|
|
392
|
-
});
|
|
305
|
+
describe('ControlFlow#wait();', function() {
|
|
306
|
+
describe('condition throws;', function() {
|
|
307
|
+
it('failure is caught', function() {
|
|
308
|
+
return flow.wait(throwStubError, 50).then(assert.fail, assertIsStubError);
|
|
309
|
+
});
|
|
393
310
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
})
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
311
|
+
it('failure is not caught', function() {
|
|
312
|
+
flow.wait(throwStubError, 50);
|
|
313
|
+
return waitForAbort().then(assertIsStubError);
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
describe('condition returns promise', function() {
|
|
318
|
+
it('failure is caught', function() {
|
|
319
|
+
return flow.wait(function() {
|
|
320
|
+
return promise.rejected(new StubError);
|
|
321
|
+
}, 50).then(assert.fail, assertIsStubError);
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
it('failure is not caught', function() {
|
|
325
|
+
flow.wait(function() {
|
|
326
|
+
return promise.rejected(new StubError);
|
|
327
|
+
}, 50);
|
|
328
|
+
return waitForAbort().then(assertIsStubError);
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
describe('condition has unhandled promise rejection', function() {
|
|
333
|
+
it('failure is caught', function() {
|
|
334
|
+
return flow.wait(function() {
|
|
335
|
+
promise.rejected(new StubError);
|
|
336
|
+
}, 50).then(assert.fail, assertIsStubError);
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
it('failure is not caught', function() {
|
|
340
|
+
flow.wait(function() {
|
|
341
|
+
promise.rejected(new StubError);
|
|
342
|
+
}, 50);
|
|
343
|
+
return waitForAbort().then(assertIsStubError);
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
describe('condition has subtask failure', function() {
|
|
348
|
+
it('failure is caught', function() {
|
|
349
|
+
return flow.wait(function() {
|
|
350
|
+
flow.execute(function() {
|
|
351
|
+
flow.execute(throwStubError);
|
|
352
|
+
});
|
|
353
|
+
}, 50).then(assert.fail, assertIsStubError);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
it('failure is not caught', function() {
|
|
357
|
+
flow.wait(function() {
|
|
358
|
+
flow.execute(function() {
|
|
359
|
+
flow.execute(throwStubError);
|
|
360
|
+
});
|
|
361
|
+
}, 50);
|
|
362
|
+
return waitForAbort().then(assertIsStubError);
|
|
363
|
+
});
|
|
402
364
|
});
|
|
403
|
-
return waitForAbort().then(assertIsStubError);
|
|
404
365
|
});
|
|
405
|
-
});
|
|
406
366
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
367
|
+
describe('errback throws a new error', function() {
|
|
368
|
+
it('start with normal promise', function() {
|
|
369
|
+
var error = Error('an error');
|
|
370
|
+
return promise.rejected(error).
|
|
371
|
+
catch(function(e) {
|
|
372
|
+
assert.equal(e, error);
|
|
373
|
+
throw new StubError;
|
|
374
|
+
}).
|
|
375
|
+
catch(assertIsStubError);
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
it('start with task result', function() {
|
|
379
|
+
var error = Error('an error');
|
|
380
|
+
return flow.execute(function() {
|
|
381
|
+
throw error;
|
|
382
|
+
}).
|
|
383
|
+
catch(function(e) {
|
|
384
|
+
assert.equal(e, error);
|
|
385
|
+
throw new StubError;
|
|
386
|
+
}).
|
|
387
|
+
catch(assertIsStubError);
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
it('start with normal promise; uncaught error', function() {
|
|
391
|
+
var error = Error('an error');
|
|
392
|
+
promise.rejected(error).
|
|
393
|
+
catch(function(e) {
|
|
394
|
+
assert.equal(e, error);
|
|
395
|
+
throw new StubError;
|
|
396
|
+
});
|
|
397
|
+
return waitForAbort().then(assertIsStubError);
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
it('start with task result; uncaught error', function() {
|
|
401
|
+
var error = Error('an error');
|
|
402
|
+
flow.execute(function() {
|
|
403
|
+
throw error;
|
|
404
|
+
}).
|
|
405
|
+
catch(function(e) {
|
|
406
|
+
assert.equal(e, error);
|
|
407
|
+
throw new StubError;
|
|
408
|
+
});
|
|
409
|
+
return waitForAbort().then(assertIsStubError);
|
|
410
|
+
});
|
|
413
411
|
});
|
|
414
|
-
});
|
|
415
412
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
throw toThrow;
|
|
413
|
+
it('thrownPromiseCausesCallbackRejection', function() {
|
|
414
|
+
let p = promise.fulfilled(1234);
|
|
415
|
+
return promise.fulfilled().then(function() {
|
|
416
|
+
throw p;
|
|
421
417
|
}).then(assert.fail, function(value) {
|
|
422
|
-
assert.
|
|
423
|
-
return toThrow;
|
|
424
|
-
}).then(function(value) {
|
|
425
|
-
assert.equal(1234, value);
|
|
418
|
+
assert.strictEqual(p, value);
|
|
426
419
|
});
|
|
427
|
-
return waitForIdle();
|
|
428
420
|
});
|
|
429
421
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
422
|
+
describe('task throws promise', function() {
|
|
423
|
+
it('promise was fulfilled', function() {
|
|
424
|
+
var toThrow = promise.fulfilled(1234);
|
|
425
|
+
flow.execute(function() {
|
|
426
|
+
throw toThrow;
|
|
427
|
+
}).then(assert.fail, function(value) {
|
|
428
|
+
assert.equal(toThrow, value);
|
|
429
|
+
return toThrow;
|
|
430
|
+
}).then(function(value) {
|
|
431
|
+
assert.equal(1234, value);
|
|
432
|
+
});
|
|
433
|
+
return waitForIdle();
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
it('promise was rejected', function() {
|
|
437
|
+
var toThrow = promise.rejected(new StubError);
|
|
438
|
+
toThrow.catch(function() {}); // For tearDown.
|
|
439
|
+
flow.execute(function() {
|
|
440
|
+
throw toThrow;
|
|
441
|
+
}).then(assert.fail, function(e) {
|
|
442
|
+
assert.equal(toThrow, e);
|
|
443
|
+
return e;
|
|
444
|
+
}).then(assert.fail, assertIsStubError);
|
|
445
|
+
return waitForIdle();
|
|
446
|
+
});
|
|
440
447
|
});
|
|
441
|
-
});
|
|
442
448
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
+
it('testFailsTaskIfThereIsAnUnhandledErrorWhileWaitingOnTaskResult', function() {
|
|
450
|
+
var d = promise.defer();
|
|
451
|
+
flow.execute(function() {
|
|
452
|
+
promise.rejected(new StubError);
|
|
453
|
+
return d.promise;
|
|
454
|
+
}).then(assert.fail, assertIsStubError);
|
|
449
455
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
456
|
+
return waitForIdle().then(function() {
|
|
457
|
+
return d.promise;
|
|
458
|
+
}).then(assert.fail, function(e) {
|
|
459
|
+
assert.equal('CancellationError: StubError', e.toString());
|
|
460
|
+
});
|
|
454
461
|
});
|
|
455
|
-
});
|
|
456
462
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
+
it('testFailsParentTaskIfAsyncScheduledTaskFails', function() {
|
|
464
|
+
var d = promise.defer();
|
|
465
|
+
flow.execute(function() {
|
|
466
|
+
flow.execute(throwStubError);
|
|
467
|
+
return d.promise;
|
|
468
|
+
}).then(assert.fail, assertIsStubError);
|
|
463
469
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
470
|
+
return waitForIdle().then(function() {
|
|
471
|
+
return d.promise;
|
|
472
|
+
}).then(assert.fail, function(e) {
|
|
473
|
+
assert.equal('CancellationError: StubError', e.toString());
|
|
474
|
+
});
|
|
468
475
|
});
|
|
469
|
-
});
|
|
470
476
|
|
|
471
|
-
|
|
472
|
-
|
|
477
|
+
describe('long stack traces', function() {
|
|
478
|
+
afterEach(() => promise.LONG_STACK_TRACES = false);
|
|
473
479
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
flow.execute(function() {
|
|
480
|
+
it('always includes task stacks in failures', function() {
|
|
481
|
+
promise.LONG_STACK_TRACES = false;
|
|
477
482
|
flow.execute(function() {
|
|
478
|
-
flow.execute(
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
483
|
+
flow.execute(function() {
|
|
484
|
+
flow.execute(throwStubError, 'throw error');
|
|
485
|
+
}, 'two');
|
|
486
|
+
}, 'three').
|
|
487
|
+
then(assert.fail, function(e) {
|
|
488
|
+
assertIsStubError(e);
|
|
489
|
+
if (typeof e.stack !== 'string') {
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
var messages = e.stack.split(/\n/).filter(function(line, index) {
|
|
493
|
+
return /^From: /.test(line);
|
|
494
|
+
});
|
|
495
|
+
assert.deepEqual([
|
|
496
|
+
'From: Task: throw error',
|
|
497
|
+
'From: Task: two',
|
|
498
|
+
'From: Task: three'
|
|
499
|
+
], messages);
|
|
488
500
|
});
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
501
|
+
return waitForIdle();
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
it('does not include completed tasks', function () {
|
|
505
|
+
flow.execute(function() {}, 'succeeds');
|
|
506
|
+
flow.execute(throwStubError, 'kaboom').then(assert.fail, function(e) {
|
|
507
|
+
assertIsStubError(e);
|
|
508
|
+
if (typeof e.stack !== 'string') {
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
var messages = e.stack.split(/\n/).filter(function(line, index) {
|
|
512
|
+
return /^From: /.test(line);
|
|
513
|
+
});
|
|
514
|
+
assert.deepEqual(['From: Task: kaboom'], messages);
|
|
515
|
+
});
|
|
516
|
+
return waitForIdle();
|
|
494
517
|
});
|
|
495
|
-
return waitForIdle();
|
|
496
|
-
});
|
|
497
518
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
519
|
+
it('does not include promise chain when disabled', function() {
|
|
520
|
+
promise.LONG_STACK_TRACES = false;
|
|
521
|
+
flow.execute(function() {
|
|
522
|
+
flow.execute(function() {
|
|
523
|
+
return promise.fulfilled().
|
|
524
|
+
then(function() {}).
|
|
525
|
+
then(function() {}).
|
|
526
|
+
then(throwStubError);
|
|
527
|
+
}, 'eventually assert.fails');
|
|
528
|
+
}, 'start').
|
|
529
|
+
then(assert.fail, function(e) {
|
|
530
|
+
assertIsStubError(e);
|
|
531
|
+
if (typeof e.stack !== 'string') {
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
var messages = e.stack.split(/\n/).filter(function(line, index) {
|
|
535
|
+
return /^From: /.test(line);
|
|
536
|
+
});
|
|
537
|
+
assert.deepEqual([
|
|
538
|
+
'From: Task: eventually assert.fails',
|
|
539
|
+
'From: Task: start'
|
|
540
|
+
], messages);
|
|
507
541
|
});
|
|
508
|
-
|
|
542
|
+
return waitForIdle();
|
|
509
543
|
});
|
|
510
|
-
return waitForIdle();
|
|
511
|
-
});
|
|
512
544
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
flow.execute(function() {
|
|
545
|
+
it('includes promise chain when enabled', function() {
|
|
546
|
+
promise.LONG_STACK_TRACES = true;
|
|
516
547
|
flow.execute(function() {
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
548
|
+
flow.execute(function() {
|
|
549
|
+
return promise.fulfilled().
|
|
550
|
+
then(function() {}).
|
|
551
|
+
then(function() {}).
|
|
552
|
+
then(throwStubError);
|
|
553
|
+
}, 'eventually assert.fails');
|
|
554
|
+
}, 'start').
|
|
555
|
+
then(assert.fail, function(e) {
|
|
556
|
+
assertIsStubError(e);
|
|
557
|
+
if (typeof e.stack !== 'string') {
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
var messages = e.stack.split(/\n/).filter(function(line, index) {
|
|
561
|
+
return /^From: /.test(line);
|
|
562
|
+
});
|
|
563
|
+
assert.deepEqual([
|
|
564
|
+
'From: Promise: then',
|
|
565
|
+
'From: Task: eventually assert.fails',
|
|
566
|
+
'From: Task: start'
|
|
567
|
+
], messages);
|
|
530
568
|
});
|
|
531
|
-
|
|
532
|
-
'From: Task: eventually assert.fails',
|
|
533
|
-
'From: Task: start'
|
|
534
|
-
], messages);
|
|
569
|
+
return waitForIdle();
|
|
535
570
|
});
|
|
536
|
-
return waitForIdle();
|
|
537
571
|
});
|
|
538
572
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
flow.execute(function() {
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
}, 'start').
|
|
549
|
-
then(assert.fail, function(e) {
|
|
550
|
-
assertIsStubError(e);
|
|
551
|
-
if (typeof e.stack !== 'string') {
|
|
552
|
-
return;
|
|
553
|
-
}
|
|
554
|
-
var messages = e.stack.split(/\n/).filter(function(line, index) {
|
|
555
|
-
return /^From: /.test(line);
|
|
573
|
+
describe('frame cancels remaining tasks', function() {
|
|
574
|
+
it('on unhandled task failure', function() {
|
|
575
|
+
var run = false;
|
|
576
|
+
return flow.execute(function() {
|
|
577
|
+
flow.execute(throwStubError);
|
|
578
|
+
flow.execute(function() { run = true; });
|
|
579
|
+
}).then(assert.fail, function(e) {
|
|
580
|
+
assertIsStubError(e);
|
|
581
|
+
assert.ok(!run);
|
|
556
582
|
});
|
|
557
|
-
assert.deepEqual([
|
|
558
|
-
'From: Promise: then',
|
|
559
|
-
'From: Task: eventually assert.fails',
|
|
560
|
-
'From: Task: start'
|
|
561
|
-
], messages);
|
|
562
583
|
});
|
|
563
|
-
return waitForIdle();
|
|
564
|
-
});
|
|
565
|
-
});
|
|
566
584
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
585
|
+
it('on unhandled promise rejection', function() {
|
|
586
|
+
var run = false;
|
|
587
|
+
return flow.execute(function() {
|
|
588
|
+
promise.rejected(new StubError);
|
|
589
|
+
flow.execute(function() { run = true; });
|
|
590
|
+
}).then(assert.fail, function(e) {
|
|
591
|
+
assertIsStubError(e);
|
|
592
|
+
assert.ok(!run);
|
|
593
|
+
});
|
|
594
|
+
});
|
|
577
595
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
596
|
+
it('if task throws', function() {
|
|
597
|
+
var run = false;
|
|
598
|
+
return flow.execute(function() {
|
|
599
|
+
flow.execute(function() { run = true; });
|
|
600
|
+
throw new StubError;
|
|
601
|
+
}).then(assert.fail, function(e) {
|
|
602
|
+
assertIsStubError(e);
|
|
603
|
+
assert.ok(!run);
|
|
604
|
+
});
|
|
605
|
+
});
|
|
588
606
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
flow.execute(throwStubError);
|
|
607
|
+
describe('task callbacks scheduled in another frame', function() {
|
|
608
|
+
flow = promise.controlFlow();
|
|
609
|
+
function noop() {}
|
|
593
610
|
|
|
594
|
-
|
|
595
|
-
seen.push(1);
|
|
596
|
-
}).then(function() {
|
|
597
|
-
seen.push(2);
|
|
598
|
-
}, function() {
|
|
599
|
-
seen.push(3);
|
|
600
|
-
});
|
|
601
|
-
}).then(assert.fail, function(e) {
|
|
602
|
-
assertIsStubError(e);
|
|
603
|
-
assert.deepEqual([], seen);
|
|
604
|
-
});
|
|
605
|
-
});
|
|
611
|
+
let subTask;
|
|
606
612
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
613
|
+
before(function() {
|
|
614
|
+
flow.execute(function() {
|
|
615
|
+
// This task will be discarded and never run because of the error below.
|
|
616
|
+
subTask = flow.execute(() => 'abc');
|
|
617
|
+
throw new StubError('stub');
|
|
618
|
+
}).catch(noop);
|
|
619
|
+
});
|
|
611
620
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
seen.push(3);
|
|
618
|
-
});
|
|
619
|
-
}).then(assert.fail, function(e) {
|
|
620
|
-
assertIsStubError(e);
|
|
621
|
-
assert.deepEqual([], seen);
|
|
622
|
-
});
|
|
623
|
-
});
|
|
621
|
+
function assertCancellation(e) {
|
|
622
|
+
assert.ok(e instanceof promise.CancellationError);
|
|
623
|
+
assert.equal(
|
|
624
|
+
'Task was discarded due to a previous failure: stub', e.message);
|
|
625
|
+
}
|
|
624
626
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
627
|
+
it('are rejected with cancellation error', function() {
|
|
628
|
+
let result;
|
|
629
|
+
return Promise.resolve().then(function() {
|
|
630
|
+
return flow.execute(function() {
|
|
631
|
+
result = subTask.then(assert.fail);
|
|
632
|
+
});
|
|
633
|
+
})
|
|
634
|
+
.then(() => result)
|
|
635
|
+
.then(assert.fail, assertCancellation);
|
|
636
|
+
});
|
|
629
637
|
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
638
|
+
it('cancellation errors propagate through callbacks (1)', function() {
|
|
639
|
+
let result;
|
|
640
|
+
return Promise.resolve().then(function() {
|
|
641
|
+
return flow.execute(function() {
|
|
642
|
+
result = subTask
|
|
643
|
+
.then(assert.fail, assertCancellation)
|
|
644
|
+
.then(() => 'abc123');
|
|
645
|
+
});
|
|
646
|
+
})
|
|
647
|
+
.then(() => result)
|
|
648
|
+
.then(value => assert.equal('abc123', value));
|
|
637
649
|
});
|
|
638
|
-
}).finally(function() {
|
|
639
|
-
seen.push(3);
|
|
640
|
-
});
|
|
641
650
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
651
|
+
it('cancellation errors propagate through callbacks (2)', function() {
|
|
652
|
+
let result;
|
|
653
|
+
return Promise.resolve().then(function() {
|
|
654
|
+
return flow.execute(function() {
|
|
655
|
+
result = subTask.then(assert.fail)
|
|
656
|
+
.then(noop, assertCancellation)
|
|
657
|
+
.then(() => 'fin');
|
|
658
|
+
});
|
|
659
|
+
})
|
|
660
|
+
// Verify result actually computed successfully all the way through.
|
|
661
|
+
.then(() => result)
|
|
662
|
+
.then(value => assert.equal('fin', value));
|
|
663
|
+
});
|
|
664
|
+
});
|
|
645
665
|
});
|
|
646
|
-
});
|
|
647
|
-
|
|
648
|
-
it('testTaskIsCancelledAfterWaitTimeout', function() {
|
|
649
|
-
var seen = [];
|
|
650
|
-
return flow.execute(function() {
|
|
651
|
-
flow.wait(function() {
|
|
652
|
-
return promise.delayed(50);
|
|
653
|
-
}, 5);
|
|
654
666
|
|
|
667
|
+
it('testRegisteredTaskCallbacksAreDroppedWhenTaskIsCancelled_return', function() {
|
|
668
|
+
var seen = [];
|
|
655
669
|
return flow.execute(function() {
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
670
|
+
flow.execute(throwStubError);
|
|
671
|
+
|
|
672
|
+
flow.execute(function() {
|
|
673
|
+
seen.push(1);
|
|
674
|
+
}).then(function() {
|
|
675
|
+
seen.push(2);
|
|
676
|
+
}, function() {
|
|
677
|
+
seen.push(3);
|
|
678
|
+
});
|
|
679
|
+
}).then(assert.fail, function(e) {
|
|
680
|
+
assertIsStubError(e);
|
|
681
|
+
assert.deepEqual([], seen);
|
|
682
|
+
});
|
|
664
683
|
});
|
|
665
|
-
});
|
|
666
684
|
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
flow.execute(function() {
|
|
685
|
+
it('testRegisteredTaskCallbacksAreDroppedWhenTaskIsCancelled_withReturn', function() {
|
|
686
|
+
var seen = [];
|
|
687
|
+
return flow.execute(function() {
|
|
671
688
|
flow.execute(throwStubError);
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
689
|
+
|
|
690
|
+
return flow.execute(function() {
|
|
691
|
+
seen.push(1);
|
|
692
|
+
}).then(function() {
|
|
693
|
+
seen.push(2);
|
|
694
|
+
}, function() {
|
|
695
|
+
seen.push(3);
|
|
677
696
|
});
|
|
697
|
+
}).then(assert.fail, function(e) {
|
|
698
|
+
assertIsStubError(e);
|
|
699
|
+
assert.deepEqual([], seen);
|
|
678
700
|
});
|
|
679
701
|
});
|
|
680
702
|
|
|
681
|
-
it('
|
|
703
|
+
it('testTasksWithinACallbackAreDroppedIfContainingTaskIsAborted', function() {
|
|
682
704
|
var seen = [];
|
|
683
|
-
|
|
684
|
-
var task;
|
|
685
|
-
flow.execute(function() {
|
|
705
|
+
return flow.execute(function() {
|
|
686
706
|
flow.execute(throwStubError);
|
|
687
|
-
task = flow.execute(function() {});
|
|
688
707
|
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
708
|
+
// None of the callbacks on this promise should execute because the
|
|
709
|
+
// task assert.failure above is never handled, causing the containing task to
|
|
710
|
+
// abort.
|
|
711
|
+
promise.fulfilled().then(function() {
|
|
712
|
+
seen.push(1);
|
|
713
|
+
return flow.execute(function() {
|
|
714
|
+
seen.push(2);
|
|
715
|
+
});
|
|
716
|
+
}).finally(function() {
|
|
717
|
+
seen.push(3);
|
|
718
|
+
});
|
|
693
719
|
|
|
694
|
-
}).then(assert.fail,
|
|
720
|
+
}).then(assert.fail, function(e) {
|
|
721
|
+
assertIsStubError(e);
|
|
722
|
+
assert.deepEqual([], seen);
|
|
723
|
+
});
|
|
724
|
+
});
|
|
695
725
|
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
726
|
+
it('testTaskIsCancelledAfterWaitTimeout', function() {
|
|
727
|
+
var seen = [];
|
|
728
|
+
return flow.execute(function() {
|
|
729
|
+
flow.wait(function() {
|
|
730
|
+
return promise.delayed(50);
|
|
731
|
+
}, 5);
|
|
732
|
+
|
|
733
|
+
return flow.execute(function() {
|
|
734
|
+
seen.push(1);
|
|
735
|
+
}).then(function() {
|
|
736
|
+
seen.push(2);
|
|
737
|
+
}, function() {
|
|
738
|
+
seen.push(3);
|
|
700
739
|
});
|
|
701
|
-
}).then(
|
|
740
|
+
}).then(assert.fail, function() {
|
|
741
|
+
assert.deepEqual([], seen);
|
|
742
|
+
});
|
|
702
743
|
});
|
|
703
|
-
});
|
|
704
744
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
745
|
+
describe('task callbacks get cancellation error if registered after task was cancelled', function() {
|
|
746
|
+
it('(a)', function() {
|
|
747
|
+
var task;
|
|
748
|
+
flow.execute(function() {
|
|
749
|
+
flow.execute(throwStubError);
|
|
750
|
+
task = flow.execute(function() {});
|
|
751
|
+
}).then(assert.fail, assertIsStubError);
|
|
752
|
+
return waitForIdle().then(function() {
|
|
753
|
+
return task.then(assert.fail, function(e) {
|
|
754
|
+
assert.ok(e instanceof promise.CancellationError);
|
|
755
|
+
});
|
|
756
|
+
});
|
|
757
|
+
});
|
|
710
758
|
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
flow.execute(throwStubError, 'a.2 (throws)');
|
|
714
|
-
});
|
|
759
|
+
it('(b)', function() {
|
|
760
|
+
var seen = [];
|
|
715
761
|
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
b3 = schedule('b.3');
|
|
721
|
-
});
|
|
762
|
+
var task;
|
|
763
|
+
flow.execute(function() {
|
|
764
|
+
flow.execute(throwStubError);
|
|
765
|
+
task = flow.execute(function() {});
|
|
722
766
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
767
|
+
task.then(() => seen.push(1))
|
|
768
|
+
.then(() => seen.push(2));
|
|
769
|
+
task.then(() => seen.push(3))
|
|
770
|
+
.then(() => seen.push(4));
|
|
771
|
+
|
|
772
|
+
}).then(assert.fail, assertIsStubError);
|
|
729
773
|
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
774
|
+
return waitForIdle().then(function() {
|
|
775
|
+
return task.then(assert.fail, function(e) {
|
|
776
|
+
seen.push(5);
|
|
777
|
+
assert.ok(e instanceof promise.CancellationError);
|
|
778
|
+
});
|
|
779
|
+
}).then(() => assert.deepEqual([5], seen));
|
|
733
780
|
});
|
|
734
|
-
}
|
|
781
|
+
});
|
|
735
782
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
})
|
|
742
|
-
.then(() => assertWasCancelled(b3))
|
|
743
|
-
.then(() => assertWasCancelled(c3));
|
|
744
|
-
});
|
|
783
|
+
it('unhandledRejectionInParallelTaskQueue', function() {
|
|
784
|
+
var seen = [];
|
|
785
|
+
function schedule(name) {
|
|
786
|
+
return flow.execute(() => seen.push(name), name);
|
|
787
|
+
}
|
|
745
788
|
|
|
746
|
-
|
|
747
|
-
|
|
789
|
+
flow.async(function() {
|
|
790
|
+
schedule('a.1');
|
|
791
|
+
flow.execute(throwStubError, 'a.2 (throws)');
|
|
792
|
+
});
|
|
748
793
|
|
|
749
|
-
|
|
750
|
-
return new Promise(function(fulfill) {
|
|
751
|
-
flow.once('uncaughtException', fulfill);
|
|
794
|
+
var b3;
|
|
752
795
|
flow.async(function() {
|
|
753
|
-
|
|
754
|
-
|
|
796
|
+
schedule('b.1');
|
|
797
|
+
schedule('b.2');
|
|
798
|
+
b3 = schedule('b.3');
|
|
755
799
|
});
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
800
|
+
|
|
801
|
+
var c3;
|
|
802
|
+
flow.async(function() {
|
|
803
|
+
schedule('c.1');
|
|
804
|
+
schedule('c.2');
|
|
805
|
+
c3 = schedule('c.3');
|
|
761
806
|
});
|
|
807
|
+
|
|
808
|
+
function assertWasCancelled(p) {
|
|
809
|
+
return p.then(assert.fail, function(e) {
|
|
810
|
+
assert.ok(e instanceof promise.CancellationError);
|
|
811
|
+
});
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
return waitForAbort()
|
|
815
|
+
.then(function() {
|
|
816
|
+
assert.deepEqual(['a.1', 'b.1', 'c.1', 'b.2', 'c.2'], seen);
|
|
817
|
+
})
|
|
818
|
+
.then(() => assertWasCancelled(b3))
|
|
819
|
+
.then(() => assertWasCancelled(c3));
|
|
762
820
|
});
|
|
763
|
-
});
|
|
764
821
|
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
var
|
|
769
|
-
return
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
822
|
+
it('errorsInAsyncFunctionsAreReportedAsUnhandledRejection', function() {
|
|
823
|
+
flow.removeAllListeners(); // For tearDown.
|
|
824
|
+
|
|
825
|
+
var task;
|
|
826
|
+
return new Promise(function(fulfill) {
|
|
827
|
+
flow.once('uncaughtException', fulfill);
|
|
828
|
+
flow.async(function() {
|
|
829
|
+
task = flow.execute(function() {});
|
|
830
|
+
throw Error('boom');
|
|
831
|
+
});
|
|
832
|
+
}).then(function(error) {
|
|
833
|
+
assert.ok(error instanceof promise.CancellationError);
|
|
834
|
+
return task.catch(function(error) {
|
|
835
|
+
assert.ok(error instanceof promise.CancellationError);
|
|
836
|
+
});
|
|
773
837
|
});
|
|
774
838
|
});
|
|
775
839
|
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
840
|
+
describe('does not wait for values thrown from callbacks to be resolved', function() {
|
|
841
|
+
it('(a)', function() {
|
|
842
|
+
var p1 = promise.fulfilled();
|
|
843
|
+
var reason = promise.fulfilled('should not see me');
|
|
844
|
+
return p1.then(function() {
|
|
845
|
+
throw reason;
|
|
846
|
+
}).then(assert.fail, function(e) {
|
|
847
|
+
assert.equal(reason, e);
|
|
848
|
+
});
|
|
784
849
|
});
|
|
785
|
-
});
|
|
786
850
|
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
851
|
+
it('(b)', function() {
|
|
852
|
+
var p1 = promise.fulfilled();
|
|
853
|
+
var reason = promise.rejected('should not see me');
|
|
854
|
+
reason.catch(function() {}); // For tearDown.
|
|
855
|
+
return p1.then(function() {
|
|
856
|
+
throw reason;
|
|
857
|
+
}).then(assert.fail, function(e) {
|
|
858
|
+
assert.equal(reason, e);
|
|
859
|
+
});
|
|
795
860
|
});
|
|
796
|
-
});
|
|
797
861
|
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
assert.
|
|
862
|
+
it('(c)', function() {
|
|
863
|
+
var p1 = promise.fulfilled();
|
|
864
|
+
var reason = promise.defer();
|
|
865
|
+
setTimeout(() => reason.fulfill('should not see me'), 100);
|
|
866
|
+
return p1.then(function() {
|
|
867
|
+
throw reason.promise;
|
|
868
|
+
}).then(assert.fail, function(e) {
|
|
869
|
+
assert.equal(reason.promise, e);
|
|
870
|
+
});
|
|
871
|
+
});
|
|
872
|
+
|
|
873
|
+
it('(d)', function() {
|
|
874
|
+
var p1 = promise.fulfilled();
|
|
875
|
+
var reason = {then: function() {}}; // A thenable like object.
|
|
876
|
+
return p1.then(function() {
|
|
877
|
+
throw reason;
|
|
878
|
+
}).then(assert.fail, function(e) {
|
|
879
|
+
assert.equal(reason, e);
|
|
880
|
+
});
|
|
805
881
|
});
|
|
806
882
|
});
|
|
807
883
|
});
|