Spy at warnings consistently inside test cases

We move any spies on `console.error()` from `beforeEach()` to the individual `it()` tests. This means that if a new test is introduced in these suites, it does not ignore warnings by default, but fails on any unexpected warning, which is Jest's default behavior.

We also change a few old instances of direct `console.error = jest.genMockFn()` assignment to use `spyOn()` for consistency with the rest of the tests.
This commit is contained in:
Dan Abramov
2016-03-30 21:50:12 +01:00
parent 05b05c4c81
commit b6bc4bd996
4 changed files with 80 additions and 86 deletions
@@ -31,8 +31,6 @@ describe('ReactContextValidator', function() {
ReactDOM = require('ReactDOM');
ReactTestUtils = require('ReactTestUtils');
reactComponentExpect = require('reactComponentExpect');
spyOn(console, 'error');
});
// TODO: This behavior creates a runtime dependency on propTypes. We should
@@ -133,6 +131,8 @@ describe('ReactContextValidator', function() {
});
it('should check context types', function() {
spyOn(console, 'error');
var Component = React.createClass({
contextTypes: {
foo: React.PropTypes.string.isRequired,
@@ -202,6 +202,8 @@ describe('ReactContextValidator', function() {
});
it('should check child context types', function() {
spyOn(console, 'error');
var Component = React.createClass({
childContextTypes: {
foo: React.PropTypes.string.isRequired,
@@ -21,7 +21,6 @@ describe('ReactClass-spec', function() {
React = require('React');
ReactDOM = require('ReactDOM');
ReactTestUtils = require('ReactTestUtils');
spyOn(console, 'error');
});
it('should throw when `render` is not specified', function() {
@@ -60,76 +59,62 @@ describe('ReactClass-spec', function() {
});
it('should warn on invalid prop types', function() {
var warn = console.error;
console.error = jest.genMockFn();
try {
React.createClass({
displayName: 'Component',
propTypes: {
prop: null,
},
render: function() {
return <span>{this.props.prop}</span>;
},
});
expect(console.error.mock.calls.length).toBe(1);
expect(console.error.mock.calls[0][0]).toBe(
'Warning: Component: prop type `prop` is invalid; ' +
'it must be a function, usually from React.PropTypes.'
);
} finally {
console.error = warn;
}
spyOn(console, 'error');
React.createClass({
displayName: 'Component',
propTypes: {
prop: null,
},
render: function() {
return <span>{this.props.prop}</span>;
},
});
expect(console.error.argsForCall.length).toBe(1);
expect(console.error.argsForCall[0][0]).toBe(
'Warning: Component: prop type `prop` is invalid; ' +
'it must be a function, usually from React.PropTypes.'
);
});
it('should warn on invalid context types', function() {
var warn = console.error;
console.error = jest.genMockFn();
try {
React.createClass({
displayName: 'Component',
contextTypes: {
prop: null,
},
render: function() {
return <span>{this.props.prop}</span>;
},
});
expect(console.error.mock.calls.length).toBe(1);
expect(console.error.mock.calls[0][0]).toBe(
'Warning: Component: context type `prop` is invalid; ' +
'it must be a function, usually from React.PropTypes.'
);
} finally {
console.error = warn;
}
spyOn(console, 'error');
React.createClass({
displayName: 'Component',
contextTypes: {
prop: null,
},
render: function() {
return <span>{this.props.prop}</span>;
},
});
expect(console.error.argsForCall.length).toBe(1);
expect(console.error.argsForCall[0][0]).toBe(
'Warning: Component: context type `prop` is invalid; ' +
'it must be a function, usually from React.PropTypes.'
);
});
it('should throw on invalid child context types', function() {
var warn = console.error;
console.error = jest.genMockFn();
try {
React.createClass({
displayName: 'Component',
childContextTypes: {
prop: null,
},
render: function() {
return <span>{this.props.prop}</span>;
},
});
expect(console.error.mock.calls.length).toBe(1);
expect(console.error.mock.calls[0][0]).toBe(
'Warning: Component: child context type `prop` is invalid; ' +
'it must be a function, usually from React.PropTypes.'
);
} finally {
console.error = warn;
}
spyOn(console, 'error');
React.createClass({
displayName: 'Component',
childContextTypes: {
prop: null,
},
render: function() {
return <span>{this.props.prop}</span>;
},
});
expect(console.error.argsForCall.length).toBe(1);
expect(console.error.argsForCall[0][0]).toBe(
'Warning: Component: child context type `prop` is invalid; ' +
'it must be a function, usually from React.PropTypes.'
);
});
it('should warn when mispelling shouldComponentUpdate', function() {
spyOn(console, 'error');
React.createClass({
componentShouldUpdate: function() {
return false;
@@ -163,6 +148,7 @@ describe('ReactClass-spec', function() {
});
it('should warn when mispelling componentWillReceiveProps', function() {
spyOn(console, 'error');
React.createClass({
componentWillRecieveProps: function() {
return false;
@@ -204,6 +190,7 @@ describe('ReactClass-spec', function() {
// TODO: Consider actually moving these to statics or drop this unit test.
xit('should warn when using deprecated non-static spec keys', function() {
spyOn(console, 'error');
React.createClass({
mixins: [{}],
propTypes: {
@@ -348,6 +335,7 @@ describe('ReactClass-spec', function() {
});
it('should throw when using legacy factories', function() {
spyOn(console, 'error');
var Component = React.createClass({
render() {
return <div />;
@@ -355,7 +343,7 @@ describe('ReactClass-spec', function() {
});
expect(() => Component()).toThrow();
expect(console.error.calls.length).toBe(1);
expect(console.error.argsForCall.length).toBe(1);
expect(console.error.argsForCall[0][0]).toBe(
'Warning: Something is calling a React component directly. Use a ' +
'factory or JSX instead. See: https://fb.me/react-legacyfactory'
@@ -241,7 +241,6 @@ describe('ReactPropTypes', function() {
return <div>{this.props.label}</div>;
},
});
spyOn(console, 'error');
});
it('should support components', () => {
@@ -258,6 +257,8 @@ describe('ReactPropTypes', function() {
});
it('should be able to define a single child as label', () => {
spyOn(console, 'error');
var instance = <Component label={<div />} />;
instance = ReactTestUtils.renderIntoDocument(instance);
@@ -265,6 +266,8 @@ describe('ReactPropTypes', function() {
});
it('should warn when passing no label and isRequired is set', () => {
spyOn(console, 'error');
var instance = <Component />;
instance = ReactTestUtils.renderIntoDocument(instance);
@@ -782,7 +785,6 @@ describe('ReactPropTypes', function() {
describe('Custom validator', function() {
beforeEach(function() {
jest.resetModuleRegistry();
spyOn(console, 'error');
});
it('should have been called with the right params', function() {
@@ -820,6 +822,8 @@ describe('ReactPropTypes', function() {
});
it('should have received the validator\'s return value', function() {
spyOn(console, 'error');
var spy = jasmine.createSpy().andCallFake(
function(props, propName, componentName) {
if (props[propName] !== 5) {
@@ -845,6 +849,8 @@ describe('ReactPropTypes', function() {
it('should not warn if the validator returned null',
function() {
spyOn(console, 'error');
var spy = jasmine.createSpy().andCallFake(
function(props, propName, componentName) {
return null;
@@ -68,8 +68,6 @@ describe('ReactCompositeComponent', function() {
<b></b>;
},
});
spyOn(console, 'error');
});
it('should support module pattern components', function() {
@@ -123,7 +121,6 @@ describe('ReactCompositeComponent', function() {
container.innerHTML = markup;
ReactDOM.render(<Parent />, container);
expect(console.error).not.toHaveBeenCalled();
});
it('should react to state changes from callbacks', function() {
@@ -173,6 +170,8 @@ describe('ReactCompositeComponent', function() {
});
it('should auto bind methods and values correctly', function() {
spyOn(console, 'error');
var ComponentClass = React.createClass({
getInitialState: function() {
return {valueToReturn: 'hi'};
@@ -273,6 +272,8 @@ describe('ReactCompositeComponent', function() {
});
it('should warn about `forceUpdate` on unmounted components', function() {
spyOn(console, 'error');
var container = document.createElement('div');
document.body.appendChild(container);
@@ -303,6 +304,8 @@ describe('ReactCompositeComponent', function() {
});
it('should warn about `setState` on unmounted components', function() {
spyOn(console, 'error');
var container = document.createElement('div');
document.body.appendChild(container);
@@ -367,17 +370,16 @@ describe('ReactCompositeComponent', function() {
});
var instance = ReactDOM.render(<Component />, container);
instance.setState({value: 1});
expect(console.error.calls.length).toBe(0);
ReactDOM.unmountComponentAtNode(container);
expect(console.error.calls.length).toBe(0);
expect(cbCalled).toBe(false);
});
it('should warn about `setState` in render', function() {
spyOn(console, 'error');
var container = document.createElement('div');
var renderedState = -1;
@@ -425,6 +427,8 @@ describe('ReactCompositeComponent', function() {
});
it('should warn about `setState` in getChildContext', function() {
spyOn(console, 'error');
var container = document.createElement('div');
var renderPasses = 0;
@@ -499,6 +503,8 @@ describe('ReactCompositeComponent', function() {
});
it('should warn when shouldComponentUpdate() returns undefined', function() {
spyOn(console, 'error');
var Component = React.createClass({
getInitialState: function() {
return {bogus: false};
@@ -524,6 +530,8 @@ describe('ReactCompositeComponent', function() {
});
it('should warn when componentDidUnmount method is defined', function() {
spyOn(console, 'error');
var Component = React.createClass({
componentDidUnmount: function() {
},
@@ -659,8 +667,6 @@ describe('ReactCompositeComponent', function() {
parentInstance.setState({flag: true});
expect(parentInstance.state.flag).toBe(true);
expect(console.error.argsForCall.length).toBe(0);
reactComponentExpect(childInstance).scalarContextEqual({foo: 'bar', flag: true});
});
@@ -719,8 +725,6 @@ describe('ReactCompositeComponent', function() {
// We update <Parent /> while <Child /> is still a static prop relative to this update
wrapper.refs.parent.setState({flag: false});
expect(console.error.argsForCall.length).toBe(0);
expect(wrapper.refs.parent.state.flag).toEqual(false);
reactComponentExpect(wrapper.refs.child).scalarContextEqual({flag: false});
@@ -840,8 +844,6 @@ describe('ReactCompositeComponent', function() {
});
expect(parentInstance.state.flag).toBe(true);
expect(console.error.argsForCall.length).toBe(0);
reactComponentExpect(childInstance).scalarContextEqual({foo: 'bar', depth: 0});
});
@@ -1036,6 +1038,8 @@ describe('ReactCompositeComponent', function() {
});
it('should disallow nested render calls', function() {
spyOn(console, 'error');
var Inner = React.createClass({
render: function() {
return <div />;
@@ -1176,8 +1180,6 @@ describe('ReactCompositeComponent', function() {
var div = document.createElement('div');
ReactDOM.render(<Parent><Component /></Parent>, div);
expect(console.error.argsForCall.length).toBe(0);
});
it('should replace state', function() {
@@ -1270,15 +1272,11 @@ describe('ReactCompositeComponent', function() {
});
ReactDOM.render(<Outer><Component /></Outer>, container);
expect(console.error.calls.length).toBe(0);
ReactDOM.render(<Outer />, container);
expect(console.error.calls.length).toBe(0);
});
it('should warn when mutated props are passed', function() {
spyOn(console, 'error');
var container = document.createElement('div');