Convert trustedTypes to createRoot (#28163)
Sebastian Silbermann committed
Jan 30, 2024 at 22:22 UTC
af7e8c7a71c60278e3935dfb20fac7b562769bb4
1 file changed
+59
-27
packages/react-dom/src/client/__tests__/trustedTypes-test.internal.js
+59
-27
@@ -11,8 +11,9 @@
11
12
describe('when Trusted Types are available in global object', () => {
13
let React;
14
- let ReactDOM;
14
+ let ReactDOMClient;
15
let ReactFeatureFlags;
16
+ let act;
17
let container;
18
let ttObject1;
19
let ttObject2;
@@ -34,7 +35,8 @@ describe('when Trusted Types are available in global object', () => {
35
ReactFeatureFlags = require('shared/ReactFeatureFlags');
36
ReactFeatureFlags.enableTrustedTypesIntegration = true;
37
React = require('react');
37
- ReactDOM = require('react-dom');
38
+ ReactDOMClient = require('react-dom/client');
39
+ act = require('internal-test-utils').act;
40
ttObject1 = {
41
toString() {
42
return '<b>Hi</b>';
@@ -53,7 +55,7 @@ describe('when Trusted Types are available in global object', () => {
55
delete window.trustedTypes;
56
});
57
56
- it('should not stringify trusted values for dangerouslySetInnerHTML', () => {
58
+ it('should not stringify trusted values for dangerouslySetInnerHTML', async () => {
59
const innerHTMLDescriptor = Object.getOwnPropertyDescriptor(
60
Element.prototype,
61
'innerHTML',
@@ -69,20 +71,21 @@ describe('when Trusted Types are available in global object', () => {
71
return innerHTMLDescriptor.set.apply(this, arguments);
72
},
73
});
72
- ReactDOM.render(
73
- <div dangerouslySetInnerHTML={{__html: ttObject1}} />,
74
- container,
75
- );
74
+ const root = ReactDOMClient.createRoot(container);
75
+ await act(() => {
76
+ root.render(<div dangerouslySetInnerHTML={{__html: ttObject1}} />);
77
+ });
78
+
79
expect(container.innerHTML).toBe('<div><b>Hi</b></div>');
80
expect(innerHTMLCalls.length).toBe(1);
81
// Ensure it didn't get stringified when passed to a DOM sink:
82
expect(innerHTMLCalls[0]).toBe(ttObject1);
83
84
innerHTMLCalls.length = 0;
82
- ReactDOM.render(
83
- <div dangerouslySetInnerHTML={{__html: ttObject2}} />,
84
- container,
85
- );
85
+ await act(() => {
86
+ root.render(<div dangerouslySetInnerHTML={{__html: ttObject2}} />);
87
+ });
88
+
89
expect(container.innerHTML).toBe('<div><b>Bye</b></div>');
90
expect(innerHTMLCalls.length).toBe(1);
91
// Ensure it didn't get stringified when passed to a DOM sink:
@@ -96,7 +99,7 @@ describe('when Trusted Types are available in global object', () => {
99
}
100
});
101
99
- it('should not stringify trusted values for setAttribute (unknown attribute)', () => {
102
+ it('should not stringify trusted values for setAttribute (unknown attribute)', async () => {
103
const setAttribute = Element.prototype.setAttribute;
104
try {
105
const setAttributeCalls = [];
@@ -104,7 +107,11 @@ describe('when Trusted Types are available in global object', () => {
107
setAttributeCalls.push([this, name.toLowerCase(), value]);
108
return setAttribute.apply(this, arguments);
109
};
107
- ReactDOM.render(<div data-foo={ttObject1} />, container);
110
+ const root = ReactDOMClient.createRoot(container);
111
+ await act(() => {
112
+ root.render(<div data-foo={ttObject1} />);
113
+ });
114
+
115
expect(container.innerHTML).toBe('<div data-foo="<b>Hi</b>"></div>');
116
expect(setAttributeCalls.length).toBe(1);
117
expect(setAttributeCalls[0][0]).toBe(container.firstChild);
@@ -113,7 +120,10 @@ describe('when Trusted Types are available in global object', () => {
120
expect(setAttributeCalls[0][2]).toBe(ttObject1);
121
122
setAttributeCalls.length = 0;
116
- ReactDOM.render(<div data-foo={ttObject2} />, container);
123
+ await act(() => {
124
+ root.render(<div data-foo={ttObject2} />);
125
+ });
126
+
127
expect(setAttributeCalls.length).toBe(1);
128
expect(setAttributeCalls[0][0]).toBe(container.firstChild);
129
expect(setAttributeCalls[0][1]).toBe('data-foo');
@@ -124,7 +134,7 @@ describe('when Trusted Types are available in global object', () => {
134
}
135
});
136
127
- it('should not stringify trusted values for setAttribute (known attribute)', () => {
137
+ it('should not stringify trusted values for setAttribute (known attribute)', async () => {
138
const setAttribute = Element.prototype.setAttribute;
139
try {
140
const setAttributeCalls = [];
@@ -132,7 +142,11 @@ describe('when Trusted Types are available in global object', () => {
142
setAttributeCalls.push([this, name.toLowerCase(), value]);
143
return setAttribute.apply(this, arguments);
144
};
135
- ReactDOM.render(<div className={ttObject1} />, container);
145
+ const root = ReactDOMClient.createRoot(container);
146
+ await act(() => {
147
+ root.render(<div className={ttObject1} />);
148
+ });
149
+
150
expect(container.innerHTML).toBe('<div class="<b>Hi</b>"></div>');
151
expect(setAttributeCalls.length).toBe(1);
152
expect(setAttributeCalls[0][0]).toBe(container.firstChild);
@@ -141,7 +155,10 @@ describe('when Trusted Types are available in global object', () => {
155
expect(setAttributeCalls[0][2]).toBe(ttObject1);
156
157
setAttributeCalls.length = 0;
144
- ReactDOM.render(<div className={ttObject2} />, container);
158
+ await act(() => {
159
+ root.render(<div className={ttObject2} />);
160
+ });
161
+
162
expect(setAttributeCalls.length).toBe(1);
163
expect(setAttributeCalls[0][0]).toBe(container.firstChild);
164
expect(setAttributeCalls[0][1]).toBe('class');
@@ -152,7 +169,7 @@ describe('when Trusted Types are available in global object', () => {
169
}
170
});
171
155
- it('should not stringify trusted values for setAttributeNS', () => {
172
+ it('should not stringify trusted values for setAttributeNS', async () => {
173
const setAttributeNS = Element.prototype.setAttributeNS;
174
try {
175
const setAttributeNSCalls = [];
@@ -160,7 +177,11 @@ describe('when Trusted Types are available in global object', () => {
177
setAttributeNSCalls.push([this, ns, name, value]);
178
return setAttributeNS.apply(this, arguments);
179
};
163
- ReactDOM.render(<svg xlinkHref={ttObject1} />, container);
180
+ const root = ReactDOMClient.createRoot(container);
181
+ await act(() => {
182
+ root.render(<svg xlinkHref={ttObject1} />);
183
+ });
184
+
185
expect(container.innerHTML).toBe('<svg xlink:href="<b>Hi</b>"></svg>');
186
expect(setAttributeNSCalls.length).toBe(1);
187
expect(setAttributeNSCalls[0][0]).toBe(container.firstChild);
@@ -170,7 +191,10 @@ describe('when Trusted Types are available in global object', () => {
191
expect(setAttributeNSCalls[0][3]).toBe(ttObject1);
192
193
setAttributeNSCalls.length = 0;
173
- ReactDOM.render(<svg xlinkHref={ttObject2} />, container);
194
+ await act(() => {
195
+ root.render(<svg xlinkHref={ttObject2} />);
196
+ });
197
+
198
expect(setAttributeNSCalls.length).toBe(1);
199
expect(setAttributeNSCalls[0][0]).toBe(container.firstChild);
200
expect(setAttributeNSCalls[0][1]).toBe('http://www.w3.org/1999/xlink');
@@ -209,14 +233,17 @@ describe('when Trusted Types are available in global object', () => {
233
});
234
235
// @gate !disableIEWorkarounds
212
- it('should log a warning', () => {
236
+ it('should log a warning', async () => {
237
class Component extends React.Component {
238
render() {
239
return <svg dangerouslySetInnerHTML={{__html: 'unsafe html'}} />;
240
}
241
}
218
- expect(() => {
219
- ReactDOM.render(<Component />, container);
242
+ const root = ReactDOMClient.createRoot(container);
243
+ await expect(async () => {
244
+ await act(() => {
245
+ root.render(<Component />);
246
+ });
247
}).toErrorDev(
248
"Warning: Using 'dangerouslySetInnerHTML' in an svg element with " +
249
'Trusted Types enabled in an Internet Explorer will cause ' +
@@ -229,9 +256,12 @@ describe('when Trusted Types are available in global object', () => {
256
});
257
});
258
232
- it('should warn once when rendering script tag in jsx on client', () => {
233
- expect(() => {
234
- ReactDOM.render(<script>alert("I am not executed")</script>, container);
259
+ it('should warn once when rendering script tag in jsx on client', async () => {
260
+ const root = ReactDOMClient.createRoot(container);
261
+ await expect(async () => {
262
+ await act(() => {
263
+ root.render(<script>alert("I am not executed")</script>);
264
+ });
265
}).toErrorDev(
266
'Warning: Encountered a script tag while rendering React component. ' +
267
'Scripts inside React components are never executed when rendering ' +
@@ -241,6 +271,8 @@ describe('when Trusted Types are available in global object', () => {
271
);
272
273
// check that the warning is printed only once
244
- ReactDOM.render(<script>alert("I am not executed")</script>, container);
274
+ await act(() => {
275
+ root.render(<script>alert("I am not executed")</script>);
276
+ });
277
});
278
});