@@ -181,11 +181,7 @@ const createMatcherFor = (consoleMethod, matcherName) =>
181
181
// Avoid using Jest's built-in spy since it can't be removed.
182
182
console [ consoleMethod ] = consoleSpy
183
183
184
- try {
185
- callback ( )
186
- } catch ( error ) {
187
- caughtError = error
188
- } finally {
184
+ const onFinally = ( ) => {
189
185
// Restore the unspied method so that unexpected errors fail tests.
190
186
console [ consoleMethod ] = originalMethod
191
187
@@ -289,11 +285,56 @@ const createMatcherFor = (consoleMethod, matcherName) =>
289
285
290
286
return { pass : true }
291
287
}
288
+
289
+ let returnPromise = null
290
+ try {
291
+ const result = callback ( )
292
+
293
+ if (
294
+ typeof result === 'object' &&
295
+ result !== null &&
296
+ typeof result . then === 'function'
297
+ ) {
298
+ // `act` returns a thenable that can't be chained.
299
+ // Once `act(async () => {}).then(() => {}).then(() => {})` works
300
+ // we can just return `result.then(onFinally, error => ...)`
301
+ returnPromise = new Promise ( ( resolve , reject ) => {
302
+ result
303
+ . then (
304
+ ( ) => {
305
+ resolve ( onFinally ( ) )
306
+ } ,
307
+ error => {
308
+ caughtError = error
309
+ return resolve ( onFinally ( ) )
310
+ } ,
311
+ )
312
+ // In case onFinally throws we need to reject from this matcher
313
+ . catch ( error => {
314
+ reject ( error )
315
+ } )
316
+ } )
317
+ }
318
+ } catch ( error ) {
319
+ caughtError = error
320
+ } finally {
321
+ return returnPromise === null ? onFinally ( ) : returnPromise
322
+ }
292
323
} else {
293
324
// Any uncaught errors or warnings should fail tests in production mode.
294
- callback ( )
325
+ const result = callback ( )
295
326
296
- return { pass : true }
327
+ if (
328
+ typeof result === 'object' &&
329
+ result !== null &&
330
+ typeof result . then === 'function'
331
+ ) {
332
+ return result . then ( ( ) => {
333
+ return { pass : true }
334
+ } )
335
+ } else {
336
+ return { pass : true }
337
+ }
297
338
}
298
339
}
299
340
0 commit comments