Convert ReactElementJSX to createRoot (#28012)
Ricky committed
Jan 22, 2024 at 15:50 UTC
ec19db4266b72ad8d94f851c050eb46c2c4d031a
1 file changed
+67
-40
packages/react/src/__tests__/ReactElementJSX-test.js
+67
-40
@@ -11,9 +11,11 @@
11
12
let React;
13
let ReactDOM;
14
+let ReactDOMClient;
15
let ReactTestUtils;
16
let JSXRuntime;
17
let JSXDEVRuntime;
18
+let act;
19
20
// NOTE: We're explicitly not using JSX here. This is intended to test
21
// a new React.jsx api which does not have a JSX transformer yet.
@@ -27,7 +29,9 @@ describe('ReactElement.jsx', () => {
29
JSXRuntime = require('react/jsx-runtime');
30
JSXDEVRuntime = require('react/jsx-dev-runtime');
31
ReactDOM = require('react-dom');
32
+ ReactDOMClient = require('react-dom/client');
33
ReactTestUtils = require('react-dom/test-utils');
34
+ act = require('internal-test-utils').act;
35
});
36
37
it('allows static methods to be called using the type property', () => {
@@ -48,23 +52,25 @@ describe('ReactElement.jsx', () => {
52
expect(element.constructor).toBe(object.constructor);
53
});
54
51
- it('should use default prop value when removing a prop', () => {
55
+ it('should use default prop value when removing a prop', async () => {
56
class Component extends React.Component {
57
render() {
54
- return JSXRuntime.jsx('span', {});
58
+ return JSXRuntime.jsx('span', {children: [this.props.fruit]});
59
}
60
}
61
Component.defaultProps = {fruit: 'persimmon'};
62
63
const container = document.createElement('div');
60
- const instance = ReactDOM.render(
61
- JSXRuntime.jsx(Component, {fruit: 'mango'}),
62
- container,
63
- );
64
- expect(instance.props.fruit).toBe('mango');
64
+ const root = ReactDOMClient.createRoot(container);
65
+ await act(() => {
66
+ root.render(JSXRuntime.jsx(Component, {fruit: 'mango'}));
67
+ });
68
+ expect(container.firstChild.textContent).toBe('mango');
69
66
- ReactDOM.render(JSXRuntime.jsx(Component, {}), container);
67
- expect(instance.props.fruit).toBe('persimmon');
70
+ await act(() => {
71
+ root.render(JSXRuntime.jsx(Component, {}));
72
+ });
73
+ expect(container.firstChild.textContent).toBe('persimmon');
74
});
75
76
it('should normalize props with default values', () => {
@@ -114,7 +120,7 @@ describe('ReactElement.jsx', () => {
120
}
121
});
122
117
- it('throws when adding a prop (in dev) after element creation', () => {
123
+ it('throws when adding a prop (in dev) after element creation', async () => {
124
const container = document.createElement('div');
125
class Outer extends React.Component {
126
render() {
@@ -134,12 +140,15 @@ describe('ReactElement.jsx', () => {
140
}
141
}
142
Outer.defaultProps = {sound: 'meow'};
137
- const outer = ReactDOM.render(JSXRuntime.jsx(Outer, {}), container);
138
- expect(ReactDOM.findDOMNode(outer).textContent).toBe('meow');
143
+ const root = ReactDOMClient.createRoot(container);
144
+ await act(() => {
145
+ root.render(JSXRuntime.jsx(Outer, {}));
146
+ });
147
+ expect(container.firstChild.textContent).toBe('meow');
148
if (__DEV__) {
140
- expect(ReactDOM.findDOMNode(outer).className).toBe('');
149
+ expect(container.firstChild.className).toBe('');
150
} else {
142
- expect(ReactDOM.findDOMNode(outer).className).toBe('quack');
151
+ expect(container.firstChild.className).toBe('quack');
152
}
153
});
154
@@ -155,7 +164,7 @@ describe('ReactElement.jsx', () => {
164
expect(test.props.value).toBeNaN();
165
});
166
158
- it('should warn when `key` is being accessed on composite element', () => {
167
+ it('should warn when `key` is being accessed on composite element', async () => {
168
const container = document.createElement('div');
169
class Child extends React.Component {
170
render() {
@@ -173,9 +182,12 @@ describe('ReactElement.jsx', () => {
182
});
183
}
184
}
176
- expect(() =>
177
- ReactDOM.render(JSXRuntime.jsx(Parent, {}), container),
178
- ).toErrorDev(
185
+ await expect(async () => {
186
+ const root = ReactDOMClient.createRoot(container);
187
+ await act(() => {
188
+ root.render(JSXRuntime.jsx(Parent, {}));
189
+ });
190
+ }).toErrorDev(
191
'Child: `key` is not a prop. Trying to access it will result ' +
192
'in `undefined` being returned. If you need to access the same ' +
193
'value within the child component, you should pass it as a different ' +
@@ -183,14 +195,14 @@ describe('ReactElement.jsx', () => {
195
);
196
});
197
186
- it('warns when a jsxs is passed something that is not an array', () => {
198
+ it('warns when a jsxs is passed something that is not an array', async () => {
199
const container = document.createElement('div');
188
- expect(() =>
189
- ReactDOM.render(
190
- JSXRuntime.jsxs('div', {children: 'foo'}, null),
191
- container,
192
- ),
193
- ).toErrorDev(
200
+ await expect(async () => {
201
+ const root = ReactDOMClient.createRoot(container);
202
+ await act(() => {
203
+ root.render(JSXRuntime.jsxs('div', {children: 'foo'}, null));
204
+ });
205
+ }).toErrorDev(
206
'React.jsx: Static children should always be an array. ' +
207
'You are likely explicitly calling React.jsxs or React.jsxDEV. ' +
208
'Use the Babel transform instead.',
@@ -209,7 +221,7 @@ describe('ReactElement.jsx', () => {
221
);
222
});
223
212
- it('should warn when `ref` is being accessed', () => {
224
+ it('should warn when `ref` is being accessed', async () => {
225
const container = document.createElement('div');
226
class Child extends React.Component {
227
render() {
@@ -223,9 +235,12 @@ describe('ReactElement.jsx', () => {
235
});
236
}
237
}
226
- expect(() =>
227
- ReactDOM.render(JSXRuntime.jsx(Parent, {}), container),
228
- ).toErrorDev(
238
+ await expect(async () => {
239
+ const root = ReactDOMClient.createRoot(container);
240
+ await act(() => {
241
+ root.render(JSXRuntime.jsx(Parent, {}));
242
+ });
243
+ }).toErrorDev(
244
'Child: `ref` is not a prop. Trying to access it will result ' +
245
'in `undefined` being returned. If you need to access the same ' +
246
'value within the child component, you should pass it as a different ' +
@@ -233,7 +248,7 @@ describe('ReactElement.jsx', () => {
248
);
249
});
250
236
- it('should warn when unkeyed children are passed to jsx', () => {
251
+ it('should warn when unkeyed children are passed to jsx', async () => {
252
const container = document.createElement('div');
253
254
class Child extends React.Component {
@@ -252,9 +267,12 @@ describe('ReactElement.jsx', () => {
267
});
268
}
269
}
255
- expect(() =>
256
- ReactDOM.render(JSXRuntime.jsx(Parent, {}), container),
257
- ).toErrorDev(
270
+ await expect(async () => {
271
+ const root = ReactDOMClient.createRoot(container);
272
+ await act(() => {
273
+ root.render(JSXRuntime.jsx(Parent, {}));
274
+ });
275
+ }).toErrorDev(
276
'Warning: Each child in a list should have a unique "key" prop.\n\n' +
277
'Check the render method of `Parent`. See https://reactjs.org/link/warning-keys for more information.\n' +
278
' in Child (at **)\n' +
@@ -262,7 +280,7 @@ describe('ReactElement.jsx', () => {
280
);
281
});
282
265
- it('should warn when keys are passed as part of props', () => {
283
+ it('should warn when keys are passed as part of props', async () => {
284
const container = document.createElement('div');
285
class Child extends React.Component {
286
render() {
@@ -276,9 +294,12 @@ describe('ReactElement.jsx', () => {
294
});
295
}
296
}
279
- expect(() =>
280
- ReactDOM.render(JSXRuntime.jsx(Parent, {}), container),
281
- ).toErrorDev(
297
+ await expect(async () => {
298
+ const root = ReactDOMClient.createRoot(container);
299
+ await act(() => {
300
+ root.render(JSXRuntime.jsx(Parent, {}));
301
+ });
302
+ }).toErrorDev(
303
'Warning: A props object containing a "key" prop is being spread into JSX:\n' +
304
' let props = {key: someKey, prop: ...};\n' +
305
' <Child {...props} />\n' +
@@ -288,7 +309,7 @@ describe('ReactElement.jsx', () => {
309
);
310
});
311
291
- it('should not warn when unkeyed children are passed to jsxs', () => {
312
+ it('should not warn when unkeyed children are passed to jsxs', async () => {
313
const container = document.createElement('div');
314
class Child extends React.Component {
315
render() {
@@ -306,8 +327,14 @@ describe('ReactElement.jsx', () => {
327
});
328
}
329
}
309
- // TODO: an explicit expect for no warning?
310
- ReactDOM.render(JSXRuntime.jsx(Parent, {}), container);
330
+
331
+ const root = ReactDOMClient.createRoot(container);
332
+ await act(() => {
333
+ root.render(JSXRuntime.jsx(Parent, {}));
334
+ });
335
+
336
+ // Test shouldn't throw any errors.
337
+ expect(true).toBe(true);
338
});
339
340
it('does not call lazy initializers eagerly', () => {