@@ -17,10 +17,13 @@ let Suspense;
17
17
let DiscreteEventPriority ;
18
18
let startTransition ;
19
19
let waitForMicrotasks ;
20
+ let Scheduler ;
21
+ let assertLog ;
20
22
21
23
describe ( 'isomorphic act()' , ( ) => {
22
24
beforeEach ( ( ) => {
23
25
React = require ( 'react' ) ;
26
+ Scheduler = require ( 'scheduler' ) ;
24
27
25
28
ReactNoop = require ( 'react-noop-renderer' ) ;
26
29
DiscreteEventPriority =
@@ -31,6 +34,7 @@ describe('isomorphic act()', () => {
31
34
startTransition = React . startTransition ;
32
35
33
36
waitForMicrotasks = require ( 'internal-test-utils' ) . waitForMicrotasks ;
37
+ assertLog = require ( 'internal-test-utils' ) . assertLog ;
34
38
} ) ;
35
39
36
40
beforeEach ( ( ) => {
@@ -41,6 +45,11 @@ describe('isomorphic act()', () => {
41
45
jest . restoreAllMocks ( ) ;
42
46
} ) ;
43
47
48
+ function Text ( { text} ) {
49
+ Scheduler . log ( text ) ;
50
+ return text ;
51
+ }
52
+
44
53
// @gate __DEV__
45
54
test ( 'bypasses queueMicrotask' , async ( ) => {
46
55
const root = ReactNoop . createRoot ( ) ;
@@ -132,19 +141,67 @@ describe('isomorphic act()', () => {
132
141
const root = ReactNoop . createLegacyRoot ( ) ;
133
142
134
143
await act ( async ( ) => {
135
- // These updates are batched. This replicates the behavior of the original
136
- // `act` implementation, for compatibility.
137
- root . render ( 'A' ) ;
138
- root . render ( 'B' ) ;
139
- // Nothing has rendered yet.
140
- expect ( root ) . toMatchRenderedOutput ( null ) ;
144
+ queueMicrotask ( ( ) => {
145
+ Scheduler . log ( 'Current tree in microtask: ' + root . getChildrenAsJSX ( ) ) ;
146
+ root . render ( < Text text = "C" /> ) ;
147
+ } ) ;
148
+ root . render ( < Text text = "A" /> ) ;
149
+ root . render ( < Text text = "B" /> ) ;
150
+
141
151
await null ;
142
- // Updates are flushed after the first await.
143
- expect ( root ) . toMatchRenderedOutput ( 'B' ) ;
152
+ assertLog ( [
153
+ // A and B should render in a single batch _before_ the microtask queue
154
+ // has run. This replicates the behavior of the original `act`
155
+ // implementation, for compatibility.
156
+ 'B' ,
157
+ 'Current tree in microtask: B' ,
158
+
159
+ // C isn't scheduled until a microtask, so it's rendered separately.
160
+ 'C' ,
161
+ ] ) ;
162
+
163
+ // Subsequent updates should also render in separate batches.
164
+ root . render ( < Text text = "D" /> ) ;
165
+ root . render ( < Text text = "E" /> ) ;
166
+ assertLog ( [ 'D' , 'E' ] ) ;
167
+ } ) ;
168
+ } ) ;
144
169
145
- // Subsequent updates in the same scope aren't batched.
146
- root . render ( 'C' ) ;
147
- expect ( root ) . toMatchRenderedOutput ( 'C' ) ;
170
+ // @gate __DEV__
171
+ test ( 'in legacy mode, in an async scope, updates are batched until the first `await` (regression test: batchedUpdates)' , async ( ) => {
172
+ const root = ReactNoop . createLegacyRoot ( ) ;
173
+
174
+ await act ( async ( ) => {
175
+ queueMicrotask ( ( ) => {
176
+ Scheduler . log ( 'Current tree in microtask: ' + root . getChildrenAsJSX ( ) ) ;
177
+ root . render ( < Text text = "C" /> ) ;
178
+ } ) ;
179
+
180
+ // This is a regression test. The presence of `batchedUpdates` would cause
181
+ // these updates to not flush until a microtask. The correct behavior is
182
+ // that they flush before the microtask queue, regardless of whether
183
+ // they are wrapped with `batchedUpdates`.
184
+ ReactNoop . batchedUpdates ( ( ) => {
185
+ root . render ( < Text text = "A" /> ) ;
186
+ root . render ( < Text text = "B" /> ) ;
187
+ } ) ;
188
+
189
+ await null ;
190
+ assertLog ( [
191
+ // A and B should render in a single batch _before_ the microtask queue
192
+ // has run. This replicates the behavior of the original `act`
193
+ // implementation, for compatibility.
194
+ 'B' ,
195
+ 'Current tree in microtask: B' ,
196
+
197
+ // C isn't scheduled until a microtask, so it's rendered separately.
198
+ 'C' ,
199
+ ] ) ;
200
+
201
+ // Subsequent updates should also render in separate batches.
202
+ root . render ( < Text text = "D" /> ) ;
203
+ root . render ( < Text text = "E" /> ) ;
204
+ assertLog ( [ 'D' , 'E' ] ) ;
148
205
} ) ;
149
206
} ) ;
150
207
0 commit comments