diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationCheckbox-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationCheckbox-test.js index 606ec88b8989..178ed7982a44 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationCheckbox-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationCheckbox-test.js @@ -15,7 +15,7 @@ const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegratio const {disableInputAttributeSyncing} = require('shared/ReactFeatureFlags'); let React; -let ReactDOM; +let ReactDOMClient; let ReactDOMServer; let ReactTestUtils; @@ -23,13 +23,13 @@ function initModules() { // Reset warning cache. jest.resetModules(); React = require('react'); - ReactDOM = require('react-dom'); + ReactDOMClient = require('react-dom/client'); ReactDOMServer = require('react-dom/server'); ReactTestUtils = require('react-dom/test-utils'); // Make them available to the helpers. return { - ReactDOM, + ReactDOMClient, ReactDOMServer, ReactTestUtils, }; diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationClassContextType-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationClassContextType-test.js index dda475b7ced3..2df2d66b9b9f 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationClassContextType-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationClassContextType-test.js @@ -13,7 +13,7 @@ const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils'); let React; -let ReactDOM; +let ReactDOMClient; let ReactDOMServer; let ReactTestUtils; @@ -21,13 +21,13 @@ function initModules() { // Reset warning cache. jest.resetModules(); React = require('react'); - ReactDOM = require('react-dom'); + ReactDOMClient = require('react-dom/client'); ReactDOMServer = require('react-dom/server'); ReactTestUtils = require('react-dom/test-utils'); // Make them available to the helpers. return { - ReactDOM, + ReactDOMClient, ReactDOMServer, ReactTestUtils, }; diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationFragment-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationFragment-test.js index 680f283b6dbf..8e8fc2aa8fe2 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationFragment-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationFragment-test.js @@ -13,7 +13,7 @@ const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils'); let React; -let ReactDOM; +let ReactDOMClient; let ReactDOMServer; let ReactTestUtils; @@ -21,13 +21,13 @@ function initModules() { // Reset warning cache. jest.resetModules(); React = require('react'); - ReactDOM = require('react-dom'); + ReactDOMClient = require('react-dom/client'); ReactDOMServer = require('react-dom/server'); ReactTestUtils = require('react-dom/test-utils'); // Make them available to the helpers. return { - ReactDOM, + ReactDOMClient, ReactDOMServer, ReactTestUtils, }; diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationInput-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationInput-test.js index afbbf28a41ec..54780dae52cd 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationInput-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationInput-test.js @@ -15,7 +15,7 @@ const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegratio const {disableInputAttributeSyncing} = require('shared/ReactFeatureFlags'); let React; -let ReactDOM; +let ReactDOMClient; let ReactDOMServer; let ReactTestUtils; @@ -23,13 +23,13 @@ function initModules() { // Reset warning cache. jest.resetModules(); React = require('react'); - ReactDOM = require('react-dom'); + ReactDOMClient = require('react-dom/client'); ReactDOMServer = require('react-dom/server'); ReactTestUtils = require('react-dom/test-utils'); // Make them available to the helpers. return { - ReactDOM, + ReactDOMClient, ReactDOMServer, ReactTestUtils, }; diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationModes-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationModes-test.js index e551a72b9ace..99cf33b821f1 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationModes-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationModes-test.js @@ -13,7 +13,7 @@ const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils'); let React; -let ReactDOM; +let ReactDOMClient; let ReactDOMServer; let ReactTestUtils; @@ -21,13 +21,13 @@ function initModules() { // Reset warning cache. jest.resetModules(); React = require('react'); - ReactDOM = require('react-dom'); + ReactDOMClient = require('react-dom/client'); ReactDOMServer = require('react-dom/server'); ReactTestUtils = require('react-dom/test-utils'); // Make them available to the helpers. return { - ReactDOM, + ReactDOMClient, ReactDOMServer, ReactTestUtils, }; diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationReconnecting-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationReconnecting-test.js index eb201c17b484..76612f510d7d 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationReconnecting-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationReconnecting-test.js @@ -13,30 +13,30 @@ const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegratio let React; let ReactDOM; +let ReactDOMClient; let ReactDOMServer; let ReactTestUtils; -function initModules() { - // Reset warning cache. - jest.resetModules(); - - React = require('react'); - ReactDOM = require('react-dom'); - ReactDOMServer = require('react-dom/server'); - ReactTestUtils = require('react-dom/test-utils'); - - // Make them available to the helpers. - return { - ReactDOM, - ReactDOMServer, - ReactTestUtils, - }; -} - -const {resetModules, expectMarkupMismatch, expectMarkupMatch} = - ReactDOMServerIntegrationUtils(initModules); - describe('ReactDOMServerIntegration', () => { + function initModules() { + // Reset warning cache. + jest.resetModules(); + + React = require('react'); + ReactDOMClient = require('react-dom/client'); + ReactDOMServer = require('react-dom/server'); + ReactTestUtils = require('react-dom/test-utils'); + + // Make them available to the helpers. + return { + ReactDOMClient, + ReactDOMServer, + ReactTestUtils, + }; + } + + const {resetModules, expectMarkupMismatch, expectMarkupMatch} = + ReactDOMServerIntegrationUtils(initModules); beforeEach(() => { resetModules(); }); @@ -123,8 +123,8 @@ describe('ReactDOMServerIntegration', () => { it('should error reconnecting different attribute values', () => expectMarkupMismatch(
,
)); - it('can explicitly ignore errors reconnecting different element types of children', () => - expectMarkupMatch( + it('should error reconnecting different element types of children', () => + expectMarkupMismatch(
, @@ -354,8 +354,8 @@ describe('ReactDOMServerIntegration', () => {
{''}
, )); - it('can explicitly ignore reconnecting more children', () => - expectMarkupMatch( + it('can not ignore reconnecting more children', () => + expectMarkupMismatch(
, @@ -365,8 +365,8 @@ describe('ReactDOMServerIntegration', () => {
, )); - it('can explicitly ignore reconnecting fewer children', () => - expectMarkupMatch( + it('can not ignore reconnecting fewer children', () => + expectMarkupMismatch(
@@ -376,8 +376,8 @@ describe('ReactDOMServerIntegration', () => {
, )); - it('can explicitly ignore reconnecting reordered children', () => - expectMarkupMatch( + it('can not ignore reconnecting reordered children', () => + expectMarkupMismatch(
@@ -456,3 +456,73 @@ describe('ReactDOMServerIntegration', () => { )); }); }); + +describe('ReactDOMServerIntegration (legacy)', () => { + function initModules() { + // Reset warning cache. + jest.resetModules(); + + React = require('react'); + ReactDOM = require('react-dom'); + ReactDOMServer = require('react-dom/server'); + ReactTestUtils = require('react-dom/test-utils'); + + // Make them available to the helpers. + return { + ReactDOM, + ReactDOMServer, + ReactTestUtils, + }; + } + + const {resetModules, expectMarkupMatch} = + ReactDOMServerIntegrationUtils(initModules); + + beforeEach(() => { + resetModules(); + }); + + it('legacy mode can explicitly ignore errors reconnecting different element types of children', () => + expectMarkupMatch( +
+
+
, +
+ +
, + )); + + it('legacy mode can explicitly ignore reconnecting more children', () => + expectMarkupMatch( +
+
+
, +
+
+
+
, + )); + + it('legacy mode can explicitly ignore reconnecting fewer children', () => + expectMarkupMatch( +
+
+
+
, +
+
+
, + )); + + it('legacy mode can explicitly ignore reconnecting reordered children', () => + expectMarkupMatch( +
+
+ +
, +
+ +
+
, + )); +}); diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationRefs-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationRefs-test.js index 76da3e92c82a..e5564d3d9348 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationRefs-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationRefs-test.js @@ -12,7 +12,7 @@ const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils'); let React; -let ReactDOM; +let ReactDOMClient; let ReactDOMServer; let ReactTestUtils; @@ -20,13 +20,13 @@ function initModules() { // Reset warning cache. jest.resetModules(); React = require('react'); - ReactDOM = require('react-dom'); + ReactDOMClient = require('react-dom/client'); ReactDOMServer = require('react-dom/server'); ReactTestUtils = require('react-dom/test-utils'); // Make them available to the helpers. return { - ReactDOM, + ReactDOMClient, ReactDOMServer, ReactTestUtils, }; diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationSpecialTypes-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationSpecialTypes-test.js index f3a8b869ad81..8ea1c9d53bae 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationSpecialTypes-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationSpecialTypes-test.js @@ -13,7 +13,7 @@ const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils'); let React; -let ReactDOM; +let ReactDOMClient; let ReactDOMServer; let ReactTestUtils; let forwardRef; @@ -26,7 +26,7 @@ function initModules() { // Reset warning cache. jest.resetModules(); React = require('react'); - ReactDOM = require('react-dom'); + ReactDOMClient = require('react-dom/client'); ReactDOMServer = require('react-dom/server'); ReactTestUtils = require('react-dom/test-utils'); forwardRef = React.forwardRef; @@ -44,7 +44,7 @@ function initModules() { // Make them available to the helpers. return { - ReactDOM, + ReactDOMClient, ReactDOMServer, ReactTestUtils, }; diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationTextarea-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationTextarea-test.js index 697ec7f340d8..dd19385e62c5 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationTextarea-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationTextarea-test.js @@ -13,7 +13,7 @@ const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils'); let React; -let ReactDOM; +let ReactDOMClient; let ReactDOMServer; let ReactTestUtils; @@ -21,13 +21,13 @@ function initModules() { // Reset warning cache. jest.resetModules(); React = require('react'); - ReactDOM = require('react-dom'); + ReactDOMClient = require('react-dom/client'); ReactDOMServer = require('react-dom/server'); ReactTestUtils = require('react-dom/test-utils'); // Make them available to the helpers. return { - ReactDOM, + ReactDOMClient, ReactDOMServer, ReactTestUtils, }; diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationUserInteraction-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationUserInteraction-test.js index b335b03b01d3..bc5980f23dda 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationUserInteraction-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationUserInteraction-test.js @@ -12,7 +12,7 @@ const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils'); let React; -let ReactDOM; +let ReactDOMClient; let ReactDOMServer; let ReactTestUtils; @@ -20,13 +20,13 @@ function initModules() { // Reset warning cache. jest.resetModules(); React = require('react'); - ReactDOM = require('react-dom'); + ReactDOMClient = require('react-dom/client'); ReactDOMServer = require('react-dom/server'); ReactTestUtils = require('react-dom/test-utils'); // Make them available to the helpers. return { - ReactDOM, + ReactDOMClient, ReactDOMServer, ReactTestUtils, }; diff --git a/packages/react-dom/src/__tests__/ReactDOMserverIntegrationProgress-test.js b/packages/react-dom/src/__tests__/ReactDOMserverIntegrationProgress-test.js index b949e0ab522f..cf51eff4aced 100644 --- a/packages/react-dom/src/__tests__/ReactDOMserverIntegrationProgress-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMserverIntegrationProgress-test.js @@ -13,7 +13,7 @@ const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils'); let React; -let ReactDOM; +let ReactDOMClient; let ReactDOMServer; let ReactTestUtils; @@ -21,13 +21,13 @@ function initModules() { // Reset warning cache. jest.resetModules(); React = require('react'); - ReactDOM = require('react-dom'); + ReactDOMClient = require('react-dom/client'); ReactDOMServer = require('react-dom/server'); ReactTestUtils = require('react-dom/test-utils'); // Make them available to the helpers. return { - ReactDOM, + ReactDOMClient, ReactDOMServer, ReactTestUtils, }; diff --git a/packages/react-dom/src/__tests__/utils/ReactDOMServerIntegrationTestUtils.js b/packages/react-dom/src/__tests__/utils/ReactDOMServerIntegrationTestUtils.js index 8392b57af03c..e9c4479b028f 100644 --- a/packages/react-dom/src/__tests__/utils/ReactDOMServerIntegrationTestUtils.js +++ b/packages/react-dom/src/__tests__/utils/ReactDOMServerIntegrationTestUtils.js @@ -14,11 +14,12 @@ const shouldIgnoreConsoleError = require('../../../../../scripts/jest/shouldIgno module.exports = function (initModules) { let ReactDOM; + let ReactDOMClient; let ReactDOMServer; let act; function resetModules() { - ({ReactDOM, ReactDOMServer} = initModules()); + ({ReactDOM, ReactDOMClient, ReactDOMServer} = initModules()); act = require('internal-test-utils').act; } @@ -51,11 +52,24 @@ module.exports = function (initModules) { async function asyncReactDOMRender(reactElement, domElement, forceHydrate) { if (forceHydrate) { await act(() => { - ReactDOM.hydrate(reactElement, domElement); + if (ReactDOMClient) { + ReactDOMClient.hydrateRoot(domElement, reactElement, { + onRecoverableError: () => { + // TODO: assert on recoverable error count. + }, + }); + } else { + ReactDOM.hydrate(reactElement, domElement); + } }); } else { await act(() => { - ReactDOM.render(reactElement, domElement); + if (ReactDOMClient) { + const root = ReactDOMClient.createRoot(domElement); + root.render(reactElement); + } else { + ReactDOM.render(reactElement, domElement); + } }); } } @@ -80,7 +94,11 @@ module.exports = function (initModules) { for (let i = 0; i < console.error.mock.calls.length; i++) { const args = console.error.mock.calls[i]; const [format, ...rest] = args; - if (!shouldIgnoreConsoleError(format, rest)) { + if ( + !shouldIgnoreConsoleError(format, rest, { + TODO_ignoreHydrationErrors: true, + }) + ) { filteredWarnings.push(args); } } diff --git a/scripts/jest/shouldIgnoreConsoleError.js b/scripts/jest/shouldIgnoreConsoleError.js index 42aae220debe..79ec7fc2ad7d 100644 --- a/scripts/jest/shouldIgnoreConsoleError.js +++ b/scripts/jest/shouldIgnoreConsoleError.js @@ -1,6 +1,10 @@ 'use strict'; -module.exports = function shouldIgnoreConsoleError(format, args) { +module.exports = function shouldIgnoreConsoleError( + format, + args, + {TODO_ignoreHydrationErrors} = {TODO_ignoreHydrationErrors: false} +) { if (__DEV__) { if (typeof format === 'string') { if (format.indexOf('Error: Uncaught [') === 0) { @@ -23,6 +27,15 @@ module.exports = function shouldIgnoreConsoleError(format, args) { // We haven't finished migrating our tests to use createRoot. return true; } + if ( + TODO_ignoreHydrationErrors && + format.indexOf( + 'An error occurred during hydration. The server HTML was replaced with client content in' + ) !== -1 + ) { + // This also gets logged by onRecoverableError, so we can ignore it. + return true; + } } else if ( format != null && typeof format.message === 'string' &&