/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
function normalizeCodeLocInfo(str) {
if (typeof str !== 'string') {
return str;
}
// This special case exists only for the special source location in
// ReactElementValidator. That will go away if we remove source locations.
str = str.replace(/Check your code at .+?:\d+/g, 'Check your code at **');
// V8 format:
// at Component (/path/filename.js:123:45)
// React format:
// in Component (at filename.js:123)
return str.replace(/\n +(?:at|in) ([\S]+)[^\n]*/g, function(m, name) {
return '\n in ' + name + ' (at **)';
});
}
describe('component stack', () => {
let React;
let act;
let legacyRender;
let mockError;
let mockWarn;
beforeEach(() => {
// Intercept native console methods before DevTools bootstraps.
// Normalize component stack locations.
mockError = jest.fn();
mockWarn = jest.fn();
console.error = (...args) => {
mockError(...args.map(normalizeCodeLocInfo));
};
console.warn = (...args) => {
mockWarn(...args.map(normalizeCodeLocInfo));
};
const utils = require('./utils');
act = utils.act;
legacyRender = utils.legacyRender;
React = require('react');
});
it('should log the current component stack along with an error or warning', () => {
const Grandparent = () => ;
const Parent = () => ;
const Child = () => {
console.error('Test error.');
console.warn('Test warning.');
return null;
};
const container = document.createElement('div');
act(() => legacyRender(, container));
expect(mockError).toHaveBeenCalledWith(
'Test error.',
'\n in Child (at **)' +
'\n in Parent (at **)' +
'\n in Grandparent (at **)',
);
expect(mockWarn).toHaveBeenCalledWith(
'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...
xit('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;
};
const container = document.createElement('div');
act(() => legacyRender(, container));
expect(useEffectCount).toBe(1);
expect(mockWarn).toHaveBeenCalledWith(
'Warning to trigger appended component stacks.',
'\n in Example (at **)',
);
});
});