@@ -18,6 +18,7 @@ let Suspense;
1818let startTransition ;
1919let getCacheForType ;
2020let caches ;
21+ let assertConsoleErrorDev ;
2122
2223// These tests are mostly concerned with concurrent roots. The legacy root
2324// behavior is covered by other older test suites and is unchanged from
@@ -38,6 +39,7 @@ describe('act warnings', () => {
3839 const InternalTestUtils = require ( 'internal-test-utils' ) ;
3940 waitForAll = InternalTestUtils . waitForAll ;
4041 assertLog = InternalTestUtils . assertLog ;
42+ assertConsoleErrorDev = InternalTestUtils . assertConsoleErrorDev ;
4143 } ) ;
4244
4345 function createTextCache ( ) {
@@ -171,9 +173,21 @@ describe('act warnings', () => {
171173
172174 // Flag is true. Warn.
173175 await withActEnvironment ( true , async ( ) => {
174- expect ( ( ) => setState ( 2 ) ) . toErrorDev (
175- 'An update to App inside a test was not wrapped in act' ,
176- ) ;
176+ setState ( 2 ) ;
177+ assertConsoleErrorDev ( [
178+ 'An update to App inside a test was not wrapped in act(...).\n' +
179+ '\n' +
180+ 'When testing, code that causes React state updates should be wrapped into act(...):\n' +
181+ '\n' +
182+ 'act(() => {\n' +
183+ ' /* fire events that update state */\n' +
184+ '});\n' +
185+ '/* assert on the output */\n' +
186+ '\n' +
187+ "This ensures that you're testing the behavior the user would see in the browser. " +
188+ 'Learn more at https://react.dev/link/wrap-tests-with-act\n' +
189+ ' in App (at **)' ,
190+ ] ) ;
177191 await waitForAll ( [ 2 ] ) ;
178192 expect ( root ) . toMatchRenderedOutput ( '2' ) ;
179193 } ) ;
@@ -202,12 +216,11 @@ describe('act warnings', () => {
202216
203217 // Default behavior. Flag is undefined. Warn.
204218 expect ( global . IS_REACT_ACT_ENVIRONMENT ) . toBe ( undefined ) ;
205- expect ( ( ) => {
206- act ( ( ) => {
207- setState ( 1 ) ;
208- } ) ;
209- } ) . toErrorDev (
210- 'The current testing environment is not configured to support act(...)' ,
219+ act ( ( ) => {
220+ setState ( 1 ) ;
221+ } ) ;
222+ assertConsoleErrorDev (
223+ [ 'The current testing environment is not configured to support act(...)' ] ,
211224 { withoutStack : true } ,
212225 ) ;
213226 assertLog ( [ 1 ] ) ;
@@ -224,12 +237,13 @@ describe('act warnings', () => {
224237
225238 // Flag is false. Warn.
226239 await withActEnvironment ( false , ( ) => {
227- expect ( ( ) => {
228- act ( ( ) => {
229- setState ( 1 ) ;
230- } ) ;
231- } ) . toErrorDev (
232- 'The current testing environment is not configured to support act(...)' ,
240+ act ( ( ) => {
241+ setState ( 1 ) ;
242+ } ) ;
243+ assertConsoleErrorDev (
244+ [
245+ 'The current testing environment is not configured to support act(...)' ,
246+ ] ,
233247 { withoutStack : true } ,
234248 ) ;
235249 assertLog ( [ 1 ] ) ;
@@ -240,10 +254,23 @@ describe('act warnings', () => {
240254 it ( 'warns if root update is not wrapped' , async ( ) => {
241255 await withActEnvironment ( true , ( ) => {
242256 const root = ReactNoop . createRoot ( ) ;
243- expect ( ( ) => root . render ( 'Hi' ) ) . toErrorDev (
244- // TODO: Better error message that doesn't make it look like "Root" is
245- // the name of a custom component
246- 'An update to Root inside a test was not wrapped in act(...)' ,
257+ root . render ( 'Hi' ) ;
258+ assertConsoleErrorDev (
259+ [
260+ // TODO: Better error message that doesn't make it look like "Root" is
261+ // the name of a custom component
262+ 'An update to Root inside a test was not wrapped in act(...).\n' +
263+ '\n' +
264+ 'When testing, code that causes React state updates should be wrapped into act(...):\n' +
265+ '\n' +
266+ 'act(() => {\n' +
267+ ' /* fire events that update state */\n' +
268+ '});\n' +
269+ '/* assert on the output */\n' +
270+ '\n' +
271+ "This ensures that you're testing the behavior the user would see in the browser. " +
272+ 'Learn more at https://react.dev/link/wrap-tests-with-act' ,
273+ ] ,
247274 { withoutStack : true } ,
248275 ) ;
249276 } ) ;
@@ -265,9 +292,21 @@ describe('act warnings', () => {
265292 act ( ( ) => {
266293 root . render ( < App /> ) ;
267294 } ) ;
268- expect ( ( ) => app . setState ( { count : 1 } ) ) . toErrorDev (
269- 'An update to App inside a test was not wrapped in act(...)' ,
270- ) ;
295+ app . setState ( { count : 1 } ) ;
296+ assertConsoleErrorDev ( [
297+ 'An update to App inside a test was not wrapped in act(...).\n' +
298+ '\n' +
299+ 'When testing, code that causes React state updates should be wrapped into act(...):\n' +
300+ '\n' +
301+ 'act(() => {\n' +
302+ ' /* fire events that update state */\n' +
303+ '});\n' +
304+ '/* assert on the output */\n' +
305+ '\n' +
306+ "This ensures that you're testing the behavior the user would see in the browser. " +
307+ 'Learn more at https://react.dev/link/wrap-tests-with-act\n' +
308+ ' in App (at **)' ,
309+ ] ) ;
271310 } ) ;
272311 } ) ;
273312
@@ -288,9 +327,21 @@ describe('act warnings', () => {
288327
289328 // Even though this update is synchronous, we should still fire a warning,
290329 // because it could have spawned additional asynchronous work
291- expect ( ( ) => ReactNoop . flushSync ( ( ) => setState ( 1 ) ) ) . toErrorDev (
292- 'An update to App inside a test was not wrapped in act(...)' ,
293- ) ;
330+ ReactNoop . flushSync ( ( ) => setState ( 1 ) ) ;
331+ assertConsoleErrorDev ( [
332+ 'An update to App inside a test was not wrapped in act(...).\n' +
333+ '\n' +
334+ 'When testing, code that causes React state updates should be wrapped into act(...):\n' +
335+ '\n' +
336+ 'act(() => {\n' +
337+ ' /* fire events that update state */\n' +
338+ '});\n' +
339+ '/* assert on the output */\n' +
340+ '\n' +
341+ "This ensures that you're testing the behavior the user would see in the browser. " +
342+ 'Learn more at https://react.dev/link/wrap-tests-with-act\n' +
343+ ' in App (at **)' ,
344+ ] ) ;
294345
295346 assertLog ( [ 1 ] ) ;
296347 expect ( root ) . toMatchRenderedOutput ( '1' ) ;
@@ -322,12 +373,36 @@ describe('act warnings', () => {
322373 expect ( root ) . toMatchRenderedOutput ( 'Loading...' ) ;
323374
324375 // This is a retry, not a ping, because we already showed a fallback.
325- expect ( ( ) => resolveText ( 'Async' ) ) . toErrorDev (
376+ resolveText ( 'Async' ) ;
377+ assertConsoleErrorDev (
326378 [
327- 'A suspended resource finished loading inside a test, but the event ' +
328- 'was not wrapped in act(...)' ,
329-
330- ...( gate ( 'enableSiblingPrerendering' ) ? [ 'not wrapped in act' ] : [ ] ) ,
379+ 'A suspended resource finished loading inside a test, but the event was not wrapped in act(...).\n' +
380+ '\n' +
381+ 'When testing, code that resolves suspended data should be wrapped into act(...):\n' +
382+ '\n' +
383+ 'act(() => {\n' +
384+ ' /* finish loading suspended data */\n' +
385+ '});\n' +
386+ '/* assert on the output */\n' +
387+ '\n' +
388+ "This ensures that you're testing the behavior the user would see in the browser. " +
389+ 'Learn more at https://react.dev/link/wrap-tests-with-act' ,
390+
391+ ...( gate ( 'enableSiblingPrerendering' )
392+ ? [
393+ 'A suspended resource finished loading inside a test, but the event was not wrapped in act(...).\n' +
394+ '\n' +
395+ 'When testing, code that resolves suspended data should be wrapped into act(...):\n' +
396+ '\n' +
397+ 'act(() => {\n' +
398+ ' /* finish loading suspended data */\n' +
399+ '});\n' +
400+ '/* assert on the output */\n' +
401+ '\n' +
402+ "This ensures that you're testing the behavior the user would see in the browser. " +
403+ 'Learn more at https://react.dev/link/wrap-tests-with-act' ,
404+ ]
405+ : [ ] ) ,
331406 ] ,
332407
333408 { withoutStack : true } ,
@@ -363,9 +438,21 @@ describe('act warnings', () => {
363438 expect ( root ) . toMatchRenderedOutput ( '(empty)' ) ;
364439
365440 // This is a ping, not a retry, because no fallback is showing.
366- expect ( ( ) => resolveText ( 'Async' ) ) . toErrorDev (
367- 'A suspended resource finished loading inside a test, but the event ' +
368- 'was not wrapped in act(...)' ,
441+ resolveText ( 'Async' ) ;
442+ assertConsoleErrorDev (
443+ [
444+ 'A suspended resource finished loading inside a test, but the event was not wrapped in act(...).\n' +
445+ '\n' +
446+ 'When testing, code that resolves suspended data should be wrapped into act(...):\n' +
447+ '\n' +
448+ 'act(() => {\n' +
449+ ' /* finish loading suspended data */\n' +
450+ '});\n' +
451+ '/* assert on the output */\n' +
452+ '\n' +
453+ "This ensures that you're testing the behavior the user would see in the browser. " +
454+ 'Learn more at https://react.dev/link/wrap-tests-with-act' ,
455+ ] ,
369456 { withoutStack : true } ,
370457 ) ;
371458 } ) ;
0 commit comments