@@ -26,6 +26,7 @@ let useFormStatus;
2626let useOptimistic ;
2727let useActionState ;
2828let Scheduler ;
29+ let assertConsoleErrorDev ;
2930
3031describe ( 'ReactDOMFizzForm' , ( ) => {
3132 beforeEach ( ( ) => {
@@ -38,6 +39,8 @@ describe('ReactDOMFizzForm', () => {
3839 useFormStatus = require ( 'react-dom' ) . useFormStatus ;
3940 useOptimistic = require ( 'react' ) . useOptimistic ;
4041 act = require ( 'internal-test-utils' ) . act ;
42+ assertConsoleErrorDev =
43+ require ( 'internal-test-utils' ) . assertConsoleErrorDev ;
4144 container = document . createElement ( 'div' ) ;
4245 document . body . appendChild ( container ) ;
4346 // TODO: Test the old api but it warns so needs warnings to be asserted.
@@ -195,12 +198,26 @@ describe('ReactDOMFizzForm', () => {
195198 ReactDOMServer . renderToReadableStream ( < App /> ) ,
196199 ) ;
197200 await readIntoContainer ( stream ) ;
198- await expect ( async ( ) => {
199- await act ( async ( ) => {
200- ReactDOMClient . hydrateRoot ( container , < App isClient = { true } /> ) ;
201- } ) ;
202- } ) . toErrorDev (
203- "A tree hydrated but some attributes of the server rendered HTML didn't match the client properties." ,
201+ await act ( async ( ) => {
202+ ReactDOMClient . hydrateRoot ( container , < App isClient = { true } /> ) ;
203+ } ) ;
204+ assertConsoleErrorDev (
205+ [
206+ "A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. " +
207+ "This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n" +
208+ "- A server/client branch `if (typeof window !== 'undefined')`.\n" +
209+ "- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\n" +
210+ "- Date formatting in a user's locale which doesn't match the server.\n" +
211+ '- External changing data without sending a snapshot of it along with the HTML.\n' +
212+ '- Invalid HTML tag nesting.\n\n' +
213+ 'It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n' +
214+ 'https://react.dev/link/hydration-mismatch\n\n' +
215+ ' <App isClient={true}>\n' +
216+ ' <form\n' +
217+ '+ action="action"\n' +
218+ '- action="function"\n' +
219+ ' >\n' ,
220+ ] ,
204221 { withoutStack : true } ,
205222 ) ;
206223 } ) ;
@@ -357,23 +374,56 @@ describe('ReactDOMFizzForm', () => {
357374
358375 // Specifying the extra form fields are a DEV error, but we expect it
359376 // to eventually still be patched up after an update.
360- await expect ( async ( ) => {
361- const stream = await serverAct ( ( ) =>
362- ReactDOMServer . renderToReadableStream ( < App /> ) ,
363- ) ;
364- await readIntoContainer ( stream ) ;
365- } ) . toErrorDev ( [
366- 'Cannot specify a encType or method for a form that specifies a function as the action.' ,
367- 'Cannot specify a formTarget for a button that specifies a function as a formAction.' ,
377+ const stream = await serverAct ( ( ) =>
378+ ReactDOMServer . renderToReadableStream ( < App /> ) ,
379+ ) ;
380+ await readIntoContainer ( stream ) ;
381+ assertConsoleErrorDev ( [
382+ 'Cannot specify a encType or method for a form that specifies a function as the action. ' +
383+ 'React provides those automatically. They will get overridden.\n' +
384+ ' in form (at **)\n' +
385+ ' in App (at **)' ,
386+ 'Cannot specify a formTarget for a button that specifies a function as a formAction. ' +
387+ 'The function will always be executed in the same window.\n' +
388+ ' in input (at **)\n' +
389+ ( gate ( 'enableOwnerStacks' ) ? '' : ' in form (at **)\n' ) +
390+ ' in App (at **)' ,
368391 ] ) ;
369392 let root ;
370- await expect ( async ( ) => {
371- await act ( async ( ) => {
372- root = ReactDOMClient . hydrateRoot ( container , < App /> ) ;
373- } ) ;
374- } ) . toErrorDev (
393+ await act ( async ( ) => {
394+ root = ReactDOMClient . hydrateRoot ( container , < App /> ) ;
395+ } ) ;
396+ assertConsoleErrorDev (
375397 [
376- "A tree hydrated but some attributes of the server rendered HTML didn't match the client properties." ,
398+ "A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. " +
399+ "This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n" +
400+ "- A server/client branch `if (typeof window !== 'undefined')`.\n" +
401+ "- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\n" +
402+ "- Date formatting in a user's locale which doesn't match the server.\n" +
403+ '- External changing data without sending a snapshot of it along with the HTML.\n' +
404+ '- Invalid HTML tag nesting.\n\n' +
405+ 'It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n' +
406+ 'https://react.dev/link/hydration-mismatch\n\n' +
407+ ' <App>\n' +
408+ ' <form\n' +
409+ ' action={function action}\n' +
410+ ' ref={{current:null}}\n' +
411+ '+ method="DELETE"\n' +
412+ '- method={null}\n' +
413+ ' >\n' +
414+ ' <input\n' +
415+ ' type="submit"\n' +
416+ ' formAction={function action}\n' +
417+ ' ref={{current:null}}\n' +
418+ '+ formTarget="elsewhere"\n' +
419+ '- formTarget={null}\n' +
420+ ' >\n' +
421+ ' <button\n' +
422+ ' formAction={function action}\n' +
423+ ' ref={{current:null}}\n' +
424+ '+ formEncType="text/plain"\n' +
425+ '- formEncType={null}\n' +
426+ ' >\n' ,
377427 ] ,
378428 { withoutStack : true } ,
379429 ) ;
0 commit comments