diff --git a/.circleci/config.yml b/.circleci/config.yml index 5cbc3a3fa6a20..13487ea0508e7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,7 @@ version: 2.1 executors: my-executor: docker: - - image: circleci/openjdk:8-jdk-node-browsers + - image: circleci/openjdk:jdk-node-browsers working_directory: /tmp jobs: @@ -76,8 +76,6 @@ jobs: command: cd workspace && yarn lightyear:build workflows: - version: 2 - validate: jobs: - install diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json new file mode 100644 index 0000000000000..7dd2a59e41457 --- /dev/null +++ b/.codesandbox/ci.json @@ -0,0 +1,10 @@ +{ + "packages": ["packages/react", "packages/react-dom", "packages/scheduler"], + "buildCommand": "build --type=NODE react/index,react-dom/index,scheduler/index,scheduler/tracing", + "publishDirectory": { + "react": "build/node_modules/react", + "react-dom": "build/node_modules/react-dom", + "scheduler": "build/node_modules/scheduler" + }, + "sandboxes": ["new"] +} diff --git a/.eslintrc.js b/.eslintrc.js index 603f20a3cacba..98bbab2367deb 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -5,11 +5,13 @@ const { esNextPaths, } = require('./scripts/shared/pathsByLanguageVersion'); +const restrictedGlobals = require('confusing-browser-globals'); + const OFF = 0; const ERROR = 2; module.exports = { - extends: 'fbjs', + extends: ['fbjs', 'prettier'], // Stop ESLint from looking for a configuration file in parent folders root: true, @@ -30,10 +32,10 @@ module.exports = { rules: { 'accessor-pairs': OFF, 'brace-style': [ERROR, '1tbs'], - 'comma-dangle': [ERROR, 'always-multiline'], 'consistent-return': OFF, 'dot-location': [ERROR, 'property'], - 'dot-notation': ERROR, + // We use console['error']() as a signal to not transform it: + 'dot-notation': [ERROR, {allowPattern: '^(error|warn)$'}], 'eol-last': ERROR, eqeqeq: [ERROR, 'allow-null'], indent: OFF, @@ -42,6 +44,7 @@ module.exports = { 'no-bitwise': OFF, 'no-inner-declarations': [ERROR, 'functions'], 'no-multi-spaces': ERROR, + 'no-restricted-globals': [ERROR].concat(restrictedGlobals), 'no-restricted-syntax': [ERROR, 'WithStatement'], 'no-shadow': ERROR, 'no-unused-expressions': ERROR, @@ -92,7 +95,9 @@ module.exports = { // the second argument of warning/invariant should be a literal string 'react-internal/no-primitive-constructors': ERROR, 'react-internal/no-to-warn-dev-within-to-throw': ERROR, - 'react-internal/warning-and-invariant-args': ERROR, + 'react-internal/invariant-args': ERROR, + 'react-internal/warning-args': ERROR, + 'react-internal/no-production-logging': OFF, }, overrides: [ @@ -133,6 +138,19 @@ module.exports = { 'jest/valid-expect-in-promise': ERROR, }, }, + { + files: [ + '**/__tests__/**/*.js', + 'scripts/**/*.js', + 'packages/*/npm/**/*.js', + 'packages/dom-event-testing-library/**/*.js', + 'packages/react-devtools*/**/*.js', + ], + rules: { + 'react-internal/no-production-logging': OFF, + 'react-internal/warning-args': OFF, + }, + }, { files: ['packages/react-native-renderer/**/*.js'], globals: { @@ -149,6 +167,7 @@ module.exports = { spyOnProd: true, __PROFILE__: true, __UMD__: true, + __EXPERIMENTAL__: true, trustedTypes: true, }, }; diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000000..e561f9d26154a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,41 @@ +--- +name: "🐛 Bug Report" +about: Report a reproducible bug or regression. +title: 'Bug: ' +labels: 'Status: Unconfirmed' + +--- + + + +React version: + +## Steps To Reproduce + +1. +2. + + + +Link to code example: + + + +## The current behavior + + +## The expected behavior diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000000..e5bb31b2b3787 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,7 @@ +contact_links: + - name: 📃 Documentation Issue + url: https://github.com/reactjs/reactjs.org/issues/new + about: This issue tracker is not for documentation issues. Please file documentation issues here. + - name: 🤔 Questions and Help + url: https://reactjs.org/community/support.html + about: This issue tracker is not for support questions. Please refer to the React community's help and discussion forums. diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 0000000000000..6dc44693e3ece --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,31 @@ +# Configuration for probot-stale - https://github.com/probot/stale +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 90 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 7 +# Issues with these labels will never be considered stale +exemptLabels: + - "Partner" + - "React Core Team" + - "Resolution: Backlog" + - "Type: Bug" + - "Type: Discussion" + - "Type: Regression" +# Label to use when marking an issue as stale +staleLabel: "Resolution: Stale" +issues: + # Comment to post when marking an issue as stale. + markComment: > + This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. + Thank you for your contribution. + # Comment to post when closing a stale issue. + closeComment: > + Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you! +pulls: + # Comment to post when marking a pull request as stale. + markComment: > + This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. + Thank you for your contribution. + # Comment to post when closing a stale pull request. + closeComment: > + Closing this pull request after a prolonged period of inactivity. If this issue is still present in the latest release, please ask for this pull request to be reopened. Thank you! diff --git a/.mailmap b/.mailmap index 278784e0afa9b..86c96fe683ed6 100644 --- a/.mailmap +++ b/.mailmap @@ -88,6 +88,7 @@ Kevin Coughlin Krystian Karczewski Kunal Mehta Laurence Rowe +Lea Rosema Marcin K. Mark Anderson Mark Funk diff --git a/.prettierrc.js b/.prettierrc.js index df8d863ae4c09..6e5dcb710f0f0 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -8,7 +8,7 @@ module.exports = { jsxBracketSameLine: true, trailingComma: 'es5', printWidth: 80, - parser: 'babylon', + parser: 'babel', overrides: [ { diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000000..655dfeaec0e67 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,7 @@ +# Reporting Security Issues + +If you believe you have found a security vulnerability in React, we encourage you to let us know right away. We will investigate all legitimate reports and do our best to quickly fix the problem. + +Please refer to the following page for our responsible disclosure policy, reward guidelines, and those things that should not be reported: + +https://www.facebook.com/whitehat diff --git a/dangerfile.js b/dangerfile.js index 985c6b675626d..86e7e422a5b40 100644 --- a/dangerfile.js +++ b/dangerfile.js @@ -32,6 +32,14 @@ const {generateResultsArray} = require('./scripts/rollup/stats'); const {existsSync, readFileSync} = require('fs'); const {exec} = require('child_process'); +// This must match the name of the CI job that creates the build artifacts +const RELEASE_CHANNEL = + process.env.RELEASE_CHANNEL === 'experimental' ? 'experimental' : 'stable'; +const artifactsJobName = + process.env.RELEASE_CHANNEL === 'experimental' + ? 'process_artifacts_experimental' + : 'process_artifacts'; + if (!existsSync('./build/bundle-sizes.json')) { // This indicates the build failed previously. // In that case, there's nothing for the Dangerfile to do. @@ -117,6 +125,8 @@ function git(args) { return; } + markdown(`## Size changes (${RELEASE_CHANNEL})`); + const upstreamRef = danger.github.pr.base.ref; await git(`remote add upstream https://github.com/facebook/react.git`); await git('fetch upstream'); @@ -135,8 +145,7 @@ function git(args) { } for (let i = 0; i < statuses.length; i++) { const status = statuses[i]; - // This must match the name of the CI job that creates the build artifacts - if (status.context === 'ci/circleci: process_artifacts') { + if (status.context === `ci/circleci: ${artifactsJobName}`) { if (status.state === 'success') { baseCIBuildId = /\/facebook\/react\/([0-9]+)/.exec( status.target_url @@ -162,7 +171,7 @@ function git(args) { for (let i = 0; i < baseArtifactsInfo.length; i++) { const info = baseArtifactsInfo[i]; - if (info.path === 'home/circleci/project/build/bundle-sizes.json') { + if (info.path.endsWith('bundle-sizes.json')) { const resultsResponse = await fetch(info.url); previousBuildResults = await resultsResponse.json(); break; diff --git a/examples/react-apollo-hooks/src/index.js b/examples/react-apollo-hooks/src/index.js index 901931fe26973..f4acb10b0e220 100644 --- a/examples/react-apollo-hooks/src/index.js +++ b/examples/react-apollo-hooks/src/index.js @@ -26,7 +26,7 @@ if (module.hot) { server.on('request', app); currentApp = app; } catch (error) { - console.error(error); + console.error('Error starting example: %s', error); } }); } diff --git a/examples/redux/src/index.js b/examples/redux/src/index.js index 901931fe26973..f4acb10b0e220 100644 --- a/examples/redux/src/index.js +++ b/examples/redux/src/index.js @@ -26,7 +26,7 @@ if (module.hot) { server.on('request', app); currentApp = app; } catch (error) { - console.error(error); + console.error('Error starting example: %s', error); } }); } diff --git a/examples/urql/src/index.js b/examples/urql/src/index.js index 901931fe26973..f4acb10b0e220 100644 --- a/examples/urql/src/index.js +++ b/examples/urql/src/index.js @@ -26,7 +26,7 @@ if (module.hot) { server.on('request', app); currentApp = app; } catch (error) { - console.error(error); + console.error('Error starting example: %s', error); } }); } diff --git a/fixtures/attribute-behavior/src/App.js b/fixtures/attribute-behavior/src/App.js index 3764349b958a7..7cb678b587389 100644 --- a/fixtures/attribute-behavior/src/App.js +++ b/fixtures/attribute-behavior/src/App.js @@ -461,9 +461,7 @@ function prepareState(initGlobals) { hasSameBehaviorForAll, rowPatternHash, // "Good enough" id that we can store in localStorage - rowIdHash: `${attribute.name} ${attribute.tagName} ${ - attribute.overrideStringValue - }`, + rowIdHash: `${attribute.name} ${attribute.tagName} ${attribute.overrideStringValue}`, }; const rowGroup = rowPatternHashes.get(rowPatternHash) || new Set(); rowGroup.add(row); @@ -866,14 +864,12 @@ class App extends React.Component { // Sort switch (sortOrder) { case ALPHABETICAL: - return filteredAttributes.sort( - (attr1, attr2) => - attr1.name.toLowerCase() < attr2.name.toLowerCase() ? -1 : 1 + return filteredAttributes.sort((attr1, attr2) => + attr1.name.toLowerCase() < attr2.name.toLowerCase() ? -1 : 1 ); case REV_ALPHABETICAL: - return filteredAttributes.sort( - (attr1, attr2) => - attr1.name.toLowerCase() < attr2.name.toLowerCase() ? 1 : -1 + return filteredAttributes.sort((attr1, attr2) => + attr1.name.toLowerCase() < attr2.name.toLowerCase() ? 1 : -1 ); case GROUPED_BY_ROW_PATTERN: { return filteredAttributes.sort((attr1, attr2) => { diff --git a/fixtures/attribute-behavior/yarn.lock b/fixtures/attribute-behavior/yarn.lock index d4dff15fb03cc..f97911b5e4993 100644 --- a/fixtures/attribute-behavior/yarn.lock +++ b/fixtures/attribute-behavior/yarn.lock @@ -268,7 +268,7 @@ async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" -async@^1.4.0, async@^1.5.2: +async@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" @@ -1448,6 +1448,10 @@ commander@2.11.x, commander@~2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" +commander@~2.20.3: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -2838,14 +2842,14 @@ handle-thing@^1.2.5: resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4" handlebars@^4.0.3: - version "4.0.10" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.10.tgz#3d30c718b09a3d96f23ea4cc1f403c4d3ba9ff4f" + version "4.5.3" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482" dependencies: - async "^1.4.0" + neo-async "^2.6.0" optimist "^0.6.1" - source-map "^0.4.4" + source-map "^0.6.1" optionalDependencies: - uglify-js "^2.6" + uglify-js "^3.1.4" har-schema@^1.0.5: version "1.0.5" @@ -4180,6 +4184,10 @@ negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" +neo-async@^2.6.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" + no-case@^2.2.0: version "2.3.1" resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.1.tgz#7aeba1c73a52184265554b7dc03baf720df80081" @@ -5696,11 +5704,9 @@ source-map@0.5.x, source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, sourc version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" -source-map@^0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" - dependencies: - amdefine ">=0.0.4" +source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" source-map@~0.2.0: version "0.2.0" @@ -6090,7 +6096,7 @@ uglify-js@3.0.x, uglify-js@^3.0.13: commander "~2.11.0" source-map "~0.5.1" -uglify-js@^2.6, uglify-js@^2.8.29: +uglify-js@^2.8.29: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" dependencies: @@ -6099,6 +6105,13 @@ uglify-js@^2.6, uglify-js@^2.8.29: optionalDependencies: uglify-to-browserify "~1.0.0" +uglify-js@^3.1.4: + version "3.7.3" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.3.tgz#f918fce9182f466d5140f24bb0ff35c2d32dcc6a" + dependencies: + commander "~2.20.3" + source-map "~0.6.1" + uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" diff --git a/fixtures/unstable-async/time-slicing/.gitignore b/fixtures/concurrent/time-slicing/.gitignore similarity index 100% rename from fixtures/unstable-async/time-slicing/.gitignore rename to fixtures/concurrent/time-slicing/.gitignore diff --git a/fixtures/unstable-async/time-slicing/README.md b/fixtures/concurrent/time-slicing/README.md similarity index 100% rename from fixtures/unstable-async/time-slicing/README.md rename to fixtures/concurrent/time-slicing/README.md diff --git a/fixtures/unstable-async/time-slicing/package.json b/fixtures/concurrent/time-slicing/package.json similarity index 100% rename from fixtures/unstable-async/time-slicing/package.json rename to fixtures/concurrent/time-slicing/package.json diff --git a/fixtures/unstable-async/time-slicing/public/favicon.ico b/fixtures/concurrent/time-slicing/public/favicon.ico similarity index 100% rename from fixtures/unstable-async/time-slicing/public/favicon.ico rename to fixtures/concurrent/time-slicing/public/favicon.ico diff --git a/fixtures/unstable-async/time-slicing/public/index.html b/fixtures/concurrent/time-slicing/public/index.html similarity index 100% rename from fixtures/unstable-async/time-slicing/public/index.html rename to fixtures/concurrent/time-slicing/public/index.html diff --git a/fixtures/unstable-async/time-slicing/public/manifest.json b/fixtures/concurrent/time-slicing/public/manifest.json similarity index 100% rename from fixtures/unstable-async/time-slicing/public/manifest.json rename to fixtures/concurrent/time-slicing/public/manifest.json diff --git a/fixtures/unstable-async/time-slicing/src/Charts.js b/fixtures/concurrent/time-slicing/src/Charts.js similarity index 100% rename from fixtures/unstable-async/time-slicing/src/Charts.js rename to fixtures/concurrent/time-slicing/src/Charts.js diff --git a/fixtures/unstable-async/time-slicing/src/Clock.js b/fixtures/concurrent/time-slicing/src/Clock.js similarity index 100% rename from fixtures/unstable-async/time-slicing/src/Clock.js rename to fixtures/concurrent/time-slicing/src/Clock.js diff --git a/fixtures/unstable-async/time-slicing/src/index.css b/fixtures/concurrent/time-slicing/src/index.css similarity index 100% rename from fixtures/unstable-async/time-slicing/src/index.css rename to fixtures/concurrent/time-slicing/src/index.css diff --git a/fixtures/unstable-async/time-slicing/src/index.js b/fixtures/concurrent/time-slicing/src/index.js similarity index 94% rename from fixtures/unstable-async/time-slicing/src/index.js rename to fixtures/concurrent/time-slicing/src/index.js index dc8890617229f..40c19442e3511 100644 --- a/fixtures/unstable-async/time-slicing/src/index.js +++ b/fixtures/concurrent/time-slicing/src/index.js @@ -1,5 +1,5 @@ import React, {PureComponent} from 'react'; -import {flushSync, unstable_createRoot} from 'react-dom'; +import {flushSync, createRoot} from 'react-dom'; import Scheduler from 'scheduler'; import _ from 'lodash'; import Charts from './Charts'; @@ -107,9 +107,10 @@ class App extends PureComponent { this.debouncedHandleChange(value); break; case 'async': - unstable_scheduleCallback(() => { + // TODO: useTransition hook instead. + setTimeout(() => { this.setState({value}); - }); + }, 0); break; default: break; @@ -146,5 +147,5 @@ class App extends PureComponent { } const container = document.getElementById('root'); -const root = ReactDOM.unstable_createRoot(container); -root.render(, container); +const root = createRoot(container); +root.render(); diff --git a/fixtures/unstable-async/time-slicing/yarn.lock b/fixtures/concurrent/time-slicing/yarn.lock similarity index 100% rename from fixtures/unstable-async/time-slicing/yarn.lock rename to fixtures/concurrent/time-slicing/yarn.lock diff --git a/fixtures/dom/package.json b/fixtures/dom/package.json index 484d96ea088f2..bacf1325fa15c 100644 --- a/fixtures/dom/package.json +++ b/fixtures/dom/package.json @@ -11,7 +11,7 @@ "classnames": "^2.2.5", "codemirror": "^5.40.0", "core-js": "^2.4.1", - "jest-diff": "^24.8.0", + "jest-diff": "^25.1.0", "prop-types": "^15.6.0", "query-string": "^4.2.3", "react": "^15.4.1", diff --git a/fixtures/dom/src/__tests__/nested-act-test.js b/fixtures/dom/src/__tests__/nested-act-test.js index a0500f47e9603..c7a191943abdf 100644 --- a/fixtures/dom/src/__tests__/nested-act-test.js +++ b/fixtures/dom/src/__tests__/nested-act-test.js @@ -8,18 +8,23 @@ */ let React; -let TestUtils; +let ReactDOM; let TestRenderer; global.__DEV__ = process.env.NODE_ENV !== 'production'; +jest.mock('react-dom', () => + require.requireActual('react-dom/cjs/react-dom-testing.development.js') +); +// we'll replace the above with react/testing and react-dom/testing right before the next minor + expect.extend(require('../toWarnDev')); describe('unmocked scheduler', () => { beforeEach(() => { jest.resetModules(); React = require('react'); - TestUtils = require('react-dom/test-utils'); + ReactDOM = require('react-dom'); TestRenderer = require('react-test-renderer'); }); @@ -33,7 +38,7 @@ describe('unmocked scheduler', () => { } // in legacy mode, this tests whether an act only flushes its own effects TestRenderer.act(() => { - TestUtils.act(() => { + ReactDOM.act(() => { TestRenderer.create(); }); expect(log).toEqual([]); @@ -42,7 +47,7 @@ describe('unmocked scheduler', () => { log = []; // for doublechecking, we flip it inside out, and assert on the outermost - TestUtils.act(() => { + ReactDOM.act(() => { TestRenderer.act(() => { TestRenderer.create(); }); @@ -59,7 +64,7 @@ describe('mocked scheduler', () => { require.requireActual('scheduler/unstable_mock') ); React = require('react'); - TestUtils = require('react-dom/test-utils'); + ReactDOM = require('react-dom'); TestRenderer = require('react-test-renderer'); }); @@ -77,7 +82,7 @@ describe('mocked scheduler', () => { } // with a mocked scheduler, this tests whether it flushes all work only on the outermost act TestRenderer.act(() => { - TestUtils.act(() => { + ReactDOM.act(() => { TestRenderer.create(); }); expect(log).toEqual([]); @@ -86,7 +91,7 @@ describe('mocked scheduler', () => { log = []; // for doublechecking, we flip it inside out, and assert on the outermost - TestUtils.act(() => { + ReactDOM.act(() => { TestRenderer.act(() => { TestRenderer.create(); }); diff --git a/fixtures/dom/src/__tests__/wrong-act-test.js b/fixtures/dom/src/__tests__/wrong-act-test.js index 05dda494d1126..10df65ce6df60 100644 --- a/fixtures/dom/src/__tests__/wrong-act-test.js +++ b/fixtures/dom/src/__tests__/wrong-act-test.js @@ -12,11 +12,16 @@ let ReactDOM; let ReactART; let ARTSVGMode; let ARTCurrentMode; -let TestUtils; let TestRenderer; let ARTTest; global.__DEV__ = process.env.NODE_ENV !== 'production'; +global.__EXPERIMENTAL__ = process.env.RELEASE_CHANNEL === 'experimental'; + +jest.mock('react-dom', () => + require.requireActual('react-dom/cjs/react-dom-testing.development.js') +); +// we'll replace the above with react/testing and react-dom/testing right before the next minor expect.extend(require('../toWarnDev')); @@ -31,7 +36,6 @@ beforeEach(() => { ReactART = require('react-art'); ARTSVGMode = require('art/modes/svg'); ARTCurrentMode = require('art/modes/current'); - TestUtils = require('react-dom/test-utils'); TestRenderer = require('react-test-renderer'); ARTCurrentMode.setCurrent(ARTSVGMode); @@ -69,8 +73,8 @@ beforeEach(() => { }); it("doesn't warn when you use the right act + renderer: dom", () => { - TestUtils.act(() => { - TestUtils.renderIntoDocument(); + ReactDOM.act(() => { + ReactDOM.render(, document.createElement('div')); }); }); @@ -85,7 +89,7 @@ it('resets correctly across renderers', () => { React.useEffect(() => {}, []); return null; } - TestUtils.act(() => { + ReactDOM.act(() => { TestRenderer.act(() => {}); expect(() => { TestRenderer.create(); @@ -98,7 +102,7 @@ it('resets correctly across renderers', () => { it('warns when using the wrong act version - test + dom: render', () => { expect(() => { TestRenderer.act(() => { - TestUtils.renderIntoDocument(); + ReactDOM.render(, document.createElement('div')); }); }).toWarnDev(["It looks like you're using the wrong act()"], { withoutStack: true, @@ -112,7 +116,7 @@ it('warns when using the wrong act version - test + dom: updates', () => { setCtr = _setCtr; return ctr; } - TestUtils.renderIntoDocument(); + ReactDOM.render(, document.createElement('div')); expect(() => { TestRenderer.act(() => { setCtr(1); @@ -122,7 +126,7 @@ it('warns when using the wrong act version - test + dom: updates', () => { it('warns when using the wrong act version - dom + test: .create()', () => { expect(() => { - TestUtils.act(() => { + ReactDOM.act(() => { TestRenderer.create(); }); }).toWarnDev(["It looks like you're using the wrong act()"], { @@ -133,7 +137,7 @@ it('warns when using the wrong act version - dom + test: .create()', () => { it('warns when using the wrong act version - dom + test: .update()', () => { const root = TestRenderer.create(); expect(() => { - TestUtils.act(() => { + ReactDOM.act(() => { root.update(); }); }).toWarnDev(["It looks like you're using the wrong act()"], { @@ -150,15 +154,15 @@ it('warns when using the wrong act version - dom + test: updates', () => { } TestRenderer.create(); expect(() => { - TestUtils.act(() => { + ReactDOM.act(() => { setCtr(1); }); }).toWarnDev(["It looks like you're using the wrong act()"]); }); it('does not warn when nesting react-act inside react-dom', () => { - TestUtils.act(() => { - TestUtils.renderIntoDocument(); + ReactDOM.act(() => { + ReactDOM.render(, document.createElement('div')); }); }); @@ -170,25 +174,27 @@ it('does not warn when nesting react-act inside react-test-renderer', () => { it("doesn't warn if you use nested acts from different renderers", () => { TestRenderer.act(() => { - TestUtils.act(() => { + ReactDOM.act(() => { TestRenderer.create(); }); }); }); -it('warns when using createRoot() + .render', () => { - const root = ReactDOM.unstable_createRoot(document.createElement('div')); - expect(() => { - TestRenderer.act(() => { - root.render(); - }); - }).toWarnDev( - [ - 'In Concurrent or Sync modes, the "scheduler" module needs to be mocked', - "It looks like you're using the wrong act()", - ], - { - withoutStack: true, - } - ); -}); +if (__EXPERIMENTAL__) { + it('warns when using createRoot() + .render', () => { + const root = ReactDOM.createRoot(document.createElement('div')); + expect(() => { + TestRenderer.act(() => { + root.render(); + }); + }).toWarnDev( + [ + 'In Concurrent or Sync modes, the "scheduler" module needs to be mocked', + "It looks like you're using the wrong act()", + ], + { + withoutStack: true, + } + ); + }); +} diff --git a/fixtures/dom/src/components/Header.js b/fixtures/dom/src/components/Header.js index 74af700e27662..77c1ecfc30da6 100644 --- a/fixtures/dom/src/components/Header.js +++ b/fixtures/dom/src/components/Header.js @@ -86,6 +86,7 @@ class Header extends React.Component { +