[Internal API only] Delete non-awaited form of act (#26339)
**This commit only affects the internal version of `act` that we use in this repo. The public `act` API is unaffected, for now.** We should always await the result of an `act` call so that any work queued in a microtask has a chance to flush. Neglecting to do this can cause us to miss bugs when testing React behavior. I codemodded all the existing `act` callers in previous PRs.
Andrew Clark committed
Mar 8, 2023 at 11:46 UTC
d8144730475cf2d71781e26e300d0d579ac6b8d9
1 file changed
+35
-48
packages/jest-react/src/internalAct.js
+35
-48
@@ -22,7 +22,7 @@ import enqueueTask from 'shared/enqueueTask';
22
23
let actingUpdatesScopeDepth = 0;
24
25
-export function act<T>(scope: () => Thenable<T> | T): Thenable<T> {
25
+export function act<T>(scope: () => Thenable<T>): Thenable<T> {
26
if (Scheduler.unstable_flushUntilNextPaint === undefined) {
27
throw Error(
28
'This version of `act` requires a special mock build of Scheduler.',
@@ -64,58 +64,45 @@ export function act<T>(scope: () => Thenable<T> | T): Thenable<T> {
64
}
65
};
66
67
- // TODO: This would be way simpler if 1) we required a promise to be
68
- // returned and 2) we could use async/await. Since it's only our used in
69
- // our test suite, we should be able to.
67
+ // TODO: This would be way simpler if we could use async/await. Move this
68
+ // function to the internal-test-utils package.
69
try {
70
const result = scope();
71
if (
73
- typeof result === 'object' &&
74
- result !== null &&
75
- // $FlowFixMe[method-unbinding]
76
- typeof result.then === 'function'
72
+ typeof result !== 'object' ||
73
+ result === null ||
74
+ typeof (result: any).then !== 'function'
75
) {
78
- const thenableResult: Thenable<T> = (result: any);
79
- return {
80
- then(resolve: T => mixed, reject: mixed => mixed) {
81
- thenableResult.then(
82
- returnValue => {
83
- flushActWork(
84
- () => {
85
- unwind();
86
- resolve(returnValue);
87
- },
88
- error => {
89
- unwind();
90
- reject(error);
91
- },
92
- );
93
- },
94
- error => {
95
- unwind();
96
- reject(error);
97
- },
98
- );
99
- },
100
- };
101
- } else {
102
- const returnValue: T = (result: any);
103
- try {
104
- // TODO: Let's not support non-async scopes at all in our tests. Need to
105
- // migrate existing tests.
106
- let didFlushWork;
107
- do {
108
- didFlushWork = Scheduler.unstable_flushAllWithoutAsserting();
109
- } while (didFlushWork);
110
- return {
111
- then(resolve: T => mixed, reject: mixed => mixed) {
112
- resolve(returnValue);
113
- },
114
- };
115
- } finally {
116
- unwind();
117
- }
76
+ throw new Error(
77
+ 'The internal version of `act` used in the React repo must be passed ' +
78
+ "an async function, even if doesn't await anything. This is a " +
79
+ 'temporary limitation that will soon be fixed.',
80
+ );
81
}
82
+ const thenableResult: Thenable<T> = (result: any);
83
+
84
+ return {
85
+ then(resolve: T => mixed, reject: mixed => mixed) {
86
+ thenableResult.then(
87
+ returnValue => {
88
+ flushActWork(
89
+ () => {
90
+ unwind();
91
+ resolve(returnValue);
92
+ },
93
+ error => {
94
+ unwind();
95
+ reject(error);
96
+ },
97
+ );
98
+ },
99
+ error => {
100
+ unwind();
101
+ reject(error);
102
+ },
103
+ );
104
+ },
105
+ };
106
} catch (error) {
107
unwind();
108
throw error;