/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment */ 'use strict'; let React; let ReactDOMClient; let ReactDOMServer; let act; const util = require('util'); const realConsoleError = console.error; function errorHandler() { // forward to console.error but don't fail the tests } describe('ReactDOMServerHydration', () => { let container; let ownerStacks; beforeEach(() => { jest.resetModules(); React = require('react'); ReactDOMClient = require('react-dom/client'); ReactDOMServer = require('react-dom/server'); act = React.act; window.addEventListener('error', errorHandler); ownerStacks = []; console.error = jest.fn(() => { const ownerStack = React.captureOwnerStack(); if (typeof ownerStack === 'string') { ownerStacks.push(ownerStack === '' ? ' ' : ownerStack); } else { ownerStacks.push(' ' + String(ownerStack)); } }); container = document.createElement('div'); document.body.appendChild(container); }); afterEach(() => { jest.restoreAllMocks(); window.removeEventListener('error', errorHandler); document.body.removeChild(container); console.error = realConsoleError; }); function normalizeCodeLocInfo(str) { return typeof str === 'string' ? str.replace(/\n +(?:at|in) ([\S]+)[^\n]*/g, function (m, name) { return '\n in ' + name + ' (at **)'; }) : str; } function formatMessage(args, index) { const ownerStack = ownerStacks[index]; if (ownerStack === undefined) { throw new Error( 'Expected an owner stack for message ' + index + ':\n' + util.format(...args), ); } const [format, ...rest] = args; if (format instanceof Error) { if (format.cause instanceof Error) { return ( 'Caught [' + format.message + ']\n Cause [' + format.cause.message + ']\n Owner Stack:' + normalizeCodeLocInfo(ownerStack) ); } return ( 'Caught [' + format.message + ']\n Owner Stack:' + normalizeCodeLocInfo(ownerStack) ); } rest[rest.length - 1] = normalizeCodeLocInfo(rest[rest.length - 1]); return ( util.format(format, ...rest) + '\n Owner Stack:' + normalizeCodeLocInfo(ownerStack) ); } function formatConsoleErrors() { return console.error.mock.calls.map(formatMessage).filter(Boolean); } function testMismatch(Mismatch) { const htmlString = ReactDOMServer.renderToString( , ); container.innerHTML = htmlString; act(() => { ReactDOMClient.hydrateRoot(container, ); }); return formatConsoleErrors(); } describe('text mismatch', () => { // @gate __DEV__ it('warns when client and server render different text', () => { function Mismatch({isClient}) { return (
{isClient ? 'client' : 'server'}
); } expect(testMismatch(Mismatch)).toMatchInlineSnapshot(` [ "Caught [Hydration failed because the server rendered text didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used: - A server/client branch \`if (typeof window !== 'undefined')\`. - Variable input such as \`Date.now()\` or \`Math.random()\` which changes each time it's called. - Date formatting in a user's locale which doesn't match the server. - External changing data without sending a snapshot of it along with the HTML. - Invalid HTML tag nesting. It can also happen if the client has a browser extension installed which messes with the HTML before React loaded. https://react.dev/link/hydration-mismatch
+ client - server ] Owner Stack: in main (at **) in Mismatch (at **)", ] `); }); // @gate __DEV__ it('warns when escaping on a checksum mismatch', () => { function Mismatch({isClient}) { if (isClient) { return (
This markup contains an nbsp entity:   client text
); } return (
This markup contains an nbsp entity:   server text
); } /* eslint-disable no-irregular-whitespace */ expect(testMismatch(Mismatch)).toMatchInlineSnapshot(` [ "Caught [Hydration failed because the server rendered text didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used: - A server/client branch \`if (typeof window !== 'undefined')\`. - Variable input such as \`Date.now()\` or \`Math.random()\` which changes each time it's called. - Date formatting in a user's locale which doesn't match the server. - External changing data without sending a snapshot of it along with the HTML. - Invalid HTML tag nesting. It can also happen if the client has a browser extension installed which messes with the HTML before React loaded. https://react.dev/link/hydration-mismatch
+ This markup contains an nbsp entity:   client text - This markup contains an nbsp entity:   server text ] Owner Stack: in div (at **) in Mismatch (at **)", ] `); /* eslint-enable no-irregular-whitespace */ }); // @gate __DEV__ it('warns when client and server render different html', () => { function Mismatch({isClient}) { return (
client' : 'server', }} />
); } expect(testMismatch(Mismatch)).toMatchInlineSnapshot(` [ "A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used: - A server/client branch \`if (typeof window !== 'undefined')\`. - Variable input such as \`Date.now()\` or \`Math.random()\` which changes each time it's called. - Date formatting in a user's locale which doesn't match the server. - External changing data without sending a snapshot of it along with the HTML. - Invalid HTML tag nesting. It can also happen if the client has a browser extension installed which messes with the HTML before React loaded. https://react.dev/link/hydration-mismatch
client" - __html: "server" }} > Owner Stack: in main (at **) in Mismatch (at **)", ] `); }); }); describe('attribute mismatch', () => { // @gate __DEV__ it('warns when client and server render different attributes', () => { function Mismatch({isClient}) { return (
); } expect(testMismatch(Mismatch)).toMatchInlineSnapshot(` [ "A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used: - A server/client branch \`if (typeof window !== 'undefined')\`. - Variable input such as \`Date.now()\` or \`Math.random()\` which changes each time it's called. - Date formatting in a user's locale which doesn't match the server. - External changing data without sending a snapshot of it along with the HTML. - Invalid HTML tag nesting. It can also happen if the client has a browser extension installed which messes with the HTML before React loaded. https://react.dev/link/hydration-mismatch
Owner Stack: in main (at **) in Mismatch (at **)", ] `); }); // @gate __DEV__ it('warns when client renders extra attributes', () => { function Mismatch({isClient}) { return (
); } expect(testMismatch(Mismatch)).toMatchInlineSnapshot(` [ "A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used: - A server/client branch \`if (typeof window !== 'undefined')\`. - Variable input such as \`Date.now()\` or \`Math.random()\` which changes each time it's called. - Date formatting in a user's locale which doesn't match the server. - External changing data without sending a snapshot of it along with the HTML. - Invalid HTML tag nesting. It can also happen if the client has a browser extension installed which messes with the HTML before React loaded. https://react.dev/link/hydration-mismatch
Owner Stack: in main (at **) in Mismatch (at **)", ] `); }); // @gate __DEV__ it('warns when server renders extra attributes', () => { function Mismatch({isClient}) { return (
); } expect(testMismatch(Mismatch)).toMatchInlineSnapshot(` [ "A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used: - A server/client branch \`if (typeof window !== 'undefined')\`. - Variable input such as \`Date.now()\` or \`Math.random()\` which changes each time it's called. - Date formatting in a user's locale which doesn't match the server. - External changing data without sending a snapshot of it along with the HTML. - Invalid HTML tag nesting. It can also happen if the client has a browser extension installed which messes with the HTML before React loaded. https://react.dev/link/hydration-mismatch
Owner Stack: in main (at **) in Mismatch (at **)", ] `); }); // @gate __DEV__ it('warns when both client and server render extra attributes', () => { function Mismatch({isClient}) { return (
); } expect(testMismatch(Mismatch)).toMatchInlineSnapshot(` [ "A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used: - A server/client branch \`if (typeof window !== 'undefined')\`. - Variable input such as \`Date.now()\` or \`Math.random()\` which changes each time it's called. - Date formatting in a user's locale which doesn't match the server. - External changing data without sending a snapshot of it along with the HTML. - Invalid HTML tag nesting. It can also happen if the client has a browser extension installed which messes with the HTML before React loaded. https://react.dev/link/hydration-mismatch
Owner Stack: in main (at **) in Mismatch (at **)", ] `); }); // @gate __DEV__ it('warns when client and server render different styles', () => { function Mismatch({isClient}) { return (
); } expect(testMismatch(Mismatch)).toMatchInlineSnapshot(` [ "A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used: - A server/client branch \`if (typeof window !== 'undefined')\`. - Variable input such as \`Date.now()\` or \`Math.random()\` which changes each time it's called. - Date formatting in a user's locale which doesn't match the server. - External changing data without sending a snapshot of it along with the HTML. - Invalid HTML tag nesting. It can also happen if the client has a browser extension installed which messes with the HTML before React loaded. https://react.dev/link/hydration-mismatch
Owner Stack: in main (at **) in Mismatch (at **)", ] `); }); // @gate __DEV__ it('picks the DFS-first Fiber as the error Owner', () => { function LeftMismatch({isClient}) { return
; } function LeftIndirection({isClient}) { return ; } function MiddleMismatch({isClient}) { return ; } function RightMisMatch({isClient}) { return

; } function App({isClient}) { return ( <> ); } expect(testMismatch(App)).toMatchInlineSnapshot(` [ "A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used: - A server/client branch \`if (typeof window !== 'undefined')\`. - Variable input such as \`Date.now()\` or \`Math.random()\` which changes each time it's called. - Date formatting in a user's locale which doesn't match the server. - External changing data without sending a snapshot of it along with the HTML. - Invalid HTML tag nesting. It can also happen if the client has a browser extension installed which messes with the HTML before React loaded. https://react.dev/link/hydration-mismatch

Owner Stack: in div (at **) in LeftMismatch (at **) in LeftIndirection (at **) in App (at **)", ] `); }); describe('nonce', () => { // Nonce is on HTMLOrSVGElement, so cover a few host tags that hydrate // attributes through getValueForAttribute. function App() { return (