mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Stacked on https://github.com/facebook/react/pull/30566 and whats under it. See [this commit](https://github.com/facebook/react/pull/30596/commits/374fd737e4b0b7028afb765838db7c0e22def865). It is mostly copying code from one place to another and updating tests. With these changes, for every console method that we patch, there is going to be a single applied patch: - For `error`, `warn`, and `trace` we are patching when hook is installed. This guarantees that component stacks are going to be appended even if browser DevTools are not opened. We pay some price for it, though: if user has browser DevTools closed and if at this point some warning or error is emitted (logged), the next time user opens browser DevTools, they are going to see `hook.js` as the source frame. Unfortunately, ignore listing from source maps is not applied retroactively, and I don't know if its a bug or just a design limitations. Once browser DevTools are opened, source maps will be loaded and ignore listing will be applied for all emitted logs in the future. - For `log`, `info`, `group`, `groupCollapsed` we are only patching when React notifies React DevTools about running in StrictMode. We unpatch the methods right after it.
140 lines
3.8 KiB
JavaScript
140 lines
3.8 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow
|
|
*/
|
|
|
|
import {
|
|
getVersionedRenderImplementation,
|
|
normalizeCodeLocInfo,
|
|
} from 'react-devtools-shared/src/__tests__/utils';
|
|
|
|
describe('component stack', () => {
|
|
let React;
|
|
let act;
|
|
let supportsOwnerStacks;
|
|
|
|
beforeEach(() => {
|
|
const utils = require('./utils');
|
|
act = utils.act;
|
|
|
|
React = require('react');
|
|
if (
|
|
React.version.startsWith('19') &&
|
|
React.version.includes('experimental')
|
|
) {
|
|
supportsOwnerStacks = true;
|
|
}
|
|
});
|
|
|
|
const {render} = getVersionedRenderImplementation();
|
|
|
|
// @reactVersion >=16.9
|
|
it('should log the current component stack along with an error or warning', () => {
|
|
const Grandparent = () => <Parent />;
|
|
const Parent = () => <Child />;
|
|
const Child = () => {
|
|
console.error('Test error.');
|
|
console.warn('Test warning.');
|
|
return null;
|
|
};
|
|
|
|
act(() => render(<Grandparent />));
|
|
|
|
expect(
|
|
global.consoleErrorMock.mock.calls[0].map(normalizeCodeLocInfo),
|
|
).toEqual([
|
|
'Test error.',
|
|
'\n in Child (at **)' +
|
|
'\n in Parent (at **)' +
|
|
'\n in Grandparent (at **)',
|
|
]);
|
|
expect(
|
|
global.consoleWarnMock.mock.calls[0].map(normalizeCodeLocInfo),
|
|
).toEqual([
|
|
'Test warning.',
|
|
'\n in Child (at **)' +
|
|
'\n in Parent (at **)' +
|
|
'\n in Grandparent (at **)',
|
|
]);
|
|
});
|
|
|
|
// This test should have caught #19911
|
|
// but didn't because both DevTools and ReactDOM are running in the same memory space,
|
|
// so the case we're testing against (DevTools prod build and React DEV build) doesn't exist.
|
|
// It would be nice to figure out a way to test this combination at some point...
|
|
// eslint-disable-next-line jest/no-disabled-tests
|
|
it.skip('should disable the current dispatcher before shallow rendering so no effects get scheduled', () => {
|
|
let useEffectCount = 0;
|
|
|
|
const Example = props => {
|
|
React.useEffect(() => {
|
|
useEffectCount++;
|
|
expect(props).toBeDefined();
|
|
}, [props]);
|
|
console.warn('Warning to trigger appended component stacks.');
|
|
return null;
|
|
};
|
|
|
|
act(() => render(<Example test="abc" />));
|
|
|
|
expect(useEffectCount).toBe(1);
|
|
|
|
expect(
|
|
global.consoleWarnMock.mock.calls[0].map(normalizeCodeLocInfo),
|
|
).toEqual([
|
|
'Warning to trigger appended component stacks.',
|
|
'\n in Example (at **)',
|
|
]);
|
|
});
|
|
|
|
// @reactVersion >= 18.3
|
|
it('should log the current component stack with debug info from promises', () => {
|
|
const Child = () => {
|
|
console.error('Test error.');
|
|
console.warn('Test warning.');
|
|
return null;
|
|
};
|
|
const ChildPromise = Promise.resolve(<Child />);
|
|
ChildPromise.status = 'fulfilled';
|
|
ChildPromise.value = <Child />;
|
|
ChildPromise._debugInfo = [
|
|
{
|
|
name: 'ServerComponent',
|
|
env: 'Server',
|
|
owner: null,
|
|
},
|
|
];
|
|
const Parent = () => ChildPromise;
|
|
const Grandparent = () => <Parent />;
|
|
|
|
act(() => render(<Grandparent />));
|
|
|
|
expect(
|
|
global.consoleErrorMock.mock.calls[0].map(normalizeCodeLocInfo),
|
|
).toEqual([
|
|
'Test error.',
|
|
supportsOwnerStacks
|
|
? '\n in Child (at **)'
|
|
: '\n in Child (at **)' +
|
|
'\n in ServerComponent (at **)' +
|
|
'\n in Parent (at **)' +
|
|
'\n in Grandparent (at **)',
|
|
]);
|
|
expect(
|
|
global.consoleWarnMock.mock.calls[0].map(normalizeCodeLocInfo),
|
|
).toEqual([
|
|
'Test warning.',
|
|
supportsOwnerStacks
|
|
? '\n in Child (at **)'
|
|
: '\n in Child (at **)' +
|
|
'\n in ServerComponent (at **)' +
|
|
'\n in Parent (at **)' +
|
|
'\n in Grandparent (at **)',
|
|
]);
|
|
});
|
|
});
|