diff --git a/packages/react-dom/src/__tests__/ReactBrowserEventEmitter-test.internal.js b/packages/react-dom/src/__tests__/ReactBrowserEventEmitter-test.internal.js
index e590851146416..d1fde4af6a4d6 100644
--- a/packages/react-dom/src/__tests__/ReactBrowserEventEmitter-test.internal.js
+++ b/packages/react-dom/src/__tests__/ReactBrowserEventEmitter-test.internal.js
@@ -277,15 +277,11 @@ describe('ReactBrowserEventEmitter', () => {
putListener(CHILD, ON_CLICK_KEY, recordIDAndReturnFalse.bind(null, CHILD));
putListener(PARENT, ON_CLICK_KEY, recordID.bind(null, PARENT));
putListener(GRANDPARENT, ON_CLICK_KEY, recordID.bind(null, GRANDPARENT));
- spyOnDev(console, 'error');
ReactTestUtils.Simulate.click(CHILD);
expect(idCallOrder.length).toBe(3);
expect(idCallOrder[0]).toBe(CHILD);
expect(idCallOrder[1]).toBe(PARENT);
expect(idCallOrder[2]).toBe(GRANDPARENT);
- if (__DEV__) {
- expect(console.error.calls.count()).toEqual(0);
- }
});
/**
diff --git a/packages/react-dom/src/__tests__/ReactComponent-test.js b/packages/react-dom/src/__tests__/ReactComponent-test.js
index a0a8fde8b8661..94d16543e436b 100644
--- a/packages/react-dom/src/__tests__/ReactComponent-test.js
+++ b/packages/react-dom/src/__tests__/ReactComponent-test.js
@@ -46,7 +46,6 @@ describe('ReactComponent', () => {
});
it('should throw (in dev) when children are mutated during render', () => {
- spyOnDev(console, 'error');
function Wrapper(props) {
props.children[1] =
; // Mutation is illegal
return
{props.children}
;
@@ -73,8 +72,6 @@ describe('ReactComponent', () => {
});
it('should throw (in dev) when children are mutated during update', () => {
- spyOnDev(console, 'error');
-
class Wrapper extends React.Component {
componentDidMount() {
this.props.children[1] = ; // Mutation is illegal
@@ -355,10 +352,13 @@ describe('ReactComponent', () => {
});
it('throws usefully when rendering badly-typed elements', () => {
- spyOnDev(console, 'error');
-
const X = undefined;
- expect(() => ReactTestUtils.renderIntoDocument()).toThrowError(
+ expect(() => {
+ expect(() => ReactTestUtils.renderIntoDocument()).toWarnDev(
+ 'React.createElement: type is invalid -- expected a string (for built-in components) ' +
+ 'or a class/function (for composite components) but got: undefined.',
+ );
+ }).toThrowError(
'Element type is invalid: expected a string (for built-in components) ' +
'or a class/function (for composite components) but got: undefined.' +
(__DEV__
@@ -368,20 +368,18 @@ describe('ReactComponent', () => {
);
const Y = null;
- expect(() => ReactTestUtils.renderIntoDocument()).toThrowError(
+ expect(() => {
+ expect(() => ReactTestUtils.renderIntoDocument()).toWarnDev(
+ 'React.createElement: type is invalid -- expected a string (for built-in components) ' +
+ 'or a class/function (for composite components) but got: null.',
+ );
+ }).toThrowError(
'Element type is invalid: expected a string (for built-in components) ' +
'or a class/function (for composite components) but got: null.',
);
-
- if (__DEV__) {
- // One warning for each element creation
- expect(console.error.calls.count()).toBe(2);
- }
});
it('includes owner name in the error about badly-typed elements', () => {
- spyOnDev(console, 'error');
-
const X = undefined;
function Indirection(props) {
@@ -400,7 +398,12 @@ describe('ReactComponent', () => {
return ;
}
- expect(() => ReactTestUtils.renderIntoDocument()).toThrowError(
+ expect(() => {
+ expect(() => ReactTestUtils.renderIntoDocument()).toWarnDev(
+ 'React.createElement: type is invalid -- expected a string (for built-in components) ' +
+ 'or a class/function (for composite components) but got: undefined.',
+ );
+ }).toThrowError(
'Element type is invalid: expected a string (for built-in components) ' +
'or a class/function (for composite components) but got: undefined.' +
(__DEV__
@@ -409,11 +412,6 @@ describe('ReactComponent', () => {
'\n\nCheck the render method of `Bar`.'
: ''),
);
-
- if (__DEV__) {
- // One warning for each element creation
- expect(console.error.calls.count()).toBe(1);
- }
});
it('throws if a plain object is used as a child', () => {
@@ -530,18 +528,13 @@ describe('ReactComponent', () => {
function Foo() {
return Foo;
}
- spyOnDev(console, 'error');
const container = document.createElement('div');
- ReactDOM.render(, container);
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Functions are not valid as a React child. This may happen if ' +
- 'you return a Component instead of from render. ' +
- 'Or maybe you meant to call this function rather than return it.\n' +
- ' in Foo (at **)',
- );
- }
+ expect(() => ReactDOM.render(, container)).toWarnDev(
+ 'Warning: Functions are not valid as a React child. This may happen if ' +
+ 'you return a Component instead of from render. ' +
+ 'Or maybe you meant to call this function rather than return it.\n' +
+ ' in Foo (at **)',
+ );
});
it('warns on function as a return value from a class', () => {
@@ -550,18 +543,13 @@ describe('ReactComponent', () => {
return Foo;
}
}
- spyOnDev(console, 'error');
const container = document.createElement('div');
- ReactDOM.render(, container);
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Functions are not valid as a React child. This may happen if ' +
- 'you return a Component instead of from render. ' +
- 'Or maybe you meant to call this function rather than return it.\n' +
- ' in Foo (at **)',
- );
- }
+ expect(() => ReactDOM.render(, container)).toWarnDev(
+ 'Warning: Functions are not valid as a React child. This may happen if ' +
+ 'you return a Component instead of from render. ' +
+ 'Or maybe you meant to call this function rather than return it.\n' +
+ ' in Foo (at **)',
+ );
});
it('warns on function as a child to host component', () => {
@@ -572,20 +560,15 @@ describe('ReactComponent', () => {
);
}
- spyOnDev(console, 'error');
const container = document.createElement('div');
- ReactDOM.render(, container);
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Functions are not valid as a React child. This may happen if ' +
- 'you return a Component instead of from render. ' +
- 'Or maybe you meant to call this function rather than return it.\n' +
- ' in span (at **)\n' +
- ' in div (at **)\n' +
- ' in Foo (at **)',
- );
- }
+ expect(() => ReactDOM.render(, container)).toWarnDev(
+ 'Warning: Functions are not valid as a React child. This may happen if ' +
+ 'you return a Component instead of from render. ' +
+ 'Or maybe you meant to call this function rather than return it.\n' +
+ ' in span (at **)\n' +
+ ' in div (at **)\n' +
+ ' in Foo (at **)',
+ );
});
it('does not warn for function-as-a-child that gets resolved', () => {
@@ -601,7 +584,6 @@ describe('ReactComponent', () => {
});
it('deduplicates function type warnings based on component type', () => {
- spyOnDev(console, 'error');
class Foo extends React.PureComponent {
constructor() {
super();
@@ -621,26 +603,23 @@ describe('ReactComponent', () => {
}
}
const container = document.createElement('div');
- const component = ReactDOM.render(, container);
+ let component;
+ expect(() => {
+ component = ReactDOM.render(, container);
+ }).toWarnDev([
+ 'Warning: Functions are not valid as a React child. This may happen if ' +
+ 'you return a Component instead of from render. ' +
+ 'Or maybe you meant to call this function rather than return it.\n' +
+ ' in div (at **)\n' +
+ ' in Foo (at **)',
+ 'Warning: Functions are not valid as a React child. This may happen if ' +
+ 'you return a Component instead of from render. ' +
+ 'Or maybe you meant to call this function rather than return it.\n' +
+ ' in span (at **)\n' +
+ ' in div (at **)\n' +
+ ' in Foo (at **)',
+ ]);
component.setState({type: 'portobello mushrooms'});
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(2);
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Functions are not valid as a React child. This may happen if ' +
- 'you return a Component instead of from render. ' +
- 'Or maybe you meant to call this function rather than return it.\n' +
- ' in div (at **)\n' +
- ' in Foo (at **)',
- );
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toBe(
- 'Warning: Functions are not valid as a React child. This may happen if ' +
- 'you return a Component instead of from render. ' +
- 'Or maybe you meant to call this function rather than return it.\n' +
- ' in span (at **)\n' +
- ' in div (at **)\n' +
- ' in Foo (at **)',
- );
- }
});
});
});
diff --git a/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js b/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js
index 33730716ac1e2..51dea221d27ba 100644
--- a/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js
+++ b/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js
@@ -198,8 +198,6 @@ describe('ReactComponentLifeCycle', () => {
});
it('should not allow update state inside of getInitialState', () => {
- spyOnDev(console, 'error');
-
class StatefulComponent extends React.Component {
constructor(props, context) {
super(props, context);
@@ -213,26 +211,20 @@ describe('ReactComponentLifeCycle', () => {
}
}
- ReactTestUtils.renderIntoDocument();
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: setState(...): Can only update a mounted or ' +
- 'mounting component. This usually means you called setState() on an ' +
- 'unmounted component. This is a no-op.\n\nPlease check the code for the ' +
- 'StatefulComponent component.',
- );
- }
+ expect(() => {
+ ReactTestUtils.renderIntoDocument();
+ }).toWarnDev(
+ 'Warning: setState(...): Can only update a mounted or ' +
+ 'mounting component. This usually means you called setState() on an ' +
+ 'unmounted component. This is a no-op.\n\nPlease check the code for the ' +
+ 'StatefulComponent component.',
+ );
- // Check deduplication
+ // Check deduplication; (no extra warnings should be logged).
ReactTestUtils.renderIntoDocument();
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- }
});
it('should correctly determine if a component is mounted', () => {
- spyOnDev(console, 'error');
class Component extends React.Component {
_isMounted() {
// No longer a public API, but we can test that it works internally by
@@ -253,19 +245,13 @@ describe('ReactComponentLifeCycle', () => {
const element = ;
- const instance = ReactTestUtils.renderIntoDocument(element);
- expect(instance._isMounted()).toBeTruthy();
-
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toContain(
- 'Component is accessing isMounted inside its render()',
- );
- }
+ expect(() => {
+ const instance = ReactTestUtils.renderIntoDocument(element);
+ expect(instance._isMounted()).toBeTruthy();
+ }).toWarnDev('Component is accessing isMounted inside its render()');
});
it('should correctly determine if a null component is mounted', () => {
- spyOnDev(console, 'error');
class Component extends React.Component {
_isMounted() {
// No longer a public API, but we can test that it works internally by
@@ -286,15 +272,10 @@ describe('ReactComponentLifeCycle', () => {
const element = ;
- const instance = ReactTestUtils.renderIntoDocument(element);
- expect(instance._isMounted()).toBeTruthy();
-
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toContain(
- 'Component is accessing isMounted inside its render()',
- );
- }
+ expect(() => {
+ const instance = ReactTestUtils.renderIntoDocument(element);
+ expect(instance._isMounted()).toBeTruthy();
+ }).toWarnDev('Component is accessing isMounted inside its render()');
});
it('isMounted should return false when unmounted', () => {
@@ -317,7 +298,6 @@ describe('ReactComponentLifeCycle', () => {
});
it('warns if findDOMNode is used inside render', () => {
- spyOnDev(console, 'error');
class Component extends React.Component {
state = {isMounted: false};
componentDidMount() {
@@ -331,18 +311,12 @@ describe('ReactComponentLifeCycle', () => {
}
}
- ReactTestUtils.renderIntoDocument();
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toContain(
- 'Component is accessing findDOMNode inside its render()',
- );
- }
+ expect(() => {
+ ReactTestUtils.renderIntoDocument();
+ }).toWarnDev('Component is accessing findDOMNode inside its render()');
});
it('should carry through each of the phases of setup', () => {
- spyOnDev(console, 'error');
-
class LifeCycleComponent extends React.Component {
constructor(props, context) {
super(props, context);
@@ -399,7 +373,13 @@ describe('ReactComponentLifeCycle', () => {
// yet initialized, or rendered.
//
const container = document.createElement('div');
- const instance = ReactDOM.render(, container);
+
+ let instance;
+ expect(() => {
+ instance = ReactDOM.render(, container);
+ }).toWarnDev(
+ 'LifeCycleComponent is accessing isMounted inside its render() function',
+ );
// getInitialState
expect(instance._testJournal.returnedFromGetInitialState).toEqual(
@@ -449,13 +429,6 @@ describe('ReactComponentLifeCycle', () => {
// But the current lifecycle of the component is unmounted.
expect(getLifeCycleState(instance)).toBe('UNMOUNTED');
expect(instance.state).toEqual(POST_WILL_UNMOUNT_STATE);
-
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toContain(
- 'LifeCycleComponent is accessing isMounted inside its render() function',
- );
- }
});
it('should not throw when updating an auxiliary component', () => {
diff --git a/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js b/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js
index 3ae6384dbbcc4..a707a8df6cd1f 100644
--- a/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js
+++ b/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js
@@ -122,29 +122,21 @@ describe('ReactCompositeComponent', () => {
}
}
- spyOnDev(console, 'warn');
const markup = ReactDOMServer.renderToString();
// Old API based on heuristic
let container = document.createElement('div');
container.innerHTML = markup;
- ReactDOM.render(, container);
- if (__DEV__) {
- expect(console.warn.calls.count()).toBe(1);
- expect(console.warn.calls.argsFor(0)[0]).toContain(
- 'render(): Calling ReactDOM.render() to hydrate server-rendered markup ' +
- 'will stop working in React v17. Replace the ReactDOM.render() call ' +
- 'with ReactDOM.hydrate() if you want React to attach to the server HTML.',
- );
- console.warn.calls.reset();
- }
+ expect(() => ReactDOM.render(, container)).toLowPriorityWarnDev(
+ 'render(): Calling ReactDOM.render() to hydrate server-rendered markup ' +
+ 'will stop working in React v17. Replace the ReactDOM.render() call ' +
+ 'with ReactDOM.hydrate() if you want React to attach to the server HTML.',
+ );
+
// New explicit API
container = document.createElement('div');
container.innerHTML = markup;
ReactDOM.hydrate(, container);
- if (__DEV__) {
- expect(console.warn.calls.count()).toBe(0);
- }
});
it('should react to state changes from callbacks', () => {
@@ -234,8 +226,6 @@ describe('ReactCompositeComponent', () => {
});
it('should warn about `forceUpdate` on unmounted components', () => {
- spyOnDev(console, 'error');
-
const container = document.createElement('div');
document.body.appendChild(container);
@@ -251,32 +241,20 @@ describe('ReactCompositeComponent', () => {
instance = ReactDOM.render(instance, container);
instance.forceUpdate();
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(0);
- }
-
ReactDOM.unmountComponentAtNode(container);
- instance.forceUpdate();
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toContain(
- 'Can only update a mounted or mounting component. This usually means ' +
- 'you called setState, replaceState, or forceUpdate on an unmounted ' +
- 'component. This is a no-op.\n\nPlease check the code for the ' +
- 'Component component.',
- );
- }
+ expect(() => instance.forceUpdate()).toWarnDev(
+ 'Can only update a mounted or mounting component. This usually means ' +
+ 'you called setState, replaceState, or forceUpdate on an unmounted ' +
+ 'component. This is a no-op.\n\nPlease check the code for the ' +
+ 'Component component.',
+ );
+ // No additional warning should be recorded
instance.forceUpdate();
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- }
});
it('should warn about `setState` on unmounted components', () => {
- spyOnDev(console, 'error');
-
const container = document.createElement('div');
document.body.appendChild(container);
@@ -300,26 +278,20 @@ describe('ReactCompositeComponent', () => {
instance.setState({value: 1});
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(0);
- }
-
expect(renders).toBe(2);
ReactDOM.unmountComponentAtNode(container);
- instance.setState({value: 2});
- expect(renders).toBe(2);
+ expect(() => {
+ instance.setState({value: 2});
+ }).toWarnDev(
+ 'Can only update a mounted or mounting component. This usually means ' +
+ 'you called setState, replaceState, or forceUpdate on an unmounted ' +
+ 'component. This is a no-op.\n\nPlease check the code for the ' +
+ 'Component component.',
+ );
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toContain(
- 'Can only update a mounted or mounting component. This usually means ' +
- 'you called setState, replaceState, or forceUpdate on an unmounted ' +
- 'component. This is a no-op.\n\nPlease check the code for the ' +
- 'Component component.',
- );
- }
+ expect(renders).toBe(2);
});
it('should silently allow `setState`, not call cb on unmounting components', () => {
@@ -351,32 +323,24 @@ describe('ReactCompositeComponent', () => {
});
it('should warn when rendering a class with a render method that does not extend React.Component', () => {
- spyOnDev(console, 'error');
const container = document.createElement('div');
class ClassWithRenderNotExtended {
render() {
return ;
}
}
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(0);
- }
expect(() => {
- ReactDOM.render(, container);
- }).toThrow(TypeError);
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toContain(
+ expect(() => {
+ ReactDOM.render(, container);
+ }).toWarnDev(
'Warning: The component appears to have a render method, ' +
"but doesn't extend React.Component. This is likely to cause errors. " +
'Change ClassWithRenderNotExtended to extend React.Component instead.',
);
- }
+ }).toThrow(TypeError);
});
it('should warn about `setState` in render', () => {
- spyOnDev(console, 'error');
-
const container = document.createElement('div');
let renderedState = -1;
@@ -395,21 +359,16 @@ describe('ReactCompositeComponent', () => {
}
}
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(0);
- }
-
- const instance = ReactDOM.render(, container);
+ let instance;
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toContain(
- 'Cannot update during an existing state transition (such as within ' +
- "`render` or another component's constructor). Render methods should " +
- 'be a pure function of props and state; constructor side-effects are ' +
- 'an anti-pattern, but can be moved to `componentWillMount`.',
- );
- }
+ expect(() => {
+ instance = ReactDOM.render(, container);
+ }).toWarnDev(
+ 'Cannot update during an existing state transition (such as within ' +
+ "`render` or another component's constructor). Render methods should " +
+ 'be a pure function of props and state; constructor side-effects are ' +
+ 'an anti-pattern, but can be moved to `componentWillMount`.',
+ );
// The setState call is queued and then executed as a second pass. This
// behavior is undefined though so we're free to change it to suit the
@@ -424,17 +383,12 @@ describe('ReactCompositeComponent', () => {
expect(renderedState).toBe(1);
expect(instance2.state.value).toBe(1);
- // Test deduplication
+ // Test deduplication; (no additional warnings are expected).
ReactDOM.unmountComponentAtNode(container);
ReactDOM.render(, container);
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- }
});
it('should warn about `setState` in getChildContext', () => {
- spyOnDev(console, 'error');
-
const container = document.createElement('div');
let renderPasses = 0;
@@ -455,25 +409,20 @@ describe('ReactCompositeComponent', () => {
}
Component.childContextTypes = {};
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(0);
- }
- const instance = ReactDOM.render(, container);
+ let instance;
+
+ expect(() => {
+ instance = ReactDOM.render(, container);
+ }).toWarnDev(
+ 'Warning: setState(...): Cannot call setState() inside getChildContext()',
+ );
+
expect(renderPasses).toBe(2);
expect(instance.state.value).toBe(1);
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: setState(...): Cannot call setState() inside getChildContext()',
- );
- }
- // Test deduplication
+ // Test deduplication; (no additional warnings are expected).
ReactDOM.unmountComponentAtNode(container);
ReactDOM.render(, container);
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- }
});
it('should cleanup even if render() fatals', () => {
@@ -487,7 +436,7 @@ describe('ReactCompositeComponent', () => {
expect(ReactCurrentOwner.current).toBe(null);
- expect(function() {
+ expect(() => {
instance = ReactTestUtils.renderIntoDocument(instance);
}).toThrow();
@@ -525,8 +474,6 @@ describe('ReactCompositeComponent', () => {
});
it('should warn when shouldComponentUpdate() returns undefined', () => {
- spyOnDev(console, 'error');
-
class Component extends React.Component {
state = {bogus: false};
@@ -540,20 +487,14 @@ describe('ReactCompositeComponent', () => {
}
const instance = ReactTestUtils.renderIntoDocument();
- instance.setState({bogus: true});
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: Component.shouldComponentUpdate(): Returned undefined instead of a ' +
- 'boolean value. Make sure to return true or false.',
- );
- }
+ expect(() => instance.setState({bogus: true})).toWarnDev(
+ 'Warning: Component.shouldComponentUpdate(): Returned undefined instead of a ' +
+ 'boolean value. Make sure to return true or false.',
+ );
});
it('should warn when componentDidUnmount method is defined', () => {
- spyOnDev(console, 'error');
-
class Component extends React.Component {
componentDidUnmount = () => {};
@@ -562,21 +503,14 @@ describe('ReactCompositeComponent', () => {
}
}
- ReactTestUtils.renderIntoDocument();
-
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: Component has a method called ' +
- 'componentDidUnmount(). But there is no such lifecycle method. ' +
- 'Did you mean componentWillUnmount()?',
- );
- }
+ expect(() => ReactTestUtils.renderIntoDocument()).toWarnDev(
+ 'Warning: Component has a method called ' +
+ 'componentDidUnmount(). But there is no such lifecycle method. ' +
+ 'Did you mean componentWillUnmount()?',
+ );
});
it('should warn when componentDidReceiveProps method is defined', () => {
- spyOnDev(console, 'error');
-
class Component extends React.Component {
componentDidReceiveProps = () => {};
@@ -585,23 +519,16 @@ describe('ReactCompositeComponent', () => {
}
}
- ReactTestUtils.renderIntoDocument();
-
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: Component has a method called ' +
- 'componentDidReceiveProps(). But there is no such lifecycle method. ' +
- 'If you meant to update the state in response to changing props, ' +
- 'use componentWillReceiveProps(). If you meant to fetch data or ' +
- 'run side-effects or mutations after React has updated the UI, use componentDidUpdate().',
- );
- }
+ expect(() => ReactTestUtils.renderIntoDocument()).toWarnDev(
+ 'Warning: Component has a method called ' +
+ 'componentDidReceiveProps(). But there is no such lifecycle method. ' +
+ 'If you meant to update the state in response to changing props, ' +
+ 'use componentWillReceiveProps(). If you meant to fetch data or ' +
+ 'run side-effects or mutations after React has updated the UI, use componentDidUpdate().',
+ );
});
it('should warn when defaultProps was defined as an instance property', () => {
- spyOnDev(console, 'error');
-
class Component extends React.Component {
constructor(props) {
super(props);
@@ -613,15 +540,10 @@ describe('ReactCompositeComponent', () => {
}
}
- ReactTestUtils.renderIntoDocument();
-
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: Setting defaultProps as an instance property on Component is not supported ' +
- 'and will be ignored. Instead, define defaultProps as a static property on Component.',
- );
- }
+ expect(() => ReactTestUtils.renderIntoDocument()).toWarnDev(
+ 'Warning: Setting defaultProps as an instance property on Component is not supported ' +
+ 'and will be ignored. Instead, define defaultProps as a static property on Component.',
+ );
});
it('should pass context to children when not owner', () => {
@@ -1093,8 +1015,6 @@ describe('ReactCompositeComponent', () => {
});
it('should disallow nested render calls', () => {
- spyOnDev(console, 'error');
-
class Inner extends React.Component {
render() {
return ;
@@ -1108,16 +1028,12 @@ describe('ReactCompositeComponent', () => {
}
}
- ReactTestUtils.renderIntoDocument();
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toMatch(
- 'Render methods should be a pure function of props and state; ' +
- 'triggering nested component updates from render is not allowed. If ' +
- 'necessary, trigger nested updates in componentDidUpdate.\n\nCheck the ' +
- 'render method of Outer.',
- );
- }
+ expect(() => ReactTestUtils.renderIntoDocument()).toWarnDev(
+ 'Render methods should be a pure function of props and state; ' +
+ 'triggering nested component updates from render is not allowed. If ' +
+ 'necessary, trigger nested updates in componentDidUpdate.\n\nCheck the ' +
+ 'render method of Outer.',
+ );
});
it('only renders once if updated in componentWillReceiveProps', () => {
@@ -1392,8 +1308,6 @@ describe('ReactCompositeComponent', () => {
});
it('should warn when mutated props are passed', () => {
- spyOnDev(console, 'error');
-
const container = document.createElement('div');
class Foo extends React.Component {
@@ -1407,19 +1321,10 @@ describe('ReactCompositeComponent', () => {
}
}
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(0);
- }
-
- ReactDOM.render(, container);
-
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toContain(
- 'Foo(...): When calling super() in `Foo`, make sure to pass ' +
- "up the same props that your component's constructor was passed.",
- );
- }
+ expect(() => ReactDOM.render(, container)).toWarnDev(
+ 'Foo(...): When calling super() in `Foo`, make sure to pass ' +
+ "up the same props that your component's constructor was passed.",
+ );
});
it('should only call componentWillUnmount once', () => {
@@ -1456,7 +1361,7 @@ describe('ReactCompositeComponent', () => {
}
};
- expect(function() {
+ expect(() => {
ReactDOM.render(, container);
ReactDOM.render(, container);
}).toThrow();
@@ -1702,7 +1607,6 @@ describe('ReactCompositeComponent', () => {
});
it('should return a meaningful warning when constructor is returned', () => {
- spyOnDev(console, 'error');
class RenderTextInvalidConstructor extends React.Component {
constructor(props) {
super(props);
@@ -1714,33 +1618,26 @@ describe('ReactCompositeComponent', () => {
}
}
- expect(function() {
- ReactTestUtils.renderIntoDocument();
- }).toThrow();
-
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.mostRecent().args[0]).toBe(
+ expect(() => {
+ expect(() => {
+ ReactTestUtils.renderIntoDocument();
+ }).toWarnDev(
'Warning: RenderTextInvalidConstructor(...): No `render` method found on the returned component instance: ' +
'did you accidentally return an object from the constructor?',
);
- }
+ }).toThrow();
});
it('should return error if render is not defined', () => {
- spyOnDev(console, 'error');
class RenderTestUndefinedRender extends React.Component {}
- expect(function() {
- ReactTestUtils.renderIntoDocument();
- }).toThrow();
-
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.mostRecent().args[0]).toBe(
+ expect(() => {
+ expect(() => {
+ ReactTestUtils.renderIntoDocument();
+ }).toWarnDev(
'Warning: RenderTestUndefinedRender(...): No `render` method found on the returned ' +
'component instance: you may have forgotten to define `render`.',
);
- }
+ }).toThrow();
});
});
diff --git a/packages/react-dom/src/__tests__/ReactCompositeComponentState-test.js b/packages/react-dom/src/__tests__/ReactCompositeComponentState-test.js
index c69e237c4e93a..c7135984d2760 100644
--- a/packages/react-dom/src/__tests__/ReactCompositeComponentState-test.js
+++ b/packages/react-dom/src/__tests__/ReactCompositeComponentState-test.js
@@ -17,7 +17,6 @@ let TestComponent;
describe('ReactCompositeComponent-state', () => {
beforeEach(() => {
React = require('react');
-
ReactDOM = require('react-dom');
TestComponent = class extends React.Component {
@@ -381,8 +380,6 @@ describe('ReactCompositeComponent-state', () => {
});
it('should treat assigning to this.state inside cWRP as a replaceState, with a warning', () => {
- spyOnDev(console, 'error');
-
let ops = [];
class Test extends React.Component {
state = {step: 1, extra: true};
@@ -409,27 +406,20 @@ describe('ReactCompositeComponent-state', () => {
const container = document.createElement('div');
ReactDOM.render(, container);
// Update
- ReactDOM.render(, container);
+ expect(() => ReactDOM.render(, container)).toWarnDev(
+ 'Warning: Test.componentWillReceiveProps(): Assigning directly to ' +
+ "this.state is deprecated (except inside a component's constructor). " +
+ 'Use setState instead.',
+ );
expect(ops).toEqual([
'render -- step: 1, extra: true',
'render -- step: 3, extra: false',
'callback -- step: 3, extra: false',
]);
- if (__DEV__) {
- expect(console.error.calls.count()).toEqual(1);
- expect(console.error.calls.argsFor(0)[0]).toEqual(
- 'Warning: Test.componentWillReceiveProps(): Assigning directly to ' +
- "this.state is deprecated (except inside a component's constructor). " +
- 'Use setState instead.',
- );
- }
- // Check deduplication
+ // Check deduplication; (no additional warnings are expected)
ReactDOM.render(, container);
- if (__DEV__) {
- expect(console.error.calls.count()).toEqual(1);
- }
});
it('should treat assigning to this.state inside cWM as a replaceState, with a warning', () => {
@@ -459,19 +449,15 @@ describe('ReactCompositeComponent-state', () => {
// Mount
const container = document.createElement('div');
- ReactDOM.render(, container);
+ expect(() => ReactDOM.render(, container)).toWarnDev(
+ 'Warning: Test.componentWillMount(): Assigning directly to ' +
+ "this.state is deprecated (except inside a component's constructor). " +
+ 'Use setState instead.',
+ );
expect(ops).toEqual([
'render -- step: 3, extra: false',
'callback -- step: 3, extra: false',
]);
- if (__DEV__) {
- expect(console.error.calls.count()).toEqual(1);
- expect(console.error.calls.argsFor(0)[0]).toEqual(
- 'Warning: Test.componentWillMount(): Assigning directly to ' +
- "this.state is deprecated (except inside a component's constructor). " +
- 'Use setState instead.',
- );
- }
});
});
diff --git a/packages/react-dom/src/__tests__/ReactDOM-test.js b/packages/react-dom/src/__tests__/ReactDOM-test.js
index 15148fed5be61..dd7f97484b6d8 100644
--- a/packages/react-dom/src/__tests__/ReactDOM-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOM-test.js
@@ -109,8 +109,6 @@ describe('ReactDOM', () => {
});
it('throws in render() if the mount callback is not a function', () => {
- spyOnDev(console, 'error');
-
function Foo() {
this.a = 1;
this.b = 2;
@@ -125,42 +123,44 @@ describe('ReactDOM', () => {
}
const myDiv = document.createElement('div');
- expect(() => ReactDOM.render(, myDiv, 'no')).toThrowError(
- 'Invalid argument passed as callback. Expected a function. Instead ' +
- 'received: no',
- );
- if (__DEV__) {
- expect(console.error.calls.argsFor(0)[0]).toContain(
+ expect(() => {
+ expect(() => {
+ ReactDOM.render(, myDiv, 'no');
+ }).toWarnDev(
'render(...): Expected the last optional `callback` argument to be ' +
'a function. Instead received: no.',
);
- }
- expect(() => ReactDOM.render(, myDiv, {foo: 'bar'})).toThrowError(
+ }).toThrowError(
'Invalid argument passed as callback. Expected a function. Instead ' +
- 'received: [object Object]',
+ 'received: no',
);
- if (__DEV__) {
- expect(console.error.calls.argsFor(1)[0]).toContain(
+
+ expect(() => {
+ expect(() => {
+ ReactDOM.render(, myDiv, {foo: 'bar'});
+ }).toWarnDev(
'render(...): Expected the last optional `callback` argument to be ' +
'a function. Instead received: [object Object].',
);
- }
- expect(() => ReactDOM.render(, myDiv, new Foo())).toThrowError(
+ }).toThrowError(
'Invalid argument passed as callback. Expected a function. Instead ' +
'received: [object Object]',
);
- if (__DEV__) {
- expect(console.error.calls.argsFor(2)[0]).toContain(
+
+ expect(() => {
+ expect(() => {
+ ReactDOM.render(, myDiv, new Foo());
+ }).toWarnDev(
'render(...): Expected the last optional `callback` argument to be ' +
'a function. Instead received: [object Object].',
);
- expect(console.error.calls.count()).toBe(3);
- }
+ }).toThrowError(
+ 'Invalid argument passed as callback. Expected a function. Instead ' +
+ 'received: [object Object]',
+ );
});
it('throws in render() if the update callback is not a function', () => {
- spyOnDev(console, 'error');
-
function Foo() {
this.a = 1;
this.b = 2;
@@ -176,39 +176,43 @@ describe('ReactDOM', () => {
const myDiv = document.createElement('div');
ReactDOM.render(, myDiv);
- expect(() => ReactDOM.render(, myDiv, 'no')).toThrowError(
- 'Invalid argument passed as callback. Expected a function. Instead ' +
- 'received: no',
- );
- if (__DEV__) {
- expect(console.error.calls.argsFor(0)[0]).toContain(
+ expect(() => {
+ expect(() => {
+ ReactDOM.render(, myDiv, 'no');
+ }).toWarnDev(
'render(...): Expected the last optional `callback` argument to be ' +
'a function. Instead received: no.',
);
- }
- ReactDOM.render(, myDiv); // Re-mount
- expect(() => ReactDOM.render(, myDiv, {foo: 'bar'})).toThrowError(
+ }).toThrowError(
'Invalid argument passed as callback. Expected a function. Instead ' +
- 'received: [object Object]',
+ 'received: no',
);
- if (__DEV__) {
- expect(console.error.calls.argsFor(1)[0]).toContain(
+
+ ReactDOM.render(, myDiv); // Re-mount
+ expect(() => {
+ expect(() => {
+ ReactDOM.render(, myDiv, {foo: 'bar'});
+ }).toWarnDev(
'render(...): Expected the last optional `callback` argument to be ' +
'a function. Instead received: [object Object].',
);
- }
- ReactDOM.render(, myDiv); // Re-mount
- expect(() => ReactDOM.render(, myDiv, new Foo())).toThrowError(
+ }).toThrowError(
'Invalid argument passed as callback. Expected a function. Instead ' +
'received: [object Object]',
);
- if (__DEV__) {
- expect(console.error.calls.argsFor(2)[0]).toContain(
+
+ ReactDOM.render(, myDiv); // Re-mount
+ expect(() => {
+ expect(() => {
+ ReactDOM.render(, myDiv, new Foo());
+ }).toWarnDev(
'render(...): Expected the last optional `callback` argument to be ' +
'a function. Instead received: [object Object].',
);
- expect(console.error.calls.count()).toBe(3);
- }
+ }).toThrowError(
+ 'Invalid argument passed as callback. Expected a function. Instead ' +
+ 'received: [object Object]',
+ );
});
it('preserves focus', () => {
@@ -375,28 +379,24 @@ describe('ReactDOM', () => {
// https://github.com/facebook/react/issues/11689
it('should warn when attempting to inject an event plugin', () => {
- spyOnDev(console, 'warn');
- ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.EventPluginHub.injection.injectEventPluginsByName(
- {
- TapEventPlugin: {
- extractEvents() {},
+ expect(() => {
+ ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.EventPluginHub.injection.injectEventPluginsByName(
+ {
+ TapEventPlugin: {
+ extractEvents() {},
+ },
},
- },
- );
- if (__DEV__) {
- expect(console.warn.calls.count()).toBe(1);
- expect(console.warn.calls.argsFor(0)[0]).toContain(
- 'Injecting custom event plugins (TapEventPlugin) is deprecated ' +
- 'and will not work in React 17+. Please update your code ' +
- 'to not depend on React internals. The stack trace for this ' +
- 'warning should reveal the library that is using them. ' +
- 'See https://github.com/facebook/react/issues/11689 for a discussion.',
);
- }
+ }).toLowPriorityWarnDev(
+ 'Injecting custom event plugins (TapEventPlugin) is deprecated ' +
+ 'and will not work in React 17+. Please update your code ' +
+ 'to not depend on React internals. The stack trace for this ' +
+ 'warning should reveal the library that is using them. ' +
+ 'See https://github.com/facebook/react/issues/11689 for a discussion.',
+ );
});
it('throws in DEV if jsdom is destroyed by the time setState() is called', () => {
- spyOnDev(console, 'error');
class App extends React.Component {
state = {x: 1};
render() {
diff --git a/packages/react-dom/src/__tests__/ReactDOMAttribute-test.js b/packages/react-dom/src/__tests__/ReactDOMAttribute-test.js
index 462f76be9ff08..c952c4b97a4dd 100644
--- a/packages/react-dom/src/__tests__/ReactDOMAttribute-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMAttribute-test.js
@@ -19,10 +19,6 @@ describe('ReactDOM unknown attribute', () => {
ReactDOM = require('react-dom');
});
- function normalizeCodeLocInfo(str) {
- return str && str.replace(/\(at .+?:\d+\)/g, '(at **)');
- }
-
function testUnknownAttributeRemoval(givenValue) {
const el = document.createElement('div');
ReactDOM.render(, el);
@@ -46,20 +42,13 @@ describe('ReactDOM unknown attribute', () => {
});
it('changes values true, false to null, and also warns once', () => {
- spyOnDev(console, 'error');
-
- testUnknownAttributeAssignment(true, null);
+ expect(() => testUnknownAttributeAssignment(true, null)).toWarnDev(
+ 'Received `true` for a non-boolean attribute `unknown`.\n\n' +
+ 'If you want to write it to the DOM, pass a string instead: ' +
+ 'unknown="true" or unknown={value.toString()}.\n' +
+ ' in div (at **)',
+ );
testUnknownAttributeAssignment(false, null);
-
- if (__DEV__) {
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toMatch(
- 'Received `true` for a non-boolean attribute `unknown`.\n\n' +
- 'If you want to write it to the DOM, pass a string instead: ' +
- 'unknown="true" or unknown={value.toString()}.\n' +
- ' in div (at **)',
- );
- expect(console.error.calls.count()).toBe(1);
- }
});
it('removes unknown attributes that were rendered but are now missing', () => {
@@ -82,17 +71,11 @@ describe('ReactDOM unknown attribute', () => {
});
it('coerces NaN to strings and warns', () => {
- spyOnDev(console, 'error');
-
- testUnknownAttributeAssignment(NaN, 'NaN');
- if (__DEV__) {
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toMatch(
- 'Warning: Received NaN for the `unknown` attribute. ' +
- 'If this is expected, cast the value to a string.\n' +
- ' in div (at **)',
- );
- expect(console.error.calls.count()).toBe(1);
- }
+ expect(() => testUnknownAttributeAssignment(NaN, 'NaN')).toWarnDev(
+ 'Warning: Received NaN for the `unknown` attribute. ' +
+ 'If this is expected, cast the value to a string.\n' +
+ ' in div (at **)',
+ );
});
it('coerces objects to strings and warns', () => {
@@ -107,54 +90,41 @@ describe('ReactDOM unknown attribute', () => {
});
it('removes symbols and warns', () => {
- spyOnDev(console, 'error');
-
- testUnknownAttributeRemoval(Symbol('foo'));
- if (__DEV__) {
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Invalid value for prop `unknown` on
tag. Either remove it ' +
- 'from the element, or pass a string or number value to keep it ' +
- 'in the DOM. For details, see https://fb.me/react-attribute-behavior\n' +
- ' in div (at **)',
- );
- expect(console.error.calls.count()).toBe(1);
- }
+ expect(() => testUnknownAttributeRemoval(Symbol('foo'))).toWarnDev(
+ 'Warning: Invalid value for prop `unknown` on
tag. Either remove it ' +
+ 'from the element, or pass a string or number value to keep it ' +
+ 'in the DOM. For details, see https://fb.me/react-attribute-behavior\n' +
+ ' in div (at **)',
+ );
});
it('removes functions and warns', () => {
- spyOnDev(console, 'error');
-
- testUnknownAttributeRemoval(function someFunction() {});
- if (__DEV__) {
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Invalid value for prop `unknown` on
tag. Either remove ' +
- 'it from the element, or pass a string or number value to ' +
- 'keep it in the DOM. For details, see ' +
- 'https://fb.me/react-attribute-behavior\n' +
- ' in div (at **)',
- );
- expect(console.error.calls.count()).toBe(1);
- }
+ expect(() =>
+ testUnknownAttributeRemoval(function someFunction() {}),
+ ).toWarnDev(
+ 'Warning: Invalid value for prop `unknown` on
tag. Either remove ' +
+ 'it from the element, or pass a string or number value to ' +
+ 'keep it in the DOM. For details, see ' +
+ 'https://fb.me/react-attribute-behavior\n' +
+ ' in div (at **)',
+ );
});
it('allows camelCase unknown attributes and warns', () => {
- spyOnDev(console, 'error');
-
const el = document.createElement('div');
- ReactDOM.render(, el);
- expect(el.firstChild.getAttribute('helloworld')).toBe('something');
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toMatch(
- 'React does not recognize the `helloWorld` prop on a DOM element. ' +
- 'If you intentionally want it to appear in the DOM as a custom ' +
- 'attribute, spell it as lowercase `helloworld` instead. ' +
- 'If you accidentally passed it from a parent component, remove ' +
- 'it from the DOM element.\n' +
- ' in div (at **)',
- );
- }
+ expect(() =>
+ ReactDOM.render(, el),
+ ).toWarnDev(
+ 'React does not recognize the `helloWorld` prop on a DOM element. ' +
+ 'If you intentionally want it to appear in the DOM as a custom ' +
+ 'attribute, spell it as lowercase `helloworld` instead. ' +
+ 'If you accidentally passed it from a parent component, remove ' +
+ 'it from the DOM element.\n' +
+ ' in div (at **)',
+ );
+
+ expect(el.firstChild.getAttribute('helloworld')).toBe('something');
});
});
});
diff --git a/packages/react-dom/src/__tests__/ReactDOMComponent-test.js b/packages/react-dom/src/__tests__/ReactDOMComponent-test.js
index 46961e7f3c347..6a8e488ac6987 100644
--- a/packages/react-dom/src/__tests__/ReactDOMComponent-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMComponent-test.js
@@ -147,110 +147,97 @@ describe('ReactDOMComponent', () => {
});
it('should warn for unknown prop', () => {
- spyOnDev(console, 'error');
const container = document.createElement('div');
- ReactDOM.render(
{}} />, container);
- if (__DEV__) {
- expect(console.error.calls.count(0)).toBe(1);
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Invalid value for prop `foo` on
tag. Either remove it ' +
- 'from the element, or pass a string or number value to keep ' +
- 'it in the DOM. For details, see https://fb.me/react-attribute-behavior' +
- '\n in div (at **)',
- );
- }
+ expect(() =>
+ ReactDOM.render(
{}} />, container),
+ ).toWarnDev(
+ 'Warning: Invalid value for prop `foo` on
tag. Either remove it ' +
+ 'from the element, or pass a string or number value to keep ' +
+ 'it in the DOM. For details, see https://fb.me/react-attribute-behavior' +
+ '\n in div (at **)',
+ );
});
it('should group multiple unknown prop warnings together', () => {
- spyOnDev(console, 'error');
const container = document.createElement('div');
- ReactDOM.render(
{}} baz={() => {}} />, container);
- if (__DEV__) {
- expect(console.error.calls.count(0)).toBe(1);
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Invalid values for props `foo`, `baz` on
tag. Either remove ' +
- 'them from the element, or pass a string or number value to keep ' +
- 'them in the DOM. For details, see https://fb.me/react-attribute-behavior' +
- '\n in div (at **)',
- );
- }
+ expect(() =>
+ ReactDOM.render(
{}} baz={() => {}} />, container),
+ ).toWarnDev(
+ 'Warning: Invalid values for props `foo`, `baz` on
tag. Either remove ' +
+ 'them from the element, or pass a string or number value to keep ' +
+ 'them in the DOM. For details, see https://fb.me/react-attribute-behavior' +
+ '\n in div (at **)',
+ );
});
it('should warn for onDblClick prop', () => {
- spyOnDev(console, 'error');
const container = document.createElement('div');
- ReactDOM.render(
{}} />, container);
- if (__DEV__) {
- expect(console.error.calls.count(0)).toBe(1);
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Invalid event handler property `onDblClick`. Did you mean `onDoubleClick`?\n in div (at **)',
- );
- }
+ expect(() =>
+ ReactDOM.render(
{}} />, container),
+ ).toWarnDev(
+ 'Warning: Invalid event handler property `onDblClick`. Did you mean `onDoubleClick`?\n in div (at **)',
+ );
});
it('should warn for unknown string event handlers', () => {
- spyOnDev(console, 'error');
const container = document.createElement('div');
- ReactDOM.render(, container);
+ expect(() =>
+ ReactDOM.render(, container),
+ ).toWarnDev(
+ 'Warning: Unknown event handler property `onUnknown`. It will be ignored.\n in div (at **)',
+ );
expect(container.firstChild.hasAttribute('onUnknown')).toBe(false);
expect(container.firstChild.onUnknown).toBe(undefined);
- ReactDOM.render(, container);
+ expect(() =>
+ ReactDOM.render(, container),
+ ).toWarnDev(
+ 'Warning: Unknown event handler property `onunknown`. It will be ignored.\n in div (at **)',
+ );
expect(container.firstChild.hasAttribute('onunknown')).toBe(false);
expect(container.firstChild.onunknown).toBe(undefined);
- ReactDOM.render(, container);
+ expect(() =>
+ ReactDOM.render(
+ ,
+ container,
+ ),
+ ).toWarnDev(
+ 'Warning: Unknown event handler property `on-unknown`. It will be ignored.\n in div (at **)',
+ );
expect(container.firstChild.hasAttribute('on-unknown')).toBe(false);
expect(container.firstChild['on-unknown']).toBe(undefined);
- if (__DEV__) {
- expect(console.error.calls.count(0)).toBe(3);
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Unknown event handler property `onUnknown`. It will be ignored.\n in div (at **)',
- );
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toBe(
- 'Warning: Unknown event handler property `onunknown`. It will be ignored.\n in div (at **)',
- );
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(2)[0])).toBe(
- 'Warning: Unknown event handler property `on-unknown`. It will be ignored.\n in div (at **)',
- );
- }
});
it('should warn for unknown function event handlers', () => {
- spyOnDev(console, 'error');
const container = document.createElement('div');
- ReactDOM.render(, container);
+ expect(() =>
+ ReactDOM.render(, container),
+ ).toWarnDev(
+ 'Warning: Unknown event handler property `onUnknown`. It will be ignored.\n in div (at **)',
+ );
expect(container.firstChild.hasAttribute('onUnknown')).toBe(false);
expect(container.firstChild.onUnknown).toBe(undefined);
- ReactDOM.render(, container);
+ expect(() =>
+ ReactDOM.render(, container),
+ ).toWarnDev(
+ 'Warning: Unknown event handler property `onunknown`. It will be ignored.\n in div (at **)',
+ );
expect(container.firstChild.hasAttribute('onunknown')).toBe(false);
expect(container.firstChild.onunknown).toBe(undefined);
- ReactDOM.render(, container);
+ expect(() =>
+ ReactDOM.render(, container),
+ ).toWarnDev(
+ 'Warning: Unknown event handler property `on-unknown`. It will be ignored.\n in div (at **)',
+ );
expect(container.firstChild.hasAttribute('on-unknown')).toBe(false);
expect(container.firstChild['on-unknown']).toBe(undefined);
- if (__DEV__) {
- expect(console.error.calls.count(0)).toBe(3);
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Unknown event handler property `onUnknown`. It will be ignored.\n in div (at **)',
- );
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toBe(
- 'Warning: Unknown event handler property `onunknown`. It will be ignored.\n in div (at **)',
- );
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(2)[0])).toBe(
- 'Warning: Unknown event handler property `on-unknown`. It will be ignored.\n in div (at **)',
- );
- }
});
it('should warn for badly cased React attributes', () => {
- spyOnDev(console, 'error');
const container = document.createElement('div');
- ReactDOM.render(, container);
+ expect(() => ReactDOM.render(, container)).toWarnDev(
+ 'Warning: Invalid DOM property `CHILDREN`. Did you mean `children`?\n in div (at **)',
+ );
expect(container.firstChild.getAttribute('CHILDREN')).toBe('5');
- if (__DEV__) {
- expect(console.error.calls.count(0)).toBe(1);
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Invalid DOM property `CHILDREN`. Did you mean `children`?\n in div (at **)',
- );
- }
});
it('should not warn for "0" as a unitless style value', () => {
@@ -264,20 +251,13 @@ describe('ReactDOMComponent', () => {
});
it('should warn nicely about NaN in style', () => {
- spyOnDev(console, 'error');
-
const style = {fontSize: NaN};
const div = document.createElement('div');
+ expect(() => ReactDOM.render(, div)).toWarnDev(
+ 'Warning: `NaN` is an invalid value for the `fontSize` css style property.' +
+ '\n in span (at **)',
+ );
ReactDOM.render(, div);
- ReactDOM.render(, div);
-
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toEqual(
- 'Warning: `NaN` is an invalid value for the `fontSize` css style property.' +
- '\n in span (at **)',
- );
- }
});
it('should update styles if initially null', () => {
@@ -575,44 +555,38 @@ describe('ReactDOMComponent', () => {
});
it('should reject attribute key injection attack on markup', () => {
- spyOnDev(console, 'error');
- for (let i = 0; i < 3; i++) {
- const container = document.createElement('div');
- const element = React.createElement(
- 'x-foo-component',
- {'blah" onclick="beevil" noise="hi': 'selected'},
- null,
- );
- ReactDOM.render(element, container);
- }
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toEqual(
- 'Warning: Invalid attribute name: `blah" onclick="beevil" noise="hi`',
- );
- }
+ expect(() => {
+ for (let i = 0; i < 3; i++) {
+ const container = document.createElement('div');
+ const element = React.createElement(
+ 'x-foo-component',
+ {'blah" onclick="beevil" noise="hi': 'selected'},
+ null,
+ );
+ ReactDOM.render(element, container);
+ }
+ }).toWarnDev(
+ 'Warning: Invalid attribute name: `blah" onclick="beevil" noise="hi`',
+ );
});
it('should reject attribute key injection attack on update', () => {
- spyOnDev(console, 'error');
- for (let i = 0; i < 3; i++) {
- const container = document.createElement('div');
- const beforeUpdate = React.createElement('x-foo-component', {}, null);
- ReactDOM.render(beforeUpdate, container);
-
- const afterUpdate = React.createElement(
- 'x-foo-component',
- {'blah" onclick="beevil" noise="hi': 'selected'},
- null,
- );
- ReactDOM.render(afterUpdate, container);
- }
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toEqual(
- 'Warning: Invalid attribute name: `blah" onclick="beevil" noise="hi`',
- );
- }
+ expect(() => {
+ for (let i = 0; i < 3; i++) {
+ const container = document.createElement('div');
+ const beforeUpdate = React.createElement('x-foo-component', {}, null);
+ ReactDOM.render(beforeUpdate, container);
+
+ const afterUpdate = React.createElement(
+ 'x-foo-component',
+ {'blah" onclick="beevil" noise="hi': 'selected'},
+ null,
+ );
+ ReactDOM.render(afterUpdate, container);
+ }
+ }).toWarnDev(
+ 'Warning: Invalid attribute name: `blah" onclick="beevil" noise="hi`',
+ );
});
it('should update arbitrary attributes for tags containing dashes', () => {
@@ -857,17 +831,13 @@ describe('ReactDOMComponent', () => {
});
it('should warn about non-string "is" attribute', () => {
- spyOnDev(console, 'error');
const container = document.createElement('div');
- ReactDOM.render(, container);
-
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toContain(
- 'Received a `function` for a string attribute `is`. If this is expected, cast ' +
- 'the value to a string.',
- );
- }
+ expect(() =>
+ ReactDOM.render(, container),
+ ).toWarnDev(
+ 'Received a `function` for a string attribute `is`. If this is expected, cast ' +
+ 'the value to a string.',
+ );
});
it('should not update when switching between null/undefined', () => {
@@ -1020,59 +990,41 @@ describe('ReactDOMComponent', () => {
});
it('should not duplicate uppercased selfclosing tags', () => {
- spyOnDev(console, 'error');
class Container extends React.Component {
render() {
return React.createElement('BR', null);
}
}
- const returnedValue = ReactDOMServer.renderToString();
+ let returnedValue;
+
+ expect(() => {
+ returnedValue = ReactDOMServer.renderToString();
+ }).toWarnDev(' is using uppercase HTML.');
expect(returnedValue).not.toContain('');
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toContain(
- ' is using uppercase HTML.',
- );
- }
});
it('should warn on upper case HTML tags, not SVG nor custom tags', () => {
- spyOnDev(console, 'error');
ReactTestUtils.renderIntoDocument(
React.createElement('svg', null, React.createElement('PATH')),
);
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(0);
- }
ReactTestUtils.renderIntoDocument(React.createElement('CUSTOM-TAG'));
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(0);
- }
- ReactTestUtils.renderIntoDocument(React.createElement('IMG'));
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toContain(
- ' is using uppercase HTML.',
- );
- }
+
+ expect(() =>
+ ReactTestUtils.renderIntoDocument(React.createElement('IMG')),
+ ).toWarnDev(' is using uppercase HTML.');
});
it('should warn on props reserved for future use', () => {
- spyOnDev(console, 'error');
- ReactTestUtils.renderIntoDocument();
- if (__DEV__) {
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toContain(
- 'The `aria` attribute is reserved for future use in React. ' +
- 'Pass individual `aria-` attributes instead.',
- );
- }
+ expect(() =>
+ ReactTestUtils.renderIntoDocument(),
+ ).toWarnDev(
+ 'The `aria` attribute is reserved for future use in React. ' +
+ 'Pass individual `aria-` attributes instead.',
+ );
});
it('should warn if the tag is unrecognized', () => {
- spyOnDev(console, 'error');
-
let realToString;
try {
realToString = Object.prototype.toString;
@@ -1089,9 +1041,13 @@ describe('ReactDOMComponent', () => {
};
Object.prototype.toString = wrappedToString; // eslint-disable-line no-extend-native
- ReactTestUtils.renderIntoDocument();
+ expect(() => ReactTestUtils.renderIntoDocument()).toWarnDev(
+ 'The tag is unrecognized in this browser',
+ );
// Test deduplication
- ReactTestUtils.renderIntoDocument();
+ expect(() => ReactTestUtils.renderIntoDocument()).toWarnDev(
+ 'The tag is unrecognized in this browser',
+ );
ReactTestUtils.renderIntoDocument();
// This is a funny case.
// Chrome is the only major browser not shipping