Skip to content

Commit ce33146

Browse files
committed
make testing builds for React/ReactDOM
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 434770c commit ce33146

26 files changed

+491
-494
lines changed

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

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,26 @@
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', () =>
17+
require.requireActual('react/cjs/react-testing.development.js')
18+
);
19+
jest.mock('react-dom', () =>
20+
require.requireActual('react-dom/cjs/react-dom-testing.development.js')
21+
);
22+
// we'll replace the above with react/testing and react-dom/testing right before the next minor
23+
1624
expect.extend(require('../toWarnDev'));
1725

1826
describe('unmocked scheduler', () => {
1927
beforeEach(() => {
2028
jest.resetModules();
2129
React = require('react');
22-
TestUtils = require('react-dom/test-utils');
30+
ReactDOM = require('react-dom');
2331
TestRenderer = require('react-test-renderer');
2432
});
2533

@@ -33,7 +41,7 @@ describe('unmocked scheduler', () => {
3341
}
3442
// in legacy mode, this tests whether an act only flushes its own effects
3543
TestRenderer.act(() => {
36-
TestUtils.act(() => {
44+
ReactDOM.act(() => {
3745
TestRenderer.create(<Effecty />);
3846
});
3947
expect(log).toEqual([]);
@@ -42,7 +50,7 @@ describe('unmocked scheduler', () => {
4250

4351
log = [];
4452
// for doublechecking, we flip it inside out, and assert on the outermost
45-
TestUtils.act(() => {
53+
ReactDOM.act(() => {
4654
TestRenderer.act(() => {
4755
TestRenderer.create(<Effecty />);
4856
});
@@ -59,7 +67,7 @@ describe('mocked scheduler', () => {
5967
require.requireActual('scheduler/unstable_mock')
6068
);
6169
React = require('react');
62-
TestUtils = require('react-dom/test-utils');
70+
ReactDOM = require('react-dom');
6371
TestRenderer = require('react-test-renderer');
6472
});
6573

@@ -77,7 +85,7 @@ describe('mocked scheduler', () => {
7785
}
7886
// with a mocked scheduler, this tests whether it flushes all work only on the outermost act
7987
TestRenderer.act(() => {
80-
TestUtils.act(() => {
88+
ReactDOM.act(() => {
8189
TestRenderer.create(<Effecty />);
8290
});
8391
expect(log).toEqual([]);
@@ -86,7 +94,7 @@ describe('mocked scheduler', () => {
8694

8795
log = [];
8896
// for doublechecking, we flip it inside out, and assert on the outermost
89-
TestUtils.act(() => {
97+
ReactDOM.act(() => {
9098
TestRenderer.act(() => {
9199
TestRenderer.create(<Effecty />);
92100
});

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

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,20 @@ 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', () =>
22+
require.requireActual('react/cjs/react-testing.development.js')
23+
);
24+
jest.mock('react-dom', () =>
25+
require.requireActual('react-dom/cjs/react-dom-testing.development.js')
26+
);
27+
// we'll replace the above with react/testing and react-dom/testing right before the next minor
28+
2229
expect.extend(require('../toWarnDev'));
2330

2431
function App(props) {
@@ -32,7 +39,6 @@ beforeEach(() => {
3239
ReactART = require('react-art');
3340
ARTSVGMode = require('art/modes/svg');
3441
ARTCurrentMode = require('art/modes/current');
35-
TestUtils = require('react-dom/test-utils');
3642
TestRenderer = require('react-test-renderer');
3743

3844
ARTCurrentMode.setCurrent(ARTSVGMode);
@@ -70,8 +76,8 @@ beforeEach(() => {
7076
});
7177

7278
it("doesn't warn when you use the right act + renderer: dom", () => {
73-
TestUtils.act(() => {
74-
TestUtils.renderIntoDocument(<App />);
79+
ReactDOM.act(() => {
80+
ReactDOM.render(<App />, document.createElement('div'));
7581
});
7682
});
7783

@@ -86,7 +92,7 @@ it('resets correctly across renderers', () => {
8692
React.useEffect(() => {}, []);
8793
return null;
8894
}
89-
TestUtils.act(() => {
95+
ReactDOM.act(() => {
9096
TestRenderer.act(() => {});
9197
expect(() => {
9298
TestRenderer.create(<Effecty />);
@@ -99,7 +105,7 @@ it('resets correctly across renderers', () => {
99105
it('warns when using the wrong act version - test + dom: render', () => {
100106
expect(() => {
101107
TestRenderer.act(() => {
102-
TestUtils.renderIntoDocument(<App />);
108+
ReactDOM.render(<App />, document.createElement('div'));
103109
});
104110
}).toWarnDev(["It looks like you're using the wrong act()"], {
105111
withoutStack: true,
@@ -113,7 +119,7 @@ it('warns when using the wrong act version - test + dom: updates', () => {
113119
setCtr = _setCtr;
114120
return ctr;
115121
}
116-
TestUtils.renderIntoDocument(<Counter />);
122+
ReactDOM.render(<Counter />, document.createElement('div'));
117123
expect(() => {
118124
TestRenderer.act(() => {
119125
setCtr(1);
@@ -123,7 +129,7 @@ it('warns when using the wrong act version - test + dom: updates', () => {
123129

124130
it('warns when using the wrong act version - dom + test: .create()', () => {
125131
expect(() => {
126-
TestUtils.act(() => {
132+
ReactDOM.act(() => {
127133
TestRenderer.create(<App />);
128134
});
129135
}).toWarnDev(["It looks like you're using the wrong act()"], {
@@ -134,7 +140,7 @@ it('warns when using the wrong act version - dom + test: .create()', () => {
134140
it('warns when using the wrong act version - dom + test: .update()', () => {
135141
const root = TestRenderer.create(<App key="one" />);
136142
expect(() => {
137-
TestUtils.act(() => {
143+
ReactDOM.act(() => {
138144
root.update(<App key="two" />);
139145
});
140146
}).toWarnDev(["It looks like you're using the wrong act()"], {
@@ -151,15 +157,15 @@ it('warns when using the wrong act version - dom + test: updates', () => {
151157
}
152158
TestRenderer.create(<Counter />);
153159
expect(() => {
154-
TestUtils.act(() => {
160+
ReactDOM.act(() => {
155161
setCtr(1);
156162
});
157163
}).toWarnDev(["It looks like you're using the wrong act()"]);
158164
});
159165

160166
it('does not warn when nesting react-act inside react-dom', () => {
161-
TestUtils.act(() => {
162-
TestUtils.renderIntoDocument(<ARTTest />);
167+
ReactDOM.act(() => {
168+
ReactDOM.render(<ARTTest />, document.createElement('div'));
163169
});
164170
});
165171

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

172178
it("doesn't warn if you use nested acts from different renderers", () => {
173179
TestRenderer.act(() => {
174-
TestUtils.act(() => {
180+
ReactDOM.act(() => {
175181
TestRenderer.create(<App />);
176182
});
177183
});

packages/react-dom/npm/testing.js

Lines changed: 38 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 6 additions & 0 deletions
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 {
@@ -249,4 +251,8 @@ if (__DEV__) {
249251
}
250252
}
251253

254+
if (isTestEnvironment) {
255+
ReactDOM.act = act;
256+
}
257+
252258
export default ReactDOM;

packages/react-dom/testing.js

Lines changed: 16 additions & 0 deletions
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)