Convert ReactDOMAttribute to createRoot (#28089)
Sebastian Silbermann committed
Jan 26, 2024 at 10:17 UTC
36baa43560f839f0add7e0ec8125580e3b85235c
1 file changed
+73
-40
packages/react-dom/src/__tests__/ReactDOMAttribute-test.js
+73
-40
@@ -11,85 +11,114 @@
11
12
describe('ReactDOM unknown attribute', () => {
13
let React;
14
- let ReactDOM;
14
+ let ReactDOMClient;
15
+ let act;
16
17
beforeEach(() => {
18
jest.resetModules();
19
React = require('react');
19
- ReactDOM = require('react-dom');
20
+ ReactDOMClient = require('react-dom/client');
21
+ act = require('internal-test-utils').act;
22
});
23
22
- function testUnknownAttributeRemoval(givenValue) {
24
+ async function testUnknownAttributeRemoval(givenValue) {
25
const el = document.createElement('div');
24
- ReactDOM.render(<div unknown="something" />, el);
26
+ const root = ReactDOMClient.createRoot(el);
27
+
28
+ await act(() => {
29
+ root.render(<div unknown="something" />);
30
+ });
31
+
32
expect(el.firstChild.getAttribute('unknown')).toBe('something');
26
- ReactDOM.render(<div unknown={givenValue} />, el);
33
+
34
+ await act(() => {
35
+ root.render(<div unknown={givenValue} />);
36
+ });
37
+
38
expect(el.firstChild.hasAttribute('unknown')).toBe(false);
39
}
40
30
- function testUnknownAttributeAssignment(givenValue, expectedDOMValue) {
41
+ async function testUnknownAttributeAssignment(givenValue, expectedDOMValue) {
42
const el = document.createElement('div');
32
- ReactDOM.render(<div unknown="something" />, el);
43
+ const root = ReactDOMClient.createRoot(el);
44
+
45
+ await act(() => {
46
+ root.render(<div unknown="something" />);
47
+ });
48
+
49
expect(el.firstChild.getAttribute('unknown')).toBe('something');
34
- ReactDOM.render(<div unknown={givenValue} />, el);
50
+
51
+ await act(() => {
52
+ root.render(<div unknown={givenValue} />);
53
+ });
54
+
55
expect(el.firstChild.getAttribute('unknown')).toBe(expectedDOMValue);
56
}
57
58
describe('unknown attributes', () => {
39
- it('removes values null and undefined', () => {
40
- testUnknownAttributeRemoval(null);
41
- testUnknownAttributeRemoval(undefined);
59
+ it('removes values null and undefined', async () => {
60
+ await testUnknownAttributeRemoval(null);
61
+ await testUnknownAttributeRemoval(undefined);
62
});
63
44
- it('changes values true, false to null, and also warns once', () => {
45
- expect(() => testUnknownAttributeAssignment(true, null)).toErrorDev(
64
+ it('changes values true, false to null, and also warns once', async () => {
65
+ await expect(() => testUnknownAttributeAssignment(true, null)).toErrorDev(
66
'Received `true` for a non-boolean attribute `unknown`.\n\n' +
67
'If you want to write it to the DOM, pass a string instead: ' +
68
'unknown="true" or unknown={value.toString()}.\n' +
69
' in div (at **)',
70
);
51
- testUnknownAttributeAssignment(false, null);
71
+ await testUnknownAttributeAssignment(false, null);
72
});
73
54
- it('removes unknown attributes that were rendered but are now missing', () => {
74
+ it('removes unknown attributes that were rendered but are now missing', async () => {
75
const el = document.createElement('div');
56
- ReactDOM.render(<div unknown="something" />, el);
76
+ const root = ReactDOMClient.createRoot(el);
77
+
78
+ await act(() => {
79
+ root.render(<div unknown="something" />);
80
+ });
81
+
82
expect(el.firstChild.getAttribute('unknown')).toBe('something');
58
- ReactDOM.render(<div />, el);
83
+
84
+ await act(() => {
85
+ root.render(<div />);
86
+ });
87
+
88
expect(el.firstChild.hasAttribute('unknown')).toBe(false);
89
});
90
62
- it('passes through strings', () => {
63
- testUnknownAttributeAssignment('a string', 'a string');
91
+ it('passes through strings', async () => {
92
+ await testUnknownAttributeAssignment('a string', 'a string');
93
});
94
66
- it('coerces numbers to strings', () => {
67
- testUnknownAttributeAssignment(0, '0');
68
- testUnknownAttributeAssignment(-1, '-1');
69
- testUnknownAttributeAssignment(42, '42');
70
- testUnknownAttributeAssignment(9000.99, '9000.99');
95
+ it('coerces numbers to strings', async () => {
96
+ await testUnknownAttributeAssignment(0, '0');
97
+ await testUnknownAttributeAssignment(-1, '-1');
98
+ await testUnknownAttributeAssignment(42, '42');
99
+ await testUnknownAttributeAssignment(9000.99, '9000.99');
100
});
101
73
- it('coerces NaN to strings and warns', () => {
74
- expect(() => testUnknownAttributeAssignment(NaN, 'NaN')).toErrorDev(
102
+ it('coerces NaN to strings and warns', async () => {
103
+ await expect(() => testUnknownAttributeAssignment(NaN, 'NaN')).toErrorDev(
104
'Warning: Received NaN for the `unknown` attribute. ' +
105
'If this is expected, cast the value to a string.\n' +
106
' in div (at **)',
107
);
108
});
109
81
- it('coerces objects to strings and warns', () => {
110
+ it('coerces objects to strings and warns', async () => {
111
const lol = {
112
toString() {
113
return 'lol';
114
},
115
};
116
88
- testUnknownAttributeAssignment({hello: 'world'}, '[object Object]');
89
- testUnknownAttributeAssignment(lol, 'lol');
117
+ await testUnknownAttributeAssignment({hello: 'world'}, '[object Object]');
118
+ await testUnknownAttributeAssignment(lol, 'lol');
119
});
120
92
- it('throws with Temporal-like objects', () => {
121
+ it('throws with Temporal-like objects', async () => {
122
class TemporalLike {
123
valueOf() {
124
// Throwing here is the behavior of ECMAScript "Temporal" date/time API.
@@ -102,16 +131,16 @@ describe('ReactDOM unknown attribute', () => {
131
}
132
const test = () =>
133
testUnknownAttributeAssignment(new TemporalLike(), null);
105
- expect(() =>
106
- expect(test).toThrowError(new TypeError('prod message')),
134
+ await expect(() =>
135
+ expect(test).rejects.toThrowError(new TypeError('prod message')),
136
).toErrorDev(
137
'Warning: The provided `unknown` attribute is an unsupported type TemporalLike.' +
138
' This value must be coerced to a string before using it here.',
139
);
140
});
141
113
- it('removes symbols and warns', () => {
114
- expect(() => testUnknownAttributeRemoval(Symbol('foo'))).toErrorDev(
142
+ it('removes symbols and warns', async () => {
143
+ await expect(() => testUnknownAttributeRemoval(Symbol('foo'))).toErrorDev(
144
'Warning: Invalid value for prop `unknown` on <div> tag. Either remove it ' +
145
'from the element, or pass a string or number value to keep it ' +
146
'in the DOM. For details, see https://reactjs.org/link/attribute-behavior \n' +
@@ -119,8 +148,8 @@ describe('ReactDOM unknown attribute', () => {
148
);
149
});
150
122
- it('removes functions and warns', () => {
123
- expect(() =>
151
+ it('removes functions and warns', async () => {
152
+ await expect(() =>
153
testUnknownAttributeRemoval(function someFunction() {}),
154
).toErrorDev(
155
'Warning: Invalid value for prop `unknown` on <div> tag. Either remove ' +
@@ -131,12 +160,16 @@ describe('ReactDOM unknown attribute', () => {
160
);
161
});
162
134
- it('allows camelCase unknown attributes and warns', () => {
163
+ it('allows camelCase unknown attributes and warns', async () => {
164
const el = document.createElement('div');
165
137
- expect(() =>
138
- ReactDOM.render(<div helloWorld="something" />, el),
139
- ).toErrorDev(
166
+ await expect(async () => {
167
+ const root = ReactDOMClient.createRoot(el);
168
+
169
+ await act(() => {
170
+ root.render(<div helloWorld="something" />);
171
+ });
172
+ }).toErrorDev(
173
'React does not recognize the `helloWorld` prop on a DOM element. ' +
174
'If you intentionally want it to appear in the DOM as a custom ' +
175
'attribute, spell it as lowercase `helloworld` instead. ' +