Skip to content

Commit 3e9251d

Browse files
make testing builds for React/ReactDOM (facebook#17915)
This PR introduces adds `react/testing` and `react-dom/testing`. - changes infra to generate these builds - exports act on ReactDOM in these testing builds - uses the new test builds in fixtures/dom In the next PR - - I'll use the new builds for all our own tests - I'll replace usages of TestUtils.act with ReactDOM.act.
1 parent ace9e81 commit 3e9251d

26 files changed

+474
-494
lines changed

fixtures/dom/src/__tests__/nested-act-test.js

+12-7
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,23 @@
88
*/
99

1010
let React;
11-
let TestUtils;
11+
let ReactDOM;
1212
let TestRenderer;
1313

1414
global.__DEV__ = process.env.NODE_ENV !== 'production';
1515

16+
jest.mock('react-dom', () =>
17+
require.requireActual('react-dom/cjs/react-dom-testing.development.js')
18+
);
19+
// we'll replace the above with react/testing and react-dom/testing right before the next minor
20+
1621
expect.extend(require('../toWarnDev'));
1722

1823
describe('unmocked scheduler', () => {
1924
beforeEach(() => {
2025
jest.resetModules();
2126
React = require('react');
22-
TestUtils = require('react-dom/test-utils');
27+
ReactDOM = require('react-dom');
2328
TestRenderer = require('react-test-renderer');
2429
});
2530

@@ -33,7 +38,7 @@ describe('unmocked scheduler', () => {
3338
}
3439
// in legacy mode, this tests whether an act only flushes its own effects
3540
TestRenderer.act(() => {
36-
TestUtils.act(() => {
41+
ReactDOM.act(() => {
3742
TestRenderer.create(<Effecty />);
3843
});
3944
expect(log).toEqual([]);
@@ -42,7 +47,7 @@ describe('unmocked scheduler', () => {
4247

4348
log = [];
4449
// for doublechecking, we flip it inside out, and assert on the outermost
45-
TestUtils.act(() => {
50+
ReactDOM.act(() => {
4651
TestRenderer.act(() => {
4752
TestRenderer.create(<Effecty />);
4853
});
@@ -59,7 +64,7 @@ describe('mocked scheduler', () => {
5964
require.requireActual('scheduler/unstable_mock')
6065
);
6166
React = require('react');
62-
TestUtils = require('react-dom/test-utils');
67+
ReactDOM = require('react-dom');
6368
TestRenderer = require('react-test-renderer');
6469
});
6570

@@ -77,7 +82,7 @@ describe('mocked scheduler', () => {
7782
}
7883
// with a mocked scheduler, this tests whether it flushes all work only on the outermost act
7984
TestRenderer.act(() => {
80-
TestUtils.act(() => {
85+
ReactDOM.act(() => {
8186
TestRenderer.create(<Effecty />);
8287
});
8388
expect(log).toEqual([]);
@@ -86,7 +91,7 @@ describe('mocked scheduler', () => {
8691

8792
log = [];
8893
// for doublechecking, we flip it inside out, and assert on the outermost
89-
TestUtils.act(() => {
94+
ReactDOM.act(() => {
9095
TestRenderer.act(() => {
9196
TestRenderer.create(<Effecty />);
9297
});

fixtures/dom/src/__tests__/wrong-act-test.js

+16-13
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,17 @@ let ReactDOM;
1212
let ReactART;
1313
let ARTSVGMode;
1414
let ARTCurrentMode;
15-
let TestUtils;
1615
let TestRenderer;
1716
let ARTTest;
1817

1918
global.__DEV__ = process.env.NODE_ENV !== 'production';
2019
global.__EXPERIMENTAL__ = process.env.RELEASE_CHANNEL === 'experimental';
2120

21+
jest.mock('react-dom', () =>
22+
require.requireActual('react-dom/cjs/react-dom-testing.development.js')
23+
);
24+
// we'll replace the above with react/testing and react-dom/testing right before the next minor
25+
2226
expect.extend(require('../toWarnDev'));
2327

2428
function App(props) {
@@ -32,7 +36,6 @@ beforeEach(() => {
3236
ReactART = require('react-art');
3337
ARTSVGMode = require('art/modes/svg');
3438
ARTCurrentMode = require('art/modes/current');
35-
TestUtils = require('react-dom/test-utils');
3639
TestRenderer = require('react-test-renderer');
3740

3841
ARTCurrentMode.setCurrent(ARTSVGMode);
@@ -70,8 +73,8 @@ beforeEach(() => {
7073
});
7174

7275
it("doesn't warn when you use the right act + renderer: dom", () => {
73-
TestUtils.act(() => {
74-
TestUtils.renderIntoDocument(<App />);
76+
ReactDOM.act(() => {
77+
ReactDOM.render(<App />, document.createElement('div'));
7578
});
7679
});
7780

@@ -86,7 +89,7 @@ it('resets correctly across renderers', () => {
8689
React.useEffect(() => {}, []);
8790
return null;
8891
}
89-
TestUtils.act(() => {
92+
ReactDOM.act(() => {
9093
TestRenderer.act(() => {});
9194
expect(() => {
9295
TestRenderer.create(<Effecty />);
@@ -99,7 +102,7 @@ it('resets correctly across renderers', () => {
99102
it('warns when using the wrong act version - test + dom: render', () => {
100103
expect(() => {
101104
TestRenderer.act(() => {
102-
TestUtils.renderIntoDocument(<App />);
105+
ReactDOM.render(<App />, document.createElement('div'));
103106
});
104107
}).toWarnDev(["It looks like you're using the wrong act()"], {
105108
withoutStack: true,
@@ -113,7 +116,7 @@ it('warns when using the wrong act version - test + dom: updates', () => {
113116
setCtr = _setCtr;
114117
return ctr;
115118
}
116-
TestUtils.renderIntoDocument(<Counter />);
119+
ReactDOM.render(<Counter />, document.createElement('div'));
117120
expect(() => {
118121
TestRenderer.act(() => {
119122
setCtr(1);
@@ -123,7 +126,7 @@ it('warns when using the wrong act version - test + dom: updates', () => {
123126

124127
it('warns when using the wrong act version - dom + test: .create()', () => {
125128
expect(() => {
126-
TestUtils.act(() => {
129+
ReactDOM.act(() => {
127130
TestRenderer.create(<App />);
128131
});
129132
}).toWarnDev(["It looks like you're using the wrong act()"], {
@@ -134,7 +137,7 @@ it('warns when using the wrong act version - dom + test: .create()', () => {
134137
it('warns when using the wrong act version - dom + test: .update()', () => {
135138
const root = TestRenderer.create(<App key="one" />);
136139
expect(() => {
137-
TestUtils.act(() => {
140+
ReactDOM.act(() => {
138141
root.update(<App key="two" />);
139142
});
140143
}).toWarnDev(["It looks like you're using the wrong act()"], {
@@ -151,15 +154,15 @@ it('warns when using the wrong act version - dom + test: updates', () => {
151154
}
152155
TestRenderer.create(<Counter />);
153156
expect(() => {
154-
TestUtils.act(() => {
157+
ReactDOM.act(() => {
155158
setCtr(1);
156159
});
157160
}).toWarnDev(["It looks like you're using the wrong act()"]);
158161
});
159162

160163
it('does not warn when nesting react-act inside react-dom', () => {
161-
TestUtils.act(() => {
162-
TestUtils.renderIntoDocument(<ARTTest />);
164+
ReactDOM.act(() => {
165+
ReactDOM.render(<ARTTest />, document.createElement('div'));
163166
});
164167
});
165168

@@ -171,7 +174,7 @@ it('does not warn when nesting react-act inside react-test-renderer', () => {
171174

172175
it("doesn't warn if you use nested acts from different renderers", () => {
173176
TestRenderer.act(() => {
174-
TestUtils.act(() => {
177+
ReactDOM.act(() => {
175178
TestRenderer.create(<App />);
176179
});
177180
});

packages/react-dom/npm/testing.js

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
'use strict';
2+
3+
function checkDCE() {
4+
/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
5+
if (
6+
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined' ||
7+
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== 'function'
8+
) {
9+
return;
10+
}
11+
if (process.env.NODE_ENV !== 'production') {
12+
// This branch is unreachable because this function is only called
13+
// in production, but the condition is true only in development.
14+
// Therefore if the branch is still here, dead code elimination wasn't
15+
// properly applied.
16+
// Don't change the message. React DevTools relies on it. Also make sure
17+
// this message doesn't occur elsewhere in this function, or it will cause
18+
// a false positive.
19+
throw new Error('^_^');
20+
}
21+
try {
22+
// Verify that the code above has been dead code eliminated (DCE'd).
23+
__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(checkDCE);
24+
} catch (err) {
25+
// DevTools shouldn't crash React, no matter what.
26+
// We should still report in case we break this code.
27+
console.error(err);
28+
}
29+
}
30+
31+
if (process.env.NODE_ENV === 'production') {
32+
// DCE check should happen before ReactDOM bundle executes so that
33+
// DevTools can report bad minification during injection.
34+
checkDCE();
35+
module.exports = require('./cjs/react-dom-testing.production.min.js');
36+
} else {
37+
module.exports = require('./cjs/react-dom-testing.development.js');
38+
}

packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js

+1
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,7 @@ function runActTests(label, render, unmount, rerender) {
722722

723723
describe('suspense', () => {
724724
if (__DEV__ && __EXPERIMENTAL__) {
725+
// todo - remove __DEV__ check once we start using testing builds
725726
it('triggers fallbacks if available', async () => {
726727
let resolved = false;
727728
let resolve;

packages/react-dom/src/client/ReactDOM.js

+6
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {
3535
attemptUserBlockingHydration,
3636
attemptContinuousHydration,
3737
attemptHydrationAtCurrentPriority,
38+
act,
3839
} from 'react-reconciler/inline.dom';
3940
import {createPortal as createPortalImpl} from 'shared/ReactPortal';
4041
import {canUseDOM} from 'shared/ExecutionEnvironment';
@@ -58,6 +59,7 @@ import {
5859
disableUnstableCreatePortal,
5960
disableUnstableRenderSubtreeIntoContainer,
6061
warnUnstableRenderSubtreeIntoContainer,
62+
isTestEnvironment,
6163
} from 'shared/ReactFeatureFlags';
6264

6365
import {
@@ -251,4 +253,8 @@ if (__DEV__) {
251253
}
252254
}
253255

256+
if (isTestEnvironment) {
257+
ReactDOM.act = act;
258+
}
259+
254260
export default ReactDOM;

packages/react-dom/testing.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow
8+
*/
9+
10+
'use strict';
11+
12+
const ReactDOM = require('./src/client/ReactDOM');
13+
14+
// TODO: decide on the top-level export form.
15+
// This is hacky but makes it work with both Rollup and Jest.
16+
module.exports = ReactDOM.default || ReactDOM;

0 commit comments

Comments
 (0)