@samitouri / QOS-React-2 / commits / 36baa43560

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. ' +