main
js 139 lines 3.84 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 * @flow
8 */
9
10 import {
11 getVersionedRenderImplementation,
12 normalizeCodeLocInfo,
13 } from 'react-devtools-shared/src/__tests__/utils';
14
15 describe('component stack', () => {
16 let React;
17 let act;
18 let supportsOwnerStacks;
19
20 beforeEach(() => {
21 const utils = require('./utils');
22 act = utils.act;
23
24 React = require('react');
25 if (
26 React.version.startsWith('19') &&
27 React.version.includes('experimental')
28 ) {
29 supportsOwnerStacks = true;
30 }
31 });
32
33 const {render} = getVersionedRenderImplementation();
34
35 // @reactVersion >=16.9
36 it('should log the current component stack along with an error or warning', () => {
37 const Grandparent = () => <Parent />;
38 const Parent = () => <Child />;
39 const Child = () => {
40 console.error('Test error.');
41 console.warn('Test warning.');
42 return null;
43 };
44
45 act(() => render(<Grandparent />));
46
47 expect(
48 global.consoleErrorMock.mock.calls[0].map(normalizeCodeLocInfo),
49 ).toEqual([
50 'Test error.',
51 '\n in Child (at **)' +
52 '\n in Parent (at **)' +
53 '\n in Grandparent (at **)',
54 ]);
55 expect(
56 global.consoleWarnMock.mock.calls[0].map(normalizeCodeLocInfo),
57 ).toEqual([
58 'Test warning.',
59 '\n in Child (at **)' +
60 '\n in Parent (at **)' +
61 '\n in Grandparent (at **)',
62 ]);
63 });
64
65 // This test should have caught #19911
66 // but didn't because both DevTools and ReactDOM are running in the same memory space,
67 // so the case we're testing against (DevTools prod build and React DEV build) doesn't exist.
68 // It would be nice to figure out a way to test this combination at some point...
69 // eslint-disable-next-line jest/no-disabled-tests
70 it.skip('should disable the current dispatcher before shallow rendering so no effects get scheduled', () => {
71 let useEffectCount = 0;
72
73 const Example = props => {
74 React.useEffect(() => {
75 useEffectCount++;
76 expect(props).toBeDefined();
77 }, [props]);
78 console.warn('Warning to trigger appended component stacks.');
79 return null;
80 };
81
82 act(() => render(<Example test="abc" />));
83
84 expect(useEffectCount).toBe(1);
85
86 expect(
87 global.consoleWarnMock.mock.calls[0].map(normalizeCodeLocInfo),
88 ).toEqual([
89 'Warning to trigger appended component stacks.',
90 '\n in Example (at **)',
91 ]);
92 });
93
94 // @reactVersion >= 18.3
95 it('should log the current component stack with debug info from promises', () => {
96 const Child = () => {
97 console.error('Test error.');
98 console.warn('Test warning.');
99 return null;
100 };
101 const ChildPromise = Promise.resolve(<Child />);
102 ChildPromise.status = 'fulfilled';
103 ChildPromise.value = <Child />;
104 ChildPromise._debugInfo = [
105 {
106 name: 'ServerComponent',
107 env: 'Server',
108 owner: null,
109 },
110 ];
111 const Parent = () => ChildPromise;
112 const Grandparent = () => <Parent />;
113
114 act(() => render(<Grandparent />));
115
116 expect(
117 global.consoleErrorMock.mock.calls[0].map(normalizeCodeLocInfo),
118 ).toEqual([
119 'Test error.',
120 supportsOwnerStacks
121 ? '\n in Child (at **)'
122 : '\n in Child (at **)' +
123 '\n in ServerComponent (at **)' +
124 '\n in Parent (at **)' +
125 '\n in Grandparent (at **)',
126 ]);
127 expect(
128 global.consoleWarnMock.mock.calls[0].map(normalizeCodeLocInfo),
129 ).toEqual([
130 'Test warning.',
131 supportsOwnerStacks
132 ? '\n in Child (at **)'
133 : '\n in Child (at **)' +
134 '\n in ServerComponent (at **)' +
135 '\n in Parent (at **)' +
136 '\n in Grandparent (at **)',
137 ]);
138 });
139 });