main
js 161 lines 4.68 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and 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 * @emails react-core
8 * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment
9 */
10
11 'use strict';
12
13 const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');
14
15 const TEXT_NODE_TYPE = 3;
16
17 let React;
18 let ReactDOMClient;
19 let ReactDOMServer;
20
21 function initModules() {
22 // Reset warning cache.
23 jest.resetModules();
24 React = require('react');
25 ReactDOMClient = require('react-dom/client');
26 ReactDOMServer = require('react-dom/server');
27
28 // Make them available to the helpers.
29 return {
30 ReactDOMClient,
31 ReactDOMServer,
32 };
33 }
34
35 const {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules);
36
37 describe('ReactDOMServerIntegration', () => {
38 beforeEach(() => {
39 resetModules();
40 });
41
42 describe('basic rendering', function () {
43 itRenders('a blank div', async render => {
44 const e = await render(<div />);
45 expect(e.tagName).toBe('DIV');
46 });
47
48 itRenders('a self-closing tag', async render => {
49 const e = await render(<br />);
50 expect(e.tagName).toBe('BR');
51 });
52
53 itRenders('a self-closing tag as a child', async render => {
54 const e = await render(
55 <div>
56 <br />
57 </div>,
58 );
59 expect(e.childNodes.length).toBe(1);
60 expect(e.firstChild.tagName).toBe('BR');
61 });
62
63 itRenders('a string', async render => {
64 const e = await render('Hello');
65 expect(e.nodeType).toBe(3);
66 expect(e.nodeValue).toMatch('Hello');
67 });
68
69 itRenders('a number', async render => {
70 const e = await render(42);
71 expect(e.nodeType).toBe(3);
72 expect(e.nodeValue).toMatch('42');
73 });
74
75 itRenders('a bigint', async render => {
76 const e = await render(42n);
77 expect(e.nodeType).toBe(3);
78 expect(e.nodeValue).toMatch('42');
79 });
80
81 itRenders('an array with one child', async render => {
82 const e = await render([<div key={1}>text1</div>]);
83 const parent = e.parentNode;
84 expect(parent.childNodes[0].tagName).toBe('DIV');
85 });
86
87 itRenders('an array with several children', async render => {
88 const Header = props => {
89 return <p>header</p>;
90 };
91 const Footer = props => {
92 return [<h2 key={1}>footer</h2>, <h3 key={2}>about</h3>];
93 };
94 const e = await render([
95 <div key={1}>text1</div>,
96 <span key={2}>text2</span>,
97 <Header key={3} />,
98 <Footer key={4} />,
99 ]);
100 const parent = e.parentNode;
101 expect(parent.childNodes[0].tagName).toBe('DIV');
102 expect(parent.childNodes[1].tagName).toBe('SPAN');
103 expect(parent.childNodes[2].tagName).toBe('P');
104 expect(parent.childNodes[3].tagName).toBe('H2');
105 expect(parent.childNodes[4].tagName).toBe('H3');
106 });
107
108 itRenders('a nested array', async render => {
109 const e = await render([
110 [<div key={1}>text1</div>],
111 <span key={1}>text2</span>,
112 [[[null, <p key={1} />], false]],
113 ]);
114 const parent = e.parentNode;
115 expect(parent.childNodes[0].tagName).toBe('DIV');
116 expect(parent.childNodes[1].tagName).toBe('SPAN');
117 expect(parent.childNodes[2].tagName).toBe('P');
118 });
119
120 itRenders('an iterable', async render => {
121 const threeDivIterable = {
122 '@@iterator': function () {
123 let i = 0;
124 return {
125 next: function () {
126 if (i++ < 3) {
127 return {value: <div key={i} />, done: false};
128 } else {
129 return {value: undefined, done: true};
130 }
131 },
132 };
133 },
134 };
135 const e = await render(threeDivIterable);
136 const parent = e.parentNode;
137 expect(parent.childNodes.length).toBe(3);
138 expect(parent.childNodes[0].tagName).toBe('DIV');
139 expect(parent.childNodes[1].tagName).toBe('DIV');
140 expect(parent.childNodes[2].tagName).toBe('DIV');
141 });
142
143 itRenders('emptyish values', async render => {
144 const e = await render(0);
145 expect(e.nodeType).toBe(TEXT_NODE_TYPE);
146 expect(e.nodeValue).toMatch('0');
147
148 // Empty string is special because client renders a node
149 // but server returns empty HTML. So we compare parent text.
150 expect((await render(<div>{''}</div>)).textContent).toBe('');
151
152 expect(await render([])).toBe(null);
153 expect(await render(false)).toBe(null);
154 expect(await render(true)).toBe(null);
155 expect(await render([[[false]], undefined])).toBe(null);
156
157 // hydrateRoot errors for undefined children.
158 expect(await render(undefined, 1)).toBe(null);
159 });
160 });
161 });