main
js 167 lines 4.42 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 */
9
10 'use strict';
11
12 let ReactDOM;
13 let React;
14 let ReactCache;
15 let ReactTestRenderer;
16 let act;
17 let assertConsoleErrorDev;
18
19 describe('ReactTestRenderer', () => {
20 beforeEach(() => {
21 jest.resetModules();
22 ReactDOM = require('react-dom');
23
24 // Isolate test renderer.
25 jest.resetModules();
26 React = require('react');
27 ReactCache = require('react-cache');
28 ReactTestRenderer = require('react-test-renderer');
29 const InternalTestUtils = require('internal-test-utils');
30 act = InternalTestUtils.act;
31 assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;
32 });
33
34 it('should warn if used to render a ReactDOM portal', async () => {
35 const container = document.createElement('div');
36 let error;
37
38 await act(() => {
39 ReactTestRenderer.create(ReactDOM.createPortal('foo', container));
40 }).catch(e => (error = e));
41 assertConsoleErrorDev([
42 'An invalid container has been provided. ' +
43 'This may indicate that another renderer is being used in addition to the test renderer. ' +
44 '(For example, ReactDOM.createPortal inside of a ReactTestRenderer tree.) ' +
45 'This is not supported.',
46 ]);
47
48 // After the update throws, a subsequent render is scheduled to
49 // unmount the whole tree. This update also causes an error, so React
50 // throws an AggregateError.
51 const errors = error.errors;
52 expect(errors.length).toBe(2);
53 expect(errors[0].message.includes('indexOf is not a function')).toBe(true);
54 expect(errors[1].message.includes('indexOf is not a function')).toBe(true);
55 });
56
57 it('find element by prop with suspended content', async () => {
58 const neverResolve = new Promise(() => {});
59
60 function TestComp({foo}) {
61 if (foo === 'one') {
62 throw neverResolve;
63 } else {
64 return null;
65 }
66 }
67
68 const tree = await act(() =>
69 ReactTestRenderer.create(
70 <div>
71 <React.Suspense fallback={null}>
72 <TestComp foo="one" />
73 </React.Suspense>
74 <TestComp foo="two" />
75 </div>,
76 ),
77 );
78
79 expect(
80 tree.root.find(item => {
81 return item.props.foo === 'two';
82 }),
83 ).toBeDefined();
84 });
85
86 describe('timed out Suspense hidden subtrees should not be observable via toJSON', () => {
87 let AsyncText;
88 let PendingResources;
89 let TextResource;
90
91 beforeEach(() => {
92 PendingResources = {};
93 TextResource = ReactCache.unstable_createResource(
94 text =>
95 new Promise(resolve => {
96 PendingResources[text] = resolve;
97 }),
98 text => text,
99 );
100
101 AsyncText = ({text}) => {
102 const value = TextResource.read(text);
103 return value;
104 };
105 });
106
107 it('for root Suspense components', async () => {
108 const App = ({text}) => {
109 return (
110 <React.Suspense fallback="fallback">
111 <AsyncText text={text} />
112 </React.Suspense>
113 );
114 };
115
116 let root;
117 await act(() => {
118 root = ReactTestRenderer.create(<App text="initial" />);
119 });
120 await act(() => {
121 PendingResources.initial('initial');
122 });
123 expect(root.toJSON()).toEqual('initial');
124
125 await act(() => {
126 root.update(<App text="dynamic" />);
127 });
128 expect(root.toJSON()).toEqual('fallback');
129
130 await act(() => {
131 PendingResources.dynamic('dynamic');
132 });
133 expect(root.toJSON()).toEqual('dynamic');
134 });
135
136 it('for nested Suspense components', async () => {
137 const App = ({text}) => {
138 return (
139 <div>
140 <React.Suspense fallback="fallback">
141 <AsyncText text={text} />
142 </React.Suspense>
143 </div>
144 );
145 };
146
147 let root;
148 await act(() => {
149 root = ReactTestRenderer.create(<App text="initial" />);
150 });
151 await act(() => {
152 PendingResources.initial('initial');
153 });
154 expect(root.toJSON().children).toEqual(['initial']);
155
156 await act(() => {
157 root.update(<App text="dynamic" />);
158 });
159 expect(root.toJSON().children).toEqual(['fallback']);
160
161 await act(() => {
162 PendingResources.dynamic('dynamic');
163 });
164 expect(root.toJSON().children).toEqual(['dynamic']);
165 });
166 });
167 });